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

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

При разработке внешних печатных форм в системе 1С:Предприятие 8 очень часто возникает задача вывода данных не в стандартный табличный документ, а непосредственно в шаблон офисного документа Microsoft Word (форматы .doc или .docx). Однако при попытке реализовать такую печатную форму в конфигурациях, использующих Библиотеку стандартных подсистем (БСП), разработчики часто сталкиваются с неприятной ошибкой: «В обработчике печати не был сформирован табличный документ для...».

Выясним причину этой ошибки и подробно разберем три различных способа ее решения: от простого обхода системы до реализации печати по современным стандартам БСП без использования нестабильных COM-объектов.

Почему возникает ошибка контроля БСП?

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

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

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

Способ 1. Быстрый «костыль» с передачей пустого табличного документа

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

Рассмотрим пример реализации этого способа в модуле внешней обработки:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // 1. Сначала запускаем вашу процедуру формирования и открытия документа Word
    ЗаполнитьИОткрытьДокументWord(МассивОбъектов);
    
    // 2. Находим нашу печатную форму в коллекции БСП
    ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ИдентификаторМоейКоманды");
    
    Если ПечатнаяФорма <> Неопределено Тогда
        // Создаем пустой табличный документ, чтобы "успокоить" БСП
        ТабДок = Новый ТабличныйДокумент;
        
        // Записываем его в коллекцию
        ПечатнаяФорма.ТабличныйДокумент = ТабДок;
        ПечатнаяФорма.СинонимМакета = "Печать договора Word";
    КонецЕсли;
    
КонецПроцедуры

Вместо поиска строки вручную можно также воспользоваться стандартным методом БСП для вывода табличного документа в коллекцию:


УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
    КоллекцияПечатныхФорм, 
    "ИдентификаторМоейКоманды", 
    "Печать договора Word", 
    Новый ТабличныйДокумент
);

Этот способ крайне прост в реализации, однако у него есть существенные недостатки: вам все равно приходится создавать лишний объект на сервере, а открытие Word происходит через медленный механизм COM на стороне клиента, что ведет к потенциальным зависаниям процессов.

Способ 2. Использование штатного механизма БСП для работы с макетами .docx

Начиная с современных версий БСП, фирма «1С» добавила полноценную поддержку офисных документов на уровне платформы. Это позволяет отказаться от нестабильных COM-объектов Word.Application, осуществлять генерацию файлов прямо на сервере (включая сервера под управлением Linux) и корректно передавать готовые двоичные данные клиенту.

Разберем по шагам, как настроить внешнюю обработку по новому стандарту:

  1. Создайте в вашей внешней обработке макет с типом Двоичные данные и загрузите туда ваш шаблон в формате .docx.
  2. В самом файле Word разметьте области заполнения с помощью тегов, например, {v8 ИмяПараметра} для одиночных параметров или структурных тегов для областей и таблиц.
  3. В процедуре Печать() заполняйте не свойство ТабличныйДокумент, а специальное свойство ОфисныеДокументы.

Посмотрим на пример кода, реализующего этот современный подход:


Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ИдентификаторМоейКоманды") Тогда
        
        ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ИдентификаторМоейКоманды");
        
        Если ПечатнаяФорма <> Неопределено Тогда
            // Вызываем функцию формирования структуры файлов Office на сервере
            ПечатнаяФорма.ОфисныеДокументы = СформироватьДокументыWordНаСервере(МассивОбъектов);
            ПечатнаяФорма.СинонимМакета = "Договор (Word)";
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Функция СформироватьДокументыWordНаСервере должна возвращать Соответствие, где ключом выступает объект печати (ссылка на документ), а значением — двоичные данные сгенерированного файла. Для сборки файлов используются методы общего модуля УправлениеПечатью, работающие с zip-архивом docx-контейнера напрямую.

Способ 3. Обход проверки БСП через «ВызовКлиентскогоМетода»

Если вам критически важно запускать заполнение Word именно на стороне клиента через установленное локальное приложение Microsoft Office и вы не хотите генерировать пустые табличные документы на сервере, есть изящное архитектурное решение. Мы можем изменить режим запуска команды печати.

Проанализируем этот подход. По умолчанию команды печати регистрируются с типом ВызовСерверногоМетода. Но если мы зарегистрируем команду как клиентскую, БСП передаст управление на клиент и вообще не будет проверять наличие табличного документа на сервере!

Для реализации этого способа выполним следующие действия:

  1. В модуле объекта внешней обработки в функции СведенияОВнешнейОбработке() для нашей команды указываем тип запуска на клиенте:

// Вместо стандартного ВызовСерверногоМетода указываем ВызовКлиентскогоМетода
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
  1. В созданной форме внешней обработки в модуле формы определяем экспортную клиентскую процедуру ВыполнитьКоманду. Обратите внимание, что имя процедуры должно быть именно таким, так как БСП вызывает ее автоматически при активации команды пользователем:

&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    
    Если ИдентификаторКоманды = "ИдентификаторМоейКоманды" Тогда
        // Запускаем заполнение Word непосредственно на компьютере пользователя
        ЗаполнитьШаблонНаКлиенте(ОбъектыНазначения);
    КонецЕсли;
    
КонецПроцедуры

При использовании клиентского вызова вся логика работы с COM-объектом (Новый COMОбъект("Word.Application")) безопасно отрабатывает на стороне локальной операционной системы пользователя. При этом серверная часть БСП не участвует в обработке печатного макета, а значит, никаких ошибок об отсутствии табличного документа не возникнет.

Таким образом, мы рассмотрели все три возможных сценария обхода и решения проблемы. Выбор конкретного метода зависит от требований к вашей системе: для простых и быстрых решений подойдет первый способ, для кроссплатформенных надежных систем выбирайте второй способ, а для сохранения сложной клиентской автоматизации Word незаменим третий способ.

← На главную