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