При работе с внешними печатными формами в конфигурациях на базе Библиотеки стандартных подсистем (БСП) разработчики часто сталкиваются с крайне неинформативной ошибкой вида:
{ОбщийМодуль.УправлениеПечатью.Модуль(1522)}: В обработчике печати не был сформирован табличный документ для: ПФ_MXL_Акт ВызватьИсключение(ТекстСообщенияОбОшибке);
Эта ошибка является системным «перехватчиком» БСП. Она сообщает лишь об одном: в коллекции печатных форм после выполнения кода формирования макета поле ТабличныйДокумент осталось пустым (значение Неопределено). Сама же реальная причина сбоя скрывается глубоко в коде вашей внешней обработки.
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем реальный практический кейс из практики разработчиков, рассмотрим другие распространенные причины и составим пошаговую инструкцию по отладке.
---
Проанализируем конкретную ситуацию. Разработчик создал внешнюю печатную форму для документа «Акт об оказании услуг» в конфигурации «Бухгалтерия предприятия 3.0» и столкнулся с вышеуказанной ошибкой. При этом стандартная печать не выдавала никаких подробностей.
Давайте посмотрим на фрагмент кода, который вызывал заполнение коллекции печатных форм в модуле обработки:
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"АктВнешний",
"Акт об оказании услуг",
ПечатьАктаОбОказанииУслуг(ТаблицаСведенийАктаОбОказанииУслуг, "АктВнешний", ПараметрыПечати),
,
"ПФ_MXL_Акт"
);
А теперь обратим внимание на сигнатуру (описание) функции, которая непосредственно формирует табличный документ:
Функция ПечатьАктаОбОказанииУслуг(СведенияАктаОбОказанииУслуг, ОбъектыПечати, СтруктураПараметровПечати) Экспорт
// ... логика формирования макета
КонецФункции
Выявим несоответствие. В функцию ПечатьАктаОбОказанииУслуг вторым параметром передается строковое значение "АктВнешний":
ПечатьАктаОбОказанииУслуг(..., "АктВнешний", ...)
Однако в качестве второго параметра функция ожидает переменную ОбъектыПечати. В механизмах БСП этот параметр всегда должен быть коллекцией (например, типом Массив или СписокЗначений), содержащей ссылки на печатаемые документы.
Когда управление передается внутрь функции формирования макета, там выполняется стандартный вызов:
УправлениеПечатью.ЗадатьОбластьПечатиДокумента(
ТабличныйДокумент,
НомерСтрокиНачало,
ОбъектыПечати,
СведенияОДокументе.Документ
);
Поскольку вместо массива ОбъектыПечати метод получает обычную строку "АктВнешний", платформа генерирует неявное исключение (ошибку несоответствия типов). Выполнение функции аварийно прерывается, табличный документ не возвращается, и БСП сообщает о том, что документ не был сформирован.
Решение проблемы: необходимо строго следить за передаваемыми типами параметров. В функцию печати в качестве второго аргумента нужно передавать массив объектов печати, полученный из внешней команды, а не строковый идентификатор команды.
---
Помимо несоответствия типов аргументов в процедурах формирования, в практике разработки выделяют еще несколько типовых ошибок.
Механизм регистрации внешних печатных форм в БСП жестко связывает идентификаторы команд. Если в функции СведенияОВнешнейОбработке() вы зарегистрировали команду с одним именем, а в процедуре Печать() проверяете другое имя, код заполнения просто проигнорирует команду.
Посмотрим на пример ошибочного кода в модуле обработки:
// В сведениях зарегистрирована команда "АктОбОказанииУслуг"
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Опечатка в имени идентификатора макета/команды
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "АктОбОказанииУслугВнешний") Тогда
// Этот блок кода никогда не выполнится!
ТабДок = СформироватьАкт(МассивОбъектов, ОбъектыПечати);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "АктОбОказанииУслугВнешний", "Акт", ТабДок);
КонецЕсли;
КонецПроцедуры
Так как условие НужноПечататьМакет вернет Ложь из-за несовпадения имен, табличный документ не запишется в коллекцию, и система выдаст ошибку.
Часто в коде внешней обработки функция генерации макета возвращает значение только при определенных условиях. Если логика построена неверно, выполнение может завершиться «в обход» финального возврата.
Функция СформироватьТабличныйДокумент(СсылкаНаДокумент)
ТабДок = Новый ТабличныйДокумент;
// ...
Если СсылкаНаДокумент.Проведен Тогда
// Заполнение документа
Возврат ТабДок;
КонецЕсли;
// Ошибка: если документ не проведен, функция вернет Неопределено!
КонецФункции
Всегда проверяйте, чтобы в любых ветках условий (Если ... Иначе) функция гарантированно возвращала объект типа ТабличныйДокумент.
Если вы взяли за основу типовой макет и решили «почистить» его, удалив неиспользуемые, по вашему мнению, строки или параметры, это может привести к фатальной ошибке. Код заполнения макета, написанный под старую структуру, попытается обратиться к удаленной области или параметру:
ОбластьМакета.Параметры.ВалидныйНоУдаленныйПараметр = Ссылка.Номер;
В этот момент код прерывается ошибкой выполнения, формирование прекращается, и БСП выдает стандартное предупреждение.
При работе в клиент-серверном режиме или в облачных сервисах (например, 1С:Fresh) код печати выполняется в фоновом задании на сервере. Использование таких операторов, как:
Предупреждение();Вопрос();ПоказатьПредупреждение();Сообщить() (в некоторых старых версиях БСП).вызывает мгновенный аварийный останов серверного процесса, так как сервер физически не может отобразить диалоговое окно пользователю.
---
Для того чтобы быстро локализовать проблему и увидеть реальное описание ошибки, а не шаблонную фразу БСП, воспользуемся проверенными методами отладки.
Самый простой способ — запустить код печатной формы как обычную внешнюю обработку на клиенте. Для этого:
СсылкаНаДокумент) и кнопку «Выполнить печать».
&НаКлиенте
Процедура ВыполнитьПечать(Команда)
ВыполнитьПечатьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьПечатьНаСервере()
ОбъектОбработки = РеквизитФормыВЗначение("Объект");
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(Объект.СсылкаНаДокумент);
КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм("АктВнешний");
ОбъектыПечати = Новый СписокЗначений;
ПараметрыВывода = УправлениеПечатью.ПодготовитьСтруктуруПараметровВывода();
// Вызываем процедуру напрямую
ОбъектОбработки.Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода);
КонецПроцедуры
Если внешняя печатная форма уже зарегистрирована в справочнике «Дополнительные отчеты и обработки» и вы хотите отладить ее в реальных условиях:
-debug).Печать() модуля объекта обработки.Если отладка в режиме реального времени невозможна (например, на «живой» базе клиента), оберните подозрительные участки кода в конструкцию Попытка ... Исключение и логируйте ошибки:
Попытка
ТабДок = СформироватьПечатнуюФорму(МассивОбъектов);
Исключение
ЗаписьЖурналаРегистрации(
"ВнешняяПечатнаяФорма.ОшибкаПечати",
УровеньЖурналаРегистрации.Ошибка,
,
,
ОписаниеОшибки()
);
ВызватьИсключение; // Пробрасываем ошибку дальше для корректного отката транзакции
КонецПопытки
После этого вам достаточно будет открыть Журнал регистрации в режиме «1С:Предприятие», отфильтровать события по событию «ВнешняяПечатнаяФорма.ОшибкаПечати» и прочитать детальный системный текст ошибки.
Используя данные методы, вы без труда сможете локализовать любое некорректное поведение алгоритмов и быстро исправить ошибки формирования макетов в БСП.