Форум программистов, компьютерный форум, киберфорум
Rius
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

Вывод текста в шаблоны формата *.docx

Запись от Rius размещена 01.09.2016 в 20:47
Показов 3714 Комментарии 2
Метки docx, ms word, report, отчет

Исходники тут: https://github.com/riuson/wordml-templates
  1. Добавляем к проекту пакет DocumentFormat.OpenXML через NuGet;
  2. Рисуем оставшуюся часть совы.

Определяем класс для пары закладки. Начало закладки и её конец - это отдельные ноды в XML документе.
При создании шаблона необходимо, чтобы эти ноды находились внутри одной вышележащей ноды. Т.е. чтобы закладка покрывала только текстовую строку и не выходила за пределы своего контейнера.
C#
1
2
3
4
5
6
7
8
9
10
11
        public class BookmarksPair
        {
            public BookmarkStart Start { get; private set; }
            public BookmarkEnd End { get; private set; }
 
            public BookmarksPair(BookmarkStart start, BookmarkEnd end)
            {
                this.Start = start;
                this.End = end;
            }
        }
Получаем закладки из файла:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        public static BookmarksPair[] GetBookmarks(string filename)
        {
            var templateFile = new FileInfo(filename);
 
            if (templateFile.Exists)
            {
                using (var documentStream = templateFile.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
                {
                    using (var document = WordprocessingDocument.Open(documentStream, true))
                    {
                        var bookmarks = GetBookmarks(document.MainDocumentPart, "").ToArray();
                        return bookmarks;
                    }
                }
            }
 
            return new BookmarksPair[] { };
        }
 
        private static IEnumerable<BookmarksPair> GetBookmarks(MainDocumentPart documentPart, string prefix)
        {
            var starts = documentPart.Document.Descendants<BookmarkStart>();
            var ends = documentPart.Document.Descendants<BookmarkEnd>();
 
            var result = from start in starts
                         join end in ends on (string)start.Id equals (string)end.Id
                         where ((string)start.Name).StartsWith(prefix)
                         where start.Parent == end.Parent // Закладки, находящиеся внутри общего элемента
                         select new BookmarksPair(start, end);
            return result;
        }
Эти закладки можно просмотреть и что-то придумать. Но, в общем-то, получать их отдельно не обязательно.

Далее снова открываем документ, собираем закладки, выбираем из них одну подходящую и заменяем.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        public static void ReplaceAndSave(string filenameSource, string filenameDestination, string bookmarkName, string value)
        {
            var templateFile = new FileInfo(filenameSource);
 
            if (templateFile.Exists)
            {
                var tempFile = templateFile.CopyTo(Path.GetTempFileName(), true);
 
                using (var documentStream = tempFile.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
                {
                    using (var document = WordprocessingDocument.Open(documentStream, true))
                    {
                        var bookmarks = GetBookmarks(document.MainDocumentPart, "");
 
                        BookmarksPair pair = bookmarks.FirstOrDefault(x => x.Start.Name == bookmarkName);
 
                        if (pair != null)
                        {
                            ReplaceBookmarkContent(pair, value);
                        }
 
                    }
                }
 
                tempFile.MoveTo(filenameDestination);
            }
        }
 
        private static void ReplaceBookmarkContent(BookmarksPair bookmarksPair, string value)
        {
            CleanContentBetweenBookmarks(bookmarksPair);
 
            Run run = new Run(new Text(value));
 
            bookmarksPair.Start.InsertAfterSelf(run);
        }
 
        private static void CleanContentBetweenBookmarks(BookmarksPair bookmarksPair)
        {
            List<OpenXmlElement> elements = new List<OpenXmlElement>();
            OpenXmlElement element = bookmarksPair.Start.NextSibling();
 
            while (element != null)
            {
                if (element == bookmarksPair.End) break;
 
                elements.Add(element);
 
                element = element.NextSibling();
            }
 
            foreach (var item in elements)
            {
                item.Remove();
            }
        }
Заметка и исходники, может быть , будут дополняться. По мере наличия свободного времени.
Поэтому исходники на GitHub, под VCS.
Метки docx, ms word, report, отчет
Размещено в C# .Net
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 2
Комментарии
  1. Старый комментарий
    Аватар для andalit
    Спасибо большущее, буду разбирать, очень много интересного в этом примере,
    как называется public BookmarkEnd End { get; private set; } - делегат ? его назначение не совсем понятно (там где get set) не в это примере а вообще.
    tableLayoutPanel - вот то что я искал что бы выставить свойства Anchor, а то таблицы расплываются при разворачивании окна.
    и как я понял этот пример работает в 2 потока 1н на контролы, 2й - на Replacer.cs
    а то столкнулся с глюками в виде тормозов если все делать в Form1.cs надо как то делегатами методы обновления таблиц распихать.
    Запись от andalit размещена 02.09.2016 в 17:44 andalit вне форума
  2. Старый комментарий
    Аватар для Rius
    BookmarkEnd стоит в конце участка, выделенного закладкой. Нужен для определения этого участка при его очистке перед вставкой нужного текста.

    Поток один - GUI.
    Запись от Rius размещена 02.09.2016 в 17:52 Rius вне форума
 
Новые блоги и статьи
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru