Разработка внешних печатных форм (ВПФ) в среде 1С, использующей Библиотеку стандартных подсистем (БСП), часто сопровождается возникновением типовой ошибки: «В обработчике печати не был сформирован табличный документ». Эта проблема может поставить в тупик даже опытного разработчика, так как визуально код формирования документа кажется верным, а при тестировании через форму обработки всё работает корректно. Рассмотрим подробнее, почему это происходит и как правильно структурировать код внешней обработки.
Основная причина кроется в механизме взаимодействия платформы 1С и БСП. Когда вы нажимаете кнопку «Печать», система вызывает экспортную функцию Печать в модуле вашей внешней обработки. В эту функцию передается параметр КоллекцияПечатныхФорм. Ошибка возникает тогда, когда после завершения работы функции Печать в этой коллекции не оказывается строки с нужным идентификатором или табличный документ в этой строке пуст.
Проанализируем ситуацию на примере кода. В функции СведенияОВнешнейОбработке мы регистрируем команду:
ДобавитьКоманду(ТаблицаКоманд,
НСтр("ru = 'Печать акта'"),
"Акт", // Это Идентификатор команды
"ВызовСерверногоМетода",
Истина,
"ПечатьMXL");
Здесь строковое значение "Акт" является уникальным ключом — Идентификатором. Выясним причину ошибки: в процедуре Печать разработчик часто допускает опечатку или путает идентификатор команды с именем макета. Посмотрим на некорректный вызов:
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "Макет1", "Акт", ...);
В данном методе второй параметр — это именно ИмяМакета (в контексте коллекции он должен соответствовать Идентификатору из таблицы команд). Если в БСП передана команда с ID "Акт", а вы пытаетесь зарегистрировать в коллекции форму с ID "Макет1", система просто не «увидит» результат работы вашего кода. Для исправления ситуации необходимо, чтобы идентификатор команды в регистрации и второй параметр функции вывода в коллекцию совпадали.
Рассмотрим эталонную структуру регистрации команды и её последующей обработки. Важно следить за количеством параметров в функции Печать. В современных версиях БСП (начиная с 2.x и 3.x) их должно быть ровно четыре.
// Функция регистрации внешней обработки
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
МассивНазначений = Новый Массив;
МассивНазначений.Добавить("Документ.РеализацияТоваровУслуг");
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "Печать акта (ВПФ)");
ПараметрыРегистрации.Вставить("Идентификатор", "ПечатьАкта"); // Общий ID
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Идентификатор команды здесь — "АктПриемаПередачи"
ДобавитьКоманду(ТаблицаКоманд, "Акт приема-передачи", "АктПриемаПередачи", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
// Основной обработчик печати
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, есть ли наша команда в запросе на печать
ПараметрыПечати = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "АктПриемаПередачи");
Если ПараметрыПечати <> Неопределено Тогда
ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати);
// ВАЖНО: Второй параметр должен быть "АктПриемаПередачи"
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"АктПриемаПередачи",
"Акт приема-передачи (заголовок)",
ТабличныйДокумент);
КонецЕсли;
КонецПроцедуры
Проанализируем распространенную ошибку, связанную с циклом Для каждого. В сообщении №4 автор создает Новый ТабличныйДокумент внутри цикла по массиву объектов. Это критическая ошибка проектирования ВПФ. Если пользователь выделит в списке 10 документов и нажмет печать, программа 10 раз перезапишет переменную ТабДокумент, и в итоге функция вернет только последний документ. Более того, БСП ожидает один общий табличный документ, где страницы разделены разделителями.
Посмотрим на пример правильной организации цикла:
Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.АвтоМасштаб = Истина;
Макет = ПолучитьМакет("Макет1");
ПервыйДокумент = Истина;
Для каждого СсылкаНаДокумент Из МассивОбъектов Цикл
Если Не ПервыйДокумент Тогда
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ПервыйДокумент = Ложь;
// Запоминаем начало вывода для ОбъектыПечати (нужно для БСП)
НомерСтрокиНачало = ТабДокумент.ВысотаТаблицы + 1;
// Выводим области макета
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Заполнить(СсылкаНаДокумент);
ТабДокумент.Вывести(ОбластьШапка);
// Указываем БСП, какой объект соответствует этим строкам
УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабДокумент, НомерСтрокиНачало, ОбъектыПечати, СсылкаНаДокумент);
КонецЦикла;
Возврат ТабДокумент;
КонецФункции
Выясним, почему ещё может не формироваться документ. В первом сообщении темы мы видим закомментированную строку ТабДок.Показать();. Помните: никогда не используйте метод .Показать() во внешних печатных формах. Код ВПФ выполняется на сервере (в контексте серверного вызова), где нет и не может быть графического интерфейса. Попытка вызвать окно на сервере приведет к аварийному завершению потока, и табличный документ не будет возвращен в коллекцию.
Также обратим внимание на Безопасный режим. Если при регистрации указано БезопасныйРежим = Истина, 1С накладывает ограничения:
СклонениеПредставленийОбъектов.Просклонять() может требовать привилегированного режима или специфических разрешений в профиле безопасности).Если ваша функция формирования «падает» из-за недостатка прав доступа к ресурсам в безопасном режиме, коллекция останется пустой, и пользователь увидит обсуждаемую ошибку. Попробуйте временно установить БезопасныйРежим = Ложь для диагностики.
Проанализируем код из сообщения №4. Мы видим выполнение запроса к справочнику КонтактныеЛица внутри цикла. Это антипаттерн разработки 1С. При печати 100 документов система сделает 100 обращений к базе данных, что существенно замедлит формирование. Рассмотрим, как сделать правильно: нужно собрать все ссылки из МассивОбъектов, выполнить один общий запрос к базе, выгрузить результат в таблицу значений или структуру, и уже из неё брать данные внутри цикла формирования документа.
Это не только ускорит работу, но и предотвратит ошибки таймаута на больших объемах данных, которые также могут привести к «недоформированию» табличного документа.
Итог: Чтобы исправить ошибку «В обработчике печати не был сформирован табличный документ», проверьте соответствие идентификатора в СведенияОВнешнейОбработке и в ВывестиТабличныйДокументВКоллекцию, убедитесь, что вы не используете клиентские методы на сервере, и проверьте, что функция Печать принимает актуальное количество параметров.