Работа с печатными формами в формате Microsoft Word — стандартная задача для многих корпоративных систем. Однако разработчики часто сталкиваются с тем, что штатные механизмы Библиотеки Стандартных Подсистем (БСП), такие как УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента, работают крайне медленно. Формирование одного документа может занимать от 5 до 20 секунд, что неприемлемо при массовой печати. В этой статье мы подробно разберем, почему это происходит, и рассмотрим проверенные способы ускорения процесса.
Для начала проанализируем ситуацию и поймем, как 1С взаимодействует с файлами Word. Существует два принципиально разных подхода, которые часто путают:
.doc). 1С запускает экземпляр Word в фоновом режиме и через программный интерфейс передает команды поиска и замены. Это самый медленный способ, так как он зависит от скорости работы самого приложения Word и ресурсов системы..docx не используют COM. Файл .docx — это ZIP-архив, внутри которого находятся XML-файлы с текстом и разметкой. 1С распаковывает этот архив, правит XML и упаковывает обратно.Основная потеря времени в БСП происходит на этапе многократной распаковки/запаковки архива и тяжеловесного анализа XML-структуры при каждом вызове функции ПрисоединитьОбластьИЗаполнитьПараметры. Выясним, как это можно оптимизировать.
Рассмотрим идею, предложенную опытными разработчиками: зачем каждый раз разбирать макет, если его структура не меняется? Мы можем выполнить инициализацию макета один раз, получить его внутреннюю структуру в виде XML и сохранить её. В дальнейшем вместо вызова тяжелой функции УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента, мы будем работать с уже готовой «заготовкой».
Посмотрим на логику реализации этого метода:
// Пример логики кэширования (псевдокод)
Функция ПолучитьПодготовленныйМакет(ИмяМакета)
Кэш = ПолучитьИзВременногоХранилища(АдресКэша);
Если Кэш = Неопределено Тогда
// Первый запуск: инициализируем стандартно
ДанныеМакета = УправлениеПечатью.МакетПечатнойФормы(ИмяМакета);
МакетОфисногоДокумента = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДанныеМакета, "docx");
// Сохраняем структуру (XML-строки) в кэш или справочник
Кэш = МакетОфисногоДокумента.Структура;
ПоместитьВоВременноеХранилище(Кэш, АдресКэша);
КонецЕсли;
Возврат Кэш;
КонецФункции
Этот метод позволяет сократить время подготовки макета на 50-60%, так как исключается стадия первичного анализа двоичных данных и разбора ZIP-архива при каждой итерации печати.
Часто причиной замедления поиска параметров в Word является специфика самого редактора. Когда вы пишете параметр вида {v8 ИмяПараметра}, Word может незаметно для вас вставить внутрь этого текста служебные теги (например, тег проверки орфографии или изменения шрифта). В итоге в XML-файле вместо одной строки получается нечто вроде {v8 ИмяПараметра}.
Рассмотрим, как правильно готовить шаблон:
Это гарантирует, что БСП найдет тег мгновенно простым поиском по строке, не тратя ресурсы на сложный регулярный разбор фрагментированного XML.
Проанализируем альтернативный путь. Если задача стоит в выводе сложной таблицы с множеством строк, механизм ПрисоединитьОбластьИЗаполнитьПараметры будет работать в цикле крайне долго. Вместо этого можно формировать документ в формате HTML.
Word отлично открывает файлы .html и .mht (веб-архивы), сохраняя форматирование и таблицы. Сборка текстовой строки HTML в 1С происходит практически мгновенно. После формирования файла его можно программно сохранить с расширением .doc, и пользователь даже не заметит разницы при открытии.
// Сборка HTML строки
ТекстHTML = "<html><body><table>";
Для Каждого СтрокаДанных Из ТаблицаЦикла Цикл
ТекстHTML = ТекстHTML + "<tr><td>" + СтрокаДанных.Значение + "</td></tr>";
КонецЦикла;
ТекстHTML = ТекстHTML + "</table></body></html>";
// Сохранение во временный файл
ПутьКФайлу = ПолучитьИмяВременногоФайла("doc"); // Расширение doc, хотя внутри HTML
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(ТекстHTML);
ТекстовыйДокумент.Записать(ПутьКФайлу, КодировкаТекста.UTF8);
Поскольку БСП активно работает с файловой системой (распаковывает макет во временную папку пользователя), узким местом может стать дисковая подсистема. Даже быстрые NVMe SSD иногда не справляются с потоком мелких операций чтения-записи временных файлов.
Выясним, как это ускорить программно-аппаратным способом. Перенос папки временных файлов (%TEMP%) пользователя, под которым работает сервер 1С или клиент, на RAM-диск (виртуальный диск в оперативной памяти), дает колоссальный прирост. Время отклика при работе с ZIP-структурой документа сокращается до минимума.
Для самых высоконагруженных систем (например, формирование сотен договоров в минуту) стандартные средства 1С могут быть недостаточно быстры. В этом случае стоит рассмотреть использование внешних компонент (Native API), написанных на C++ или использующих библиотеку Open XML SDK.
Такие компоненты позволяют модифицировать содержимое document.xml прямо в оперативной памяти без промежуточного сохранения на диск. Это самый сложный в реализации, но и самый производительный метод, который часто применяется в крупных внедрениях на Linux-серверах, где COM-объекты Microsoft Word недоступны в принципе.
Подводя итог, выберем стратегию в зависимости от ваших трудозатрат:
ИнициализироватьМакетОфисногоДокумента в цикле.Помните, что формат MXL всегда будет работать быстрее Word, и если есть возможность убедить заказчика перенести шаблон в табличный документ 1С (используя метод «подложки» в виде картинки для сохранения точности разметки), это будет лучшим архитектурным решением для производительности системы.