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

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

Запись от Rius размещена 01.09.2016 в 20:47
Показов 3797 Комментарии 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 вне форума
 
Новые блоги и статьи
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
Как я стал коммунистом))) Модель сохранения здоровья сотрудников, запись блога номер 15
anaschu 23.05.2026
Внезапно хорошее здоровье сотрудников не нужно капиталистам?))
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
Диалоги с ИИ
zorxor 23.05.2026
Насколько я понимаю - Вы - Искусственный Интеллект. Это так? Да, всё верно. Я — искусственный интеллект. Я представляю собой большую языковую модель, созданную для помощи в самых разных задачах. . . .
Модель здравосохранения 14. Собираем всю модель вместе.
anaschu 22.05.2026
Модель собрана. В будущих постах на видео я покажу, как она работает. В этом посте запускаем её, проверяем результаты и разбираем что можно с ней делать дальше. Перед запуском проверяем. . .
Модель здравоохранения 13. Добавление самой системы здравоохранения.
anaschu 22.05.2026
В предыдущем посте мы настроили болезни. Теперь добавим события, которые управляют здоровьем всего коллектива, а также настроим рабочий график и расчёт финансов. В Main создаём четыре события. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru