Как исправить ошибку при формировании внешней печатной формы в MS Word через дополнительные отчеты и обработки?

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

Разработка внешних печатных форм (ВПФ) с использованием Microsoft Word — это классическая задача, с которой сталкиваются многие программисты 1С. Однако часто возникает ситуация, когда обработка прекрасно работает при запуске через Файл — Открыть, но выдает ошибку сразу после регистрации в справочнике Дополнительные отчеты и обработки. Проанализируем ситуацию, выясним причину такого поведения и разберем по шагам правильную архитектуру печатной формы.

Почему возникает ошибка при запуске из справочника?

Основная причина кроется в особенностях работы системы «1С:Предприятие» в клиент-серверном варианте и механизмах Библиотеки стандартных подсистем (БСП). Рассмотрим подробнее, что происходит:

  1. Разделение контекста: Когда вы открываете обработку локально, весь код выполняется в контексте вашего клиентского приложения, где есть доступ к установленному Microsoft Word.
  2. Серверное выполнение: При использовании механизма дополнительных обработок БСП по умолчанию пытается выполнить команду на сервере (режим ВызовСерверногоМетода).
  3. Отсутствие интерфейса на сервере: Служба сервера 1С работает в изолированной «сессии 0», где нет графического интерфейса. Пытаясь создать объект COMОбъект("Word.Application") на сервере, система либо возвращает ошибку «Метод объекта не обнаружен», либо процесс WINWORD.EXE «зависает» в памяти, не имея возможности отобразить окно пользователю.

Для решения этой проблемы нам необходимо перенести ту часть кода, которая взаимодействует с Word, на сторону клиента, оставив подготовку данных на сервере.

Шаг 1. Правильная регистрация команды в модуле объекта

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

Найдем в таблице команд настройку поля Использование. Вместо ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода() необходимо прописать использование клиентского метода:


НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = "Печать договора в Word";
НоваяКоманда.Идентификатор = "ПечатьВорд"; // Имя процедуры в модуле формы
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL";

Шаг 2. Подготовка данных на сервере (Модуль объекта)

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

Разберем пример функции ПечатьМакета:


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

Шаг 3. Реализация клиентской части (Модуль формы)

Теперь выясним, как правильно принять эти данные в форме и открыть Word. В модуле формы должна быть экспортная процедура Печать (или с тем идентификатором, который вы указали при регистрации). Она будет выступать «дирижером» процесса.

Проанализируем структуру кода в модуле формы:


&НаКлиенте
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    
    // 1. Вызываем серверную функцию для подготовки файла
    РезультатПечати = ПодготовитьФайлНаСервере(ОбъектыНазначенияМассив);
    
    Если РезультатПечати = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // 2. Получаем данные из хранилища на клиент
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(РезультатПечати);
    ИмяФайлаНаКлиенте = ПолучитьИмяВременногоФайла(".docx");
    ДвоичныеДанные.Записать(ИмяФайлаНаКлиенте);
    
    // 3. Работаем с COM-объектом непосредственно на клиенте
    Попытка
        WordПриложение = Новый COMОбъект("Word.Application");
        Документы = WordПриложение.Documents;
        // Открываем файл
        НовыйДокумент = Документы.Open(ИмяФайлаНаКлиенте);
        
        // Делаем Word видимым
        WordПриложение.Visible = Истина;
        WordПриложение.Activate();
        
        // Пример заполнения закладок (Bookmarks) на клиенте
        Если НовыйДокумент.Bookmarks.Exists("НомерДоговора") Тогда
            НовыйДокумент.Bookmarks("НомерДоговора").Select();
            WordПриложение.Selection.TypeText("№123-БП");
        КонецЕсли;
        
    Исключение
        Сообщить("Ошибка при работе с Microsoft Word: " + ОписаниеОшибки());
        Если WordПриложение <> Неопределено Тогда
            WordПриложение.Quit();
        КонецЕсли;
    КонецПопытки;

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

&НаСервере
Функция ПодготовитьФайлНаСервере(ОбъектыНазначенияМассив)
    ОбъектОбработка = РеквизитФормыВЗначение("Объект");
    ОбъектыПечати = Новый СписокЗначений;
    Возврат ОбъектОбработка.ПечатьМакета(ОбъектыНазначенияМассив, ОбъектыПечати);
КонецФункции

Устранение типичных проблем

Рассмотрим ситуацию с «двойным открытием» Word, о которой часто упоминают пользователи. Это происходит, когда команда Word.Visible = Истина вызывается несколько раз или когда и на сервере, и на клиенте пытаются инициализировать приложение. Чтобы этого избежать, никогда не используйте COMОбъект внутри серверных процедур модуля объекта в контексте ВПФ. Вся визуализация должна происходить только в конце клиентской процедуры Печать.

Также важно обратить внимание на тип макета. В современных версиях 1С рекомендуется хранить шаблоны Word как Двоичные данные. Это позволяет избежать проблем с попыткой 1С автоматически интерпретировать файл как Active Document в момент получения макета на сервере, что часто приводит к ошибкам прав доступа или несовместимости разрядности (32/64 бит).

Полезный совет: Для более стабильной работы используйте замену параметров в тексте документа через поиск и замену, а не через закладки, если структура документа сложная. Это менее чувствительно к случайному удалению закладок пользователем при редактировании шаблона.

Итоги

Подводя итог, мы проанализировали основные ошибки и выработали надежный алгоритм работы:

  1. Используйте ТипКомандыВызовКлиентскогоМетода в сведениях о ВПФ.
  2. Реализуйте основную логику открытия Word в Модуле формы обработки в процедуре с директивой &НаКлиенте.
  3. Передавайте сформированный файл с сервера на клиент через Временное хранилище в виде двоичных данных.
  4. Не забывайте про обработку исключений (Попытка...Исключение), чтобы в случае ошибки процесс Word не оставался «висеть» в диспетчере задач.

Следуя этой структуре, вы обеспечите стабильную работу печатных форм в любых вариантах развертывания 1С, будь то файловая база или мощный кластер серверов.

← На главную