Форум программистов, компьютерный форум, киберфорум
Rius
Войти
Регистрация
Восстановить пароль
Рейтинг: 5.00. Голосов: 1.

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

Запись от Rius размещена 01.09.2016 в 20:47
Обновил(-а) Rius 01.09.2016 в 21:34
Метки 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.
Размещено в C# .Net
Просмотров 950 Комментарии 2
Всего комментариев 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 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.