Как сформировать печатную форму Microsoft Word из макета в управляемом приложении 1С?

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

При разработке внешних печатных форм и обработок для управляемого приложения (1С:Предприятие 8.3) разработчики часто сталкиваются со спецификой клиент-серверной архитектуры. Классический код для обычных форм, где макет Word типа ActiveDocument получался и открывался напрямую, в тонком клиенте вызывает критические ошибки.

Разберем типичные ошибки, проанализируем их причины и рассмотрим правильные варианты реализации печатных форм MS Word.

Анализ типовых ошибок при работе с макетами Word

Рассмотрим две наиболее распространенные проблемы, с которыми сталкиваются при попытке сгенерировать документ Word:

  1. Ошибка отображения типов: «Отсутствует отображение для типа 'ОболочкаActiveDocument'».
    Данная ошибка возникает, когда макет в конфигурации или внешней обработке создан с типом Active document, и разработчик пытается вернуть объект макета из серверной функции на клиент (или поместить его в ВременноеХранилище). Тип ОболочкаActiveDocument не сериализуется через XDTO и не может передаваться по контексту между сервером и клиентом.
  2. Ошибка получения объекта COM: «Класс не зарегистрирован» (-2147221164 / 0x80040154).
    Попытка перенести всю работу с COM-объектом (COMОбъект("Word.Application") или ПолучитьCOMОбъект()) на сторону сервера приводит к сбою, если на сервере 1С не установлен офисный пакет Microsoft Office. На серверных машинах установка офисных приложений зачастую запрещена политиками безопасности или невозможна из-за отсутствия лицензий. Кроме того, создание COM-объектов на 64-разрядном сервере 1С требует 64-битных версий библиотек Office.

Правильная схема работы: макет «Двоичные данные» и заполнение на клиенте

Для гарантированной работы печатной формы в клиент-серверной базе без установки Microsoft Office на сервере разберем по шагам правильную цепочку действий:

  1. Тип макета: В свойствах макета обработки или документа обязательно выбираем тип Двоичные данные (Binary Data), загружая файл шаблона с расширением .doc, .docx или .dot.
  2. Серверная часть: Получаем макет как объект типа ДвоичныеДанные и помещаем его во временное хранилище с привязкой к уникальному идентификатору текущей формы.
  3. Клиентская часть: Получаем двоичные данные из временного хранилища, сохраняем их во временный файл на локальном диске пользователя через ПолучитьИмяВременногоФайла().
  4. COM-автоматизация на клиенте: Создаем COM-объект Word на клиентском компьютере, открываем созданный временный файл, заполняем параметры и делаем окно видимым для пользователя.

Посмотрим на пример правильной программной реализации в модуле формы обработки:


&НаКлиенте
Процедура СформироватьДоговор(Команда)
    
    // Получаем адрес макета из временного хранилища на сервере
    АдресХранилища = ПодготовитьМакетНаСервере();
    Если Не ЗначениеЗаполнено(АдресХранилища) Тогда
        Возврат;
    КонецЕсли;
    
    // Попытка инициализации COM-объекта на стороне клиента
    Попытка
        WordОбъект = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("Не удалось запустить Microsoft Word на клиентском компьютере: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        Возврат;
    КонецПопытки;
    
    // Извлекаем двоичные данные макета и сохраняем во временный файл на клиенте
    ДвоичныеДанныеМакета = ПолучитьИзВременногоХранилища(АдресХранилища);
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
    ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
    
    Попытка
        // Открываем документ на основе сохраненного файла шаблона
        ДокументWord = WordОбъект.Documents.Add(ИмяВременногоФайла);
        
        // Выполняем замену текстовых маркеров/параметров
        ПоискИЗамена = ДокументWord.Content.Find;
        ПоискИЗамена.Execute("<НомерДоговора>", Ложь, Истина, Ложь, Ложь, , Истина, , Ложь, "123/2024", 2);
        ПоискИЗамена.Execute("<Контрагент>", Ложь, Истина, Ложь, Ложь, , Истина, , Ложь, "ООО ""Торговый Дом""", 2);
        
        // Отображаем заполненный документ пользователю
        WordОбъект.Application.Visible = Истина;
        WordОбъект.Activate();
    Исключение
        WordОбъект.Quit();
        WordОбъект = Неопределено;
        УдалитьФайлы(ИмяВременногоФайла);
        ВызватьИсключение "Ошибка при заполнении шаблона Word: " + ОписаниеОшибки();
    КонецПопытки;
    
    // Удаляем временный файл шаблона после открытия в Word
    УдалитьФайлы(ИмяВременногоФайла);

КонецПроцедуры

&НаСервере
Функция ПодготовитьМакетНаСервере()
    
    // Получаем объект внешней обработки или конфигурации
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    
    // Макет в дереве метаданных должен иметь тип "Двоичные данные"
    ДвоичныеДанныеМакета = ОбработкаОбъект.ПолучитьМакет("МакетДоговора");
    
    // Привязываем адрес к уникальному идентификатору формы, чтобы данные очистились при закрытии
    АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеМакета, УникальныйИдентификатор);
    
    Возврат АдресХранилища;

КонецФункции

Важные технические нюансы и оптимизация

Рассмотрим детали, которые помогут избежать утечек памяти и нестабильной работы:

  1. Уникальный идентификатор формы: При вызове метода ПоместитьВоВременноеХранилище() вторым параметром всегда передавайте УникальныйИдентификатор текущей управляемой формы (а не создавайте Новый УникальныйИдентификатор()). Это гарантирует автоматическое освобождение памяти на сервере после закрытия окна формы.
  2. Очистка процессов WINWORD.EXE: Если в блоке модификации документа произойдет программная ошибка, фоновый процесс Microsoft Word останется висеть в памяти. Обязательно используйте конструкцию Попытка ... Исключение, вызывая WordОбъект.Quit() и обнуляя переменную WordОбъект = Неопределено при возникновении сбоя.
  3. Ускорение обработки: Если шаблон содержит много параметров, отключите обновление экрана перед заменой текста с помощью WordОбъект.ScreenUpdating = Ложь, а параметр Visible = Истина включайте строго в самом конце.
  4. Ограничения веб-клиента и других ОС: COM-автоматизация работает исключительно в среде Windows под тонким или толстым клиентом. Если пользователи работают через веб-клиент или операционные системы Linux / macOS, COM-объекты использовать нельзя.

Альтернативные способы формирования печатных форм Word

Разберем варианты, когда COM-объект не подходит или нежелателен в архитектуре:

  1. Подсистема печати БСП (Библиотека стандартных подсистем): Если конфигурация построена на базе БСП, рекомендуется использовать встроенный механизм печати по офисным шаблонам. Он поддерживает форматы DOCX/ODT, автоматически заполняет одиночные поля, списки и таблицы, и корректно работает через механизмы БСП.
  2. Формирование DOCX через ZIP и XML на сервере: Файл .docx представляет собой ZIP-архив с файлами разметки XML. С помощью встроенных объектов 1С ЧтениеZipФайла, ЗаписьZipФайла и ЧтениеXML можно распаковать шаблон на сервере, заменить теги внутри файла word/document.xml и запаковать обратно. Этот метод работает на любой операционной системе (включая серверный Linux) и не требует установленного Microsoft Office.
  3. Штатный экспорт Табличного документа в DOCX: Если печатную форму можно нарисовать в стандартном табличном макете 1С, для сохранения в Word достаточно штатного вызова ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.DOCX).
← На главную