При разработке внешних печатных форм для типовых конфигураций на обычных формах (в частности, 1С:Управление производственным предприятием) нередко возникает задача формировать кадровые приказы, договоры или акты в виде документов Microsoft Word. Типовой механизм подсистемы печати ожидает на выходе табличный документ. Если попытаться вернуть созданный COM-объект Word или открытый макет напрямую в вызывающую процедуру, платформа выдает критическую ошибку.
Разберем, почему возникает сбой, как правильно вернуть управление типовой подсистеме и какие нюансы следует учитывать при интеграции с MS Word через COM-соединение.
Рассмотрим типовую ситуацию: разработчик внедряет шаблон документа Word в обработку в виде макета ActiveDocument, подключается к офисному приложению, производит замену закладок или параметров и передает полученный объект обратно в процедуру печати. В результате в окне сообщений появляется исключение:
{ОбщийМодуль.УниверсальныеМеханизмы.Модуль(827)}: Поле объекта не обнаружено (КоличествоЭкземпляров)
ПечДокумент.КоличествоЭкземпляров = КоличествоЭкземпляров;
Выясним причину такого поведения. Типовой модуль УниверсальныеМеханизмы в УПП спроектирован для вывода отчетов на базе объекта ТабличныйДокумент. Получив результат выполнения экспортной функции печати из внешней обработки, подсистема сразу пытается применить параметры страницы и печати (например, свойства КоличествоЭкземпляров, ПолеСлева, ОриентацияСтраницы). Поскольку COM-объект Word или открытый документ ActiveDocument такими свойствами платформы 1С не обладает, генерируется ошибка обращения к несуществующему полю.
Для корректной работы достаточно перенести ответственность за отображение документа на сам код внешней печатной формы, а механизму УПП вернуть значение Неопределено. Когда типовая процедура печати видит, что результат равен Неопределено, она считает, что обработка самостоятельно выполнила все необходимые действия (печать или открытие окна пользователю), и прекращает дальнейшую обработку табличного документа.
Посмотрим на пример правильной структуры экспортной функции печати:
Функция Печать() Экспорт
// Получаем макет ActiveDocument из обработки
Макет = ПолучитьМакет("МакетПриказа");
ДокументWord = Макет.Получить();
// Заполняем параметры шаблона
// ... логика подстановки данных ...
// Делаем окно MS Word видимым для пользователя
ДокументWord.Application.Visible = Истина;
ДокументWord.Activate();
// Сигнализируем типовому механизму, что табдок выводить не нужно
Возврат Неопределено;
КонецФункции
При использовании макетов ActiveDocument напрямую через метод Получить() нередко блокируется сам внедренный макет обработки. Надежнее и безопаснее выгружать шаблон во временный файл, открывать его через приложение Word и сохранять под новым именем. Разберем по шагам надежный алгоритм вывода формы.
ПолучитьИмяВременногоФайла("docx").Word.Application с обязательной обработкой исключений.Application.DisplayAlerts = 0, чтобы избежать зависания процесса на скрытых диалоговых окнах Word.Application.Visible = Истина.Возврат Неопределено;.Посмотрим на программный пример с обработкой ошибок:
Функция СформироватьПриказ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С:
COMОбъект("Word.Application") должно выполняться строго на стороне клиента. На сервере 1С вызывать офисные приложения запрещено: это нарушает лицензионную политику Microsoft и приводит к зависанию системных процессов в сессиях сервисов Windows.WINWORD.EXE: если при формировании файла произойдет ошибка до строки включения видимости окна, а блок Исключение не содержит метода Quit(), процесс Word останется в памяти в скрытом виде. Регулярное возникновение ошибок в коде без очистки COM-объекта быстро приводит к исчерпанию оперативной памяти на компьютере пользователя.Если на рабочих местах пользователей установлены разные версии офисных пакетов (или используется свободное ПО), можно рассмотреть альтернативные решения без применения COM-объектов:
ТабличныйДокумент и сохранить его через метод Записать(ИмяФайла, ТипФайлаТабличногоДокумента.DOCX) или в формате HTML. Этот способ не требует установленного MS Office, однако имеет ограничения по сложному позиционированию колонтитулов и шапок с графическими логотипами..docx представляет собой ZIP-контейнер. Шаблон можно поместить в макет как двоичные данные, распаковать методами ЧтениеZIPФайла, заменить текстовые маркеры непосредственно в файле word/document.xml, собрать архив обратно через ЗаписьZIPФайла и запустить файл системной ассоциацией через ЗапуститьПриложение(). Такой подход работает во много раз быстрее COM-соединения и полностью изолирован от офисного пакета на этапе генерации.com.sun.star.ServiceManager, что позволяет формировать документы в форматах DOCX и ODT.