Как заполнить и открыть шаблон DOCX на сервере 1С без использования COM-объектов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе систем на клиент-серверный режим работы, переносе серверов 1С на операционную систему Linux или организации работы пользователей через веб-клиент разработчики часто сталкиваются с критической ошибкой. Попытка инициализировать MS Word на стороне сервера с помощью конструкции COMОбъект("Word.Application") вызывает аварийное завершение процесса или ошибку отсутствия зарегистрированного COM-класса. Пытаться установить Microsoft Office на серверную ОС — это крайне неэффективный, небезопасный и лицензионно сомнительный путь.

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

Причина проблемы: Почему COMОбъект не должен жить на сервере

Прежде чем перейти к решениям, проанализируем ситуацию. Технология COM (Component Object Model) является Windows-ориентированной. Если ваш сервер 1С работает под управлением Linux, запустить COM-объект физически невозможно. Но даже на Windows-серверах использование MS Office в серверных процессах крайне нерекомендуемо самим разработчиком Microsoft. Это приводит к зависанию процессов WINWORD.EXE в памяти, утечкам оперативной памяти и резкому снижению производительности всей системы 1С при одновременной печати документов несколькими пользователями.

---

Решение 1. Использование встроенных механизмов БСП (Рекомендуемый способ)

Если вы работаете в современной конфигурации, такой как 1С:ЗУП 3.1, 1С:КА или 1С:ERP, вам не нужно изобретать велосипед. В состав БСП уже входит мощная подсистема «Печать», которая умеет работать с офисными макетами (в форматах DOCX и ODT) напрямую. Платформа 1С самостоятельно разбирает структуру файла, заменяет параметры и формирует готовый документ в виде двоичных данных.

Рассмотрим по шагам, как настроить такую печатную форму:

Шаг 1. Подготовка шаблона в MS Word

Вместо привычных квадратных скобок или спецсимволов, БСП использует строгий синтаксис для определения параметров. Откройте ваш договор в Word и укажите плейсхолдеры в следующем формате:

Шаг 2. Загрузка шаблона в 1С

В создаваемой внешней печатной форме (ВПФ) добавьте новый макет. Важно выбрать тип макета Двоичные данные (а не Active Document). Загрузите туда ваш подготовленный файл .docx.

Шаг 3. Программный код заполнения на сервере

В модуле объекта внешней печатной формы пропишем алгоритм формирования документа. Для этого мы обратимся к процедурам общего модуля УправлениеПечатью. Проанализируем пример кода:


Функция СформироватьПечатнуюФормуДоговора(СсылкаНаОбъект, АдресМакета) Экспорт
    
    // Получаем двоичные данные шаблона из макета
    ДвоичныеДанныеМакета = ПолучитьМакет("ДоговорШаблон");
    
    // Инициализируем структуру макета средствами БСП
    ДанныеМакет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, "DOCX");
    Если ДанныеМакет = Неопределено Тогда
        ВызватьИсключение "Не удалось инициализировать макет DOCX!";
    КонецЕсли;
    
    // Инициализируем коллекцию для формирования итогового печатного документа
    ПечатнаяФорма = УправлениеПечатью.ИнициализироватьПечатнуюФорму("DOCX");
    
    // Подготавливаем данные для заполнения полей шаблона
    ДанныеПараметров = Новый Структура;
    ДанныеПараметров.Вставить("СотрудникФИО", СсылкаНаОбъект.Сотрудник.Наименование);
    ДанныеПараметров.Вставить("НомерДоговора", СсылкаНаОбъект.НомерДоговора);
    ДанныеПараметров.Вставить("ДатаДоговора", Формат(СсылкаНаОбъект.ДатаДоговора, "ДЛФ=DD"));
    ДанныеПараметров.Вставить("Оклад", Формат(СсылкаНаОбъект.Оклад, "ЧДЦ=2"));
    
    // Выделяем область "Шапка" из шаблона и присоединяем её с заполнением параметров
    ОбластьШапка = УправлениеПечатью.ОбластьМакетОфисногоДокумента(ДанныеМакет, "Шапка");
    Если ОбластьШапка <> Неопределено Тогда
        УправлениеПечатью.ПрисоединитьОбласть(ПечатнаяФорма, ОбластьШапка, ДанныеПараметров);
    КонецЕсли;
    
    // Сворачиваем временные структуры и получаем готовые двоичные данные файла
    АдресХранилища = УправлениеПечатью.СформироватьДокумент(ПечатнаяФорма);
    
    Возврат АдресХранилища;
КонецФункции

Метод БСП хорош тем, что он автоматически обрабатывает форматирование. Если параметр {v8 СотрудникФИО} в макете был выделен полужирным шрифтом или курсивом, то в итоговом документе подставившееся значение ФИО полностью унаследует это форматирование.

---

Решение 2. Низкоуровневый разбор XML (Подход для любых конфигураций)

Что делать, если в вашей конфигурации нет БСП, или она сильно устарела? Мы можем использовать тот факт, что любой файл формата .docx — это обычный ZIP-архив, внутри которого находятся структурированные XML-файлы. Весь содержательный текст документа, включая наши параметры-метки, хранится в файле по пути word/document.xml.

Рассмотрим по шагам этот алгоритм:

Шаг 1. Маркировка шаблона

В тексте договора укажите плейсхолдеры в простом текстовом формате, например: [ФИО_Сотрудника], [Номер_Договора].

Важная техническая тонкость: Когда вы форматируете документ в Word (делаете слова жирными, меняете шрифты), текстовый процессор разбивает текст внутри XML на мелкие теги (блоки "run" <w:r>). Если вы напишете [ФИО], а потом решите сделать эту надпись жирной, Word может разбить XML-код на части: <w:t>[</w:t><w:t>ФИО</w:t><w:t>]</w:t>. Простая функция СтрЗаменить() в 1С такой тег не найдет. Чтобы избежать этого, создавайте плейсхолдеры в обычном Блокноте и вставляйте их в Word без форматирования отдельных букв внутри самой метки.

Шаг 2. Код распаковки, модификации и упаковки архива в 1С

Для реализации этого метода нам понадобятся стандартные объекты платформы: ЧтениеZipФайла, ЗаписьZipФайла, а также средства работы с текстом.


Функция ЗаполнитьШаблонDocxЧерезXML(ДвоичныеДанныеШаблона, СоответствиеПараметров) Экспорт
    
    // Создаем уникальные имена временных файлов
    ИмяВременногоАрхива = ПолучитьИмяВременногоФайла("zip");
    ДвоичныеДанныеШаблона.Записать(ИмяВременногоАрхива);
    
    КаталогРаспаковки = ПолучитьИмяВременногоФайла("");
    СоздатьКаталог(КаталогРаспаковки);
    
    // Распаковываем DOCX-архив во временный каталог
    Архив = Новый ЧтениеZipФайла(ИмяВременногоАрхива);
    Архив.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
    Архив.Закрыть();
    
    // Текст документа лежит в файле word/document.xml
    ПутьКФайлуXML = КаталогРаспаковки + "/word/document.xml";
    ФайлXML = Новый Файл(ПутьКФайлуXML);
    
    Если Не ФайлXML.Существует() Тогда
        ВызватьИсключение "Неверная структура офисного документа DOCX!";
    КонецЕсли;
    
    // Читаем содержимое XML в строку
    ЧтениеТекста = Новый ЧтениеТекста(ПутьКФайлуXML, КодировкаТекста.UTF8);
    ТекстДокумента = ЧтениеТекста.Прочитать();
    ЧтениеТекста.Закрыть();
    
    // Производим замену наших плейсхолдеров реальными данными
    Для Каждого Параметр Из СоответствиеПараметров Цикл
        Метка = "[" + Параметр.Ключ + "]";
        Значение = Строка(Параметр.Value); // Предотвращаем падение на нестроковых типах
        
        // Заменяем спецсимволы XML для безопасности данных
        Значение = СтрЗаменить(Значение, "&", "&");
        Значение = СтрЗаменить(Значение, "<", "<");
        Значение = СтрЗаменить(Значение, ">", ">");
        
        ТекстДокумента = СтрЗаменить(ТекстДокумента, Метка, Значение);
    КонецЦикла;
    
    // Записываем обновленный XML обратно
    ЗаписьТекста = Новый ЗаписьТекста(ПутьКФайлуXML, КодировкаТекста.UTF8);
    ЗаписьТекста.Записать(ТекстДокумента);
    ЗаписьТекста.Закрыть();
    
    // Упаковываем файлы обратно в DOCX
    ИмяНовогоФайлаDocx = ПолучитьИмяВременногоФайла("docx");
    
    Архиватор = Новый ЗаписьZipФайла(ИмяНовогоФайлаDocx);
    Архиватор.Добавить(КаталогРаспаковки + "/*", РежимСохраненияПутейФайловZIP.СохранятьОтносительныеПути, РежимСжатияZIP.Максимальный);
    Архиватор.Записать();
    
    // Очищаем временные папки и файлы архива
    УдалитьФайлы(ИмяВременногоАрхива);
    УдалитьФайлы(КаталогРаспаковки);
    
    // Получаем результирующие двоичные данные
    Результат = Новый ДвоичныеДанные(ИмяНовогоФайлаDocx);
    УдалитьФайлы(ИмяНовогоФайлаDocx);
    
    Возврат Результат;
    
КонецФункции

Этот способ работает невероятно быстро, полностью независим от внешних программных библиотек и стабильно функционирует на любой операционной системе (Windows, Linux, macOS).

---

Как передать и открыть готовый документ пользователю?

После того как на сервере сгенерированы двоичные данные файла договора, нам необходимо вернуть их на клиент и запустить просмотр у пользователя. Проанализируем, как правильно передать управление на клиентскую сторону:


&НаКлиенте
Процедура СформироватьИОткрытьДоговор()
    
    // Получаем заполненный файл во временном хранилище
    АдресФайлаВоВременномХранилище = ПолучитьФайлДоговораНаСервере();
    
    Если ЗначениеЗаполнено(АдресФайлаВоВременномХранилище) Тогда
        
        // Описываем имя локального файла на клиенте
        ИмяФайлаНаКлиенте = ПолучитьИмяВременногоФайла("docx");
        
        // Скачиваем двоичные данные из хранилища на диск пользователя
        ПолучитьФайл(АдресФайлаВоВременномХранилище, ИмяФайлаНаКлиенте, Ложь);
        
        // Открываем документ ассоциированным приложением (MS Word, LibreOffice, ОС-просмотрщик)
        ЗапуститьПриложение(ИмяФайлаНаКлиенте);
        
    КонецЕсли;
    
КонецПроцедуры

Используя конструкцию ЗапуститьПриложение(ИмяФайла), платформа 1С автоматически откроет созданный файл DOCX в текстовом редакторе, установленном по умолчанию на компьютере пользователя. Сервер при этом остается разгруженным и безопасным.

Резюме

Мы проанализировали основные подходы к замене технологии COM в 1С. Использование подсистемы печати БСП является наиболее простым и предпочтительным решением для типовых конфигураций 1С v8.3. В случаях, когда требуется максимальная скорость работы или используется нетиповая архитектура, отличным выбором будет прямая работа со структурой ZIP/XML файла шаблона. Оба этих метода гарантируют стабильную работу базы данных 1С в режиме 24/7 на любых операционных системах.

← На главную