Как реализовать внешнюю печатную форму в формате Word без ошибок в 1С:УПП?

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

При разработке внешних печатных форм для типовых конфигураций на обычных формах (в частности, 1С:Управление производственным предприятием) нередко возникает задача формировать кадровые приказы, договоры или акты в виде документов Microsoft Word. Типовой механизм подсистемы печати ожидает на выходе табличный документ. Если попытаться вернуть созданный COM-объект Word или открытый макет напрямую в вызывающую процедуру, платформа выдает критическую ошибку.

Разберем, почему возникает сбой, как правильно вернуть управление типовой подсистеме и какие нюансы следует учитывать при интеграции с MS Word через COM-соединение.

Анализ ошибки подсистемы печати

Рассмотрим типовую ситуацию: разработчик внедряет шаблон документа Word в обработку в виде макета ActiveDocument, подключается к офисному приложению, производит замену закладок или параметров и передает полученный объект обратно в процедуру печати. В результате в окне сообщений появляется исключение:


{ОбщийМодуль.УниверсальныеМеханизмы.Модуль(827)}: Поле объекта не обнаружено (КоличествоЭкземпляров)
    ПечДокумент.КоличествоЭкземпляров = КоличествоЭкземпляров;

Выясним причину такого поведения. Типовой модуль УниверсальныеМеханизмы в УПП спроектирован для вывода отчетов на базе объекта ТабличныйДокумент. Получив результат выполнения экспортной функции печати из внешней обработки, подсистема сразу пытается применить параметры страницы и печати (например, свойства КоличествоЭкземпляров, ПолеСлева, ОриентацияСтраницы). Поскольку COM-объект Word или открытый документ ActiveDocument такими свойствами платформы 1С не обладает, генерируется ошибка обращения к несуществующему полю.

Решение проблемы: возврат Неопределено

Для корректной работы достаточно перенести ответственность за отображение документа на сам код внешней печатной формы, а механизму УПП вернуть значение Неопределено. Когда типовая процедура печати видит, что результат равен Неопределено, она считает, что обработка самостоятельно выполнила все необходимые действия (печать или открытие окна пользователю), и прекращает дальнейшую обработку табличного документа.

Посмотрим на пример правильной структуры экспортной функции печати:


Функция Печать() Экспорт

    // Получаем макет ActiveDocument из обработки
    Макет = ПолучитьМакет("МакетПриказа");
    ДокументWord = Макет.Получить();
    
    // Заполняем параметры шаблона
    // ... логика подстановки данных ...

    // Делаем окно MS Word видимым для пользователя
    ДокументWord.Application.Visible = Истина;
    ДокументWord.Activate();

    // Сигнализируем типовому механизму, что табдок выводить не нужно
    Возврат Неопределено;

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

Пошаговая реализация печати через COM и временные файлы

При использовании макетов ActiveDocument напрямую через метод Получить() нередко блокируется сам внедренный макет обработки. Надежнее и безопаснее выгружать шаблон во временный файл, открывать его через приложение Word и сохранять под новым именем. Разберем по шагам надежный алгоритм вывода формы.

  1. Создание временного файла: получаем имя во временном каталоге с помощью метода ПолучитьИмяВременногоФайла("docx").
  2. Запись макета на диск: извлекаем двоичные данные шаблона и сохраняем файл на рабочую станцию пользователя.
  3. Инициализация COM-объекта: запускаем экземпляр Word.Application с обязательной обработкой исключений.
  4. Отключение предупреждений: устанавливаем свойство Application.DisplayAlerts = 0, чтобы избежать зависания процесса на скрытых диалоговых окнах Word.
  5. Заполнение и отображение: заменяем параметры или метки в тексте, после чего включаем видимость Application.Visible = Истина.
  6. Возврат значения: завершаем функцию строкой Возврат Неопределено;.

Посмотрим на программный пример с обработкой ошибок:


Функция СформироватьПриказWord() Экспорт

    ВспомогательныйФайл = ПолучитьИмяВременногоФайла("docx");
    ДвоичныеДанныеШаблона = ПолучитьМакет("ШаблонПриказа");
    ДвоичныеДанныеШаблона.Записать(ВспомогательныйФайл);

    Попытка
        ПриложениеWord = Новый COMОбъект("Word.Application");
    Исключение
        Предупреждение("Не удалось запустить Microsoft Word. Проверьте установку офисного пакета.");
        Возврат Неопределено;
    КонецПопытки;

    // Блокируем показ системных предупреждений офиса
    ПриложениеWord.DisplayAlerts = 0;

    Попытка
        Документ = ПриложениеWord.Documents.Open(ВспомогательныйФайл);

        // Пример замены закладок или меток
        // Документ.Content.Find.Execute("[НомерПриказа]", , , , , , , , , "123-к", 2);

        // Показываем готовый документ пользователю
        ПриложениеWord.Visible = Истина;
        Документ.Activate();
    Исключение
        // В случае ошибки принудительно закрываем фоновый процесс
        ПриложениеWord.Quit();
        ПриложениеWord = Неопределено;
        ВызватьИсключение "Ошибка при заполнении документа Word: " + ОписаниеОшибки();
    КонецПопытки;

    Возврат Неопределено;

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

Важные технические ограничения

Проанализируем технические нюансы, с которыми сталкиваются разработчики при автоматизации офисных приложений в среде 1С:

  1. Контекст выполнения: создание объекта COMОбъект("Word.Application") должно выполняться строго на стороне клиента. На сервере 1С вызывать офисные приложения запрещено: это нарушает лицензионную политику Microsoft и приводит к зависанию системных процессов в сессиях сервисов Windows.
  2. Конфликт разрядности: при использовании 64-битного клиента 1С и 32-битного Microsoft Office (или наоборот) попытка создания COM-объекта завершится системной ошибкой регистрации класса. В таком случае требуется либо выравнивание разрядности приложений, либо отказ от прямого COM в пользу работы с файлами.
  3. Зависшие процессы WINWORD.EXE: если при формировании файла произойдет ошибка до строки включения видимости окна, а блок Исключение не содержит метода Quit(), процесс Word останется в памяти в скрытом виде. Регулярное возникновение ошибок в коде без очистки COM-объекта быстро приводит к исчерпанию оперативной памяти на компьютере пользователя.

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

Если на рабочих местах пользователей установлены разные версии офисных пакетов (или используется свободное ПО), можно рассмотреть альтернативные решения без применения COM-объектов:

  1. Формирование табличного документа с сохранением: платформа 1С позволяет программно сформировать обычный ТабличныйДокумент и сохранить его через метод Записать(ИмяФайла, ТипФайлаТабличногоДокумента.DOCX) или в формате HTML. Этот способ не требует установленного MS Office, однако имеет ограничения по сложному позиционированию колонтитулов и шапок с графическими логотипами.
  2. Прямая модификация архива DOCX: файл формата .docx представляет собой ZIP-контейнер. Шаблон можно поместить в макет как двоичные данные, распаковать методами ЧтениеZIPФайла, заменить текстовые маркеры непосредственно в файле word/document.xml, собрать архив обратно через ЗаписьZIPФайла и запустить файл системной ассоциацией через ЗапуститьПриложение(). Такой подход работает во много раз быстрее COM-соединения и полностью изолирован от офисного пакета на этапе генерации.
  3. Интеграция с LibreOffice / OpenOffice: при использовании бесплатных офисных пакетов аналогичная схема строится через COM-объект com.sun.star.ServiceManager, что позволяет формировать документы в форматах DOCX и ODT.
← На главную