При разработке печатных форм часто возникает задача сформировать документ Microsoft Word (DOCX), содержащий сложную иерархическую структуру: произвольный список клиентов, внутри каждого из которых выводятся отдельные пункты, подпункты и динамические таблицы с произвольным количеством строк. Рассмотрим, как решить эту задачу в 1С, какие возможности и ограничения есть у подсистемы печати БСП, и какие альтернативные подходы можно применить на практике.
Среди разработчиков распространено заблуждение, что шаблон Microsoft Word в 1С жестко ограничен и не позволяет многократно выводить одну и ту же область. На самом деле подсистема «Печать» Библиотеки стандартных подсистем (БСП) позволяет циклически обращаться к областям макета и выводить их столько раз, сколько требуется. Вы можете описать шаблон для одного клиента и вызывать его заполнение в цикле для каждого элемента выборки данных.
Однако разберем важное архитектурное ограничение: разметка областей в шаблонах DOCX для БСП реализуется с помощью механизма комментариев (Word Comments), выделяющих параграфы или строки таблиц. Метод УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры ориентирован на последовательный вывод областей — либо списка абзацев, либо строк одной конкретной таблицы. Полноценная динамическая вложенность (когда для каждого клиента сначала выводится блок описания, затем таблица с произвольным числом строк, а после нее — список подпунктов) требует комбинирования нескольких областей или прямой модификации внутреннего содержимого шаблона.
Рассмотрим подход, позволяющий динамически дублировать и заполнять фрагменты внутри макета БСП. Шаблон DOCX представляет собой ZIP-архив с XML-файлами, где основной текст и таблицы хранятся в word/document.xml. Мы можем разметить повторяющиеся блоки специальными метками в шаблоне, а затем программно модифицировать XML-текст области перед окончательным выводом.
Посмотрим на пример кода, предложенный участниками обсуждения для манипуляции с текстом области:
// Получаем область макета через стандартные механизмы БСП
Область = УправлениеПечатью.ОбластьМакета(Макет, СтруктураОбластей["СтраницаВывода"]);
// Выполняем поиск меток повтора, формируем динамический блок и заменяем разметку
// Метки абзацев в OpenXML представлены тегами <w:p> и </w:p>
Область.Текст = СтрЗаменить(Область.Текст, "[ПовторОбласти1]", ТекстДинамическихДанных);
// Выводим область стандартными средствами подсистемы печати
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(КоллекцияПечатныхФорм, ТаблицаДанных, Область);
При реализации данного подхода проанализируем важную техническую деталь: Microsoft Word при сохранении документа часто разбивает сплошной текст на отдельные узлы <w:r> (run) и <w:t> (text). Это происходит, если при наборе текста менялся язык ввода, шрифт, применялось форматирование или срабатывала встроенная проверка правописания. В результате метка вида [ПовторОбласти1] в итоговом XML может оказаться разбитой на фрагменты [Повтор и Области1], из-за чего простая замена строк в 1С не сработает.
Чтобы избежать этой проблемы при подготовке DOCX-шаблона, выполним следующие рекомендации:
MERGEFIELD) вместо произвольных текстовых скобок. Поля слияния сохраняются в XML как единый неделимый объект платформы Word.Если задача требует произвольного клонирования не только текста, но и сложных вложенных таблиц <w:tbl>, наиболее надежным способом является прямая обработка файла документа средствами платформы 1С:
ЧтениеZipФайла.word/document.xml в объект ДокументDOM или обрабатываем его с помощью объектов ЧтениеXML и ЗаписьXML.<w:p>) и таблиц (<w:tbl>), клонируем их в цикле по клиентам, заполняем дочерние текстовые узлы нужными значениями.ЗаписьZipФайла.Этот метод работает на уровне сервера 1С полностью автономно, не зависит от сторонних программ и корректно выполняется как в среде Windows, так и в Linux.
В вопросе рассматривался вариант использования COM-соединения и скриптов VBA. Разберем, почему данный подход крайне не рекомендуется для современных информационных систем:
Word.Application доступен исключительно в операционной системе Windows при наличии локально установленного пакета Microsoft Office. В серверных средах на базе Linux данный механизм не функционирует.WINWORD.EXE зависают в памяти, приводя к утечкам ресурсов и блокировке работы сервера.Если формат DOCX не является жестким требованием контрагента, проанализируем самый простой и производительный вариант: реализацию печатной формы через стандартный объект ТабличныйДокумент платформы 1С. В макете табличного документа можно легко настроить любую вложенность областей: шапку клиента, циклические строки внутренней таблицы и завершающие подпункты. Сформированный табличный документ можно программно сохранить в формате HTML (который открывается Word как полноценный форматированный документ) либо в PDF штатным методом Записать с указанием соответствующего типа файла.