Формирование документов из макета без использования COM-объекта Word

17 3

Конструктор документов, как он есть

Стандартная поставка системы DIRECTUM содержит полезный механизм "Конструктор документов". При минимуме разработки он формирует типовые и не очень документы из заранее подготовленных т.н. макетов. Макеты представляют собой документы с обозначенными местами для вставки текста. Как это работает: путём нехитрых манипуляций разрабатывается обобщённый макет - шаблон будущих документов. В нужном месте автоматизируемого процесса на основе полученных нужных данных (например, у пользователя в мастере действий) и заранее подготовленного макета прикладная функция GenerateDocument() формирует готовый документ.

Как раз об оптимизации логики формирования документов из макетов и поговорим дальше.

Как работает функция GenerateDocument()?

В функции при помощи COM-объекта Word.Application (ну или Excel.Application) происходят манипуляции с макетом, наполнение его нужными данными. При создании объекта Word.Application происходит запуск процесса WINWORD.EXE, в память загружается документ и происходит обработка.Так вот формирование документа из стандартного макета протокола совещания таким способом на моём рабочем ПК занимает около 5 секунд. А в подавляющем большинстве случаев использования, по требованиям процесса, в прикладных вычислениях по соседству с генерацией выполняются другие затратные по времени операции: создание документа из файла, создание, заполнение и отправка задачи. Кроме этого требуется выполнять поиски, перебирать детальные разделы, делать вынужденные преобразования и т.д., создающие "фон" на свои полсекунды-секунду.

Как быть? Оптимизировать вычисления.

Но есть действия, время и оптимальность выполнения которых не всегда зависит от прикладной разработки. Так, на скорость создания документа на сервере повлияет "ширина канала" до сервера (передаётся тело документа). А для эффективной работы с содержимым документов при формировании документов из макетов приходится использовать тяжёлые офисные COM-объекты - наш случай.

Что-нибудь ещё кроме времени выполнения функции GenerateDocument()? Да. Формирование документов может выполняться на стороне службы workflow и сервере веб-доступа. В некоторых ситуациях операции генерации документов - массовые, сталкивался лично на одном из проектов. И имеют место быть:

  • неидеальная стабильность работы тяжёлых COM-объектов при многочисленных вызовах;
  • необходимость установки пакета MS Office версии 2007 и выше;
  • необходимость первоначальной настройки запуска процессов Word и Excel от конкретного пользователя.

Это вызывает дополнительное беспокойство администратора.

Оптимизируем

Идея оптимизации пришла в голову давно и состоит в следующем: т.к. файлы .docx, по сути, zip-архивы с xml-файлами по формату Office Open XML - работать с документом как с xml-файлом. OpenXML SDK позволяет разработчику с удобством работать с OpenXML, в частности с .docx. Да и работать с xml приятнее в .net, чем используя MSXML. Как для знакомства с форматом OpenXML, так и для глубокого изучения рекомендую сайт openxmldeveloper.org. Там масса полезной информации о формате, примеры кода на разных языках, разбор типовых случаев работы с документами.

Результатом реализации идеи стала COM-библиотека DocXConstructor.dll с простым интерфейсом:

  • вызовом метода AddMacro(string key, string value) в библиотеку передаются наименования макропеременных и значения;
  • метод UpdateMacros(string inputFilePath, string outputFilePath) из макета по пути inputFilePath формируется готовый документ по пути outputFilePath.

Библиотека использует .NET Framevork v.3.5 и OpenXML SDK и повторяет логику работы функции GenerateDocument().

Но есть исключения-ограничения:

  1. В сформированный документ не попадает красный текст МАКРОПЕРЕМЕННАЯ НЕ ОЗНАЧЕНА, если не передано значение макроподстановки. Наверное, такой текст полезен для отладки, но я решил это исключить. Теперь при разработке не требуется передавать пустые строки в качестве значений макропеременных.
  2. Не поддерживается формирование документов Excel (.xlsx). Для формирования таблиц рекомендую использовать генерацию из шаблона. (Коллеги, поделитесь знаниями, возможно ли формирование документов Word как в указанной статье? Скорее всего нет, но я сходу не нашёл чёткого ответа, почему.)

В дополнение к самой библиотеке я написал функцию GenerateDocumentFasterWithMoreEnergy() для работы с DocXConstructor.dll. Функция формирует из макетов только .docx документы или генерирует исключение. Чтобы опробовать работу оптимизированного формирования документов из макетов вместо вызова GenerateDocument(), предварительно проверив расширение файла, вызывайте  GenerateDocumentFasterWithMoreEnergy(), по параметрам они идентичны.

На компьютерах, где документы будут генерироваться из макета по-новому (на сервере workflow и/или на рабочих местах пользователей) распакуйте архив в нужное вам место и запустите register.bat для регистрации библиотеки из папки DocXConstructor. Чтобы разрегистрировать библиотеку запустите unregister.bat. Функция GenerateDocumentFasterWithMoreEnergy() в виде пакета разработки доступна в папке dev архива.

Установленный и настроенный Microsoft Office для работы DocXConstructor.dll не требуется. Это полезно там, где используются отличные от Microsoft Office офисные пакеты.

Исправление пожеланий к решению возможно, но не гарантируется.

Прошу в комментариях оставить мнение о полезности решения. Планируете ли использовать это решение на своих проектах?

Спасибо за внимание.

Приложение

DocXConstructor.zip (1,93 Мб)

Татьяна Филиппова

Интересная статья. А почему не поддерживается генерация .xlsx? 

Еще заметила за OpenXML SDK такой грешок: иногда генерируемый документ отличается от шаблона (в моем случае у некоторых элементов списка пропали маркеры). Вы с таким не сталкивались? 

Дмитрий Пролеев

>> А почему не поддерживается генерация .xlsx? 

на мой взгляд генерация именно из макетов в excel мало используется. Решил не тратить на это время. Ограничений в техническом смысле нет, доделывается быстро.

>> иногда генерируемый документ отличается от шаблона (в моем случае у некоторых элементов списка пропали маркеры). Вы с таким не сталкивались? 

Сталкивался с обратным, что при манипуляциях с документом как с xml-документов всё остаётся всё точно как в макетах, в т.ч. стили (а маркеры это стиль). Я сталкивался с тем, что иногда сбивается стиль при подстановках значений макропеременных через Word.Application (но не нашёл закономерности).

Стандратный маркер помечается  на уровне xml в параграфе. Его можно потерять при манипуляциях со структурой документа, в частности, при копировании. Это самая вероятная причина, считаю.

Михаил Манохин

Считаю что давно пора уходить от использования Com-объектов ворда в сторону OpenXML, да и от "старых" форматов надо полностью избавляться. Нужно допилить Excel и включать в стандартную :)

Авторизуйтесь, чтобы написать комментарий