Разработка внешних печатных форм (ВПФ) — одна из самых частых задач программиста 1С. Однако начинающие разработчики часто сталкиваются с ситуацией, когда форма идеально работает при ручном запуске через Файл -> Открыть, но после регистрации в справочнике Дополнительные отчеты и обработки выводит только «шапку» макета без данных. В этой статье мы разберем, почему так происходит, проанализируем механизмы передачи параметров в современных конфигурациях и приведем правильные примеры кода для корректной работы печати.
Главная причина описанной проблемы кроется в архитектуре Библиотеки стандартных подсистем (БСП), которая используется в большинстве современных конфигураций (Бухгалтерия предприятия 3.0, Управление торговлей 11, ERP и др.). Рассмотрим ситуацию подробнее.
Когда вы открываете обработку как обычный файл, вы, скорее всего, используете форму обработки, где интерактивно выбираете документ в реквизит СсылкаНаОбъект. В этом случае код запроса успешно подхватывает значение этого реквизита. Однако при встраивании ВПФ в систему механизм вызова меняется:
Печать() в модуле объекта обработки.В результате переменная СсылкаНаОбъект, на которую рассчитывал автор темы, оказывается пустой (или неопределенной), запрос не находит данных по «пустой» ссылке, и макет выводится незаполненным. Давайте выясним, как это исправить.
Проанализируем стандартную сигнатуру процедуры печати, которую ожидает БСП. Она должна быть расположена в модуле объекта вашей внешней обработки и иметь модификатор Экспорт. Рассмотрим обязательные параметры:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Здесь начинается логика формирования печатной формы
КонецПроцедуры
Параметр МассивОбъектов — это именно тот список документов, которые пользователь выбрал в списке или открыл для печати. Именно его нужно использовать для получения данных.
Рассмотрим пример кода из обсуждения. Изначально автор использовал условие в запросе ГДЕ Ссылка = &Ссылка. Это в корне неверно для встраиваемой печатной формы, так как форма должна поддерживать групповую печать. Если пользователь выделит в списке 10 документов и нажмет «Печать», ваша форма должна обработать их все за один вызов сервера.
Проанализируем правильный подход к построению запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ТаблицаТовары.НомерСтроки КАК НомерСтроки,
| ТаблицаТовары.Номенклатура КАК Номенклатура,
| ТаблицаТовары.Количество КАК Количество,
| ТаблицаТовары.Ссылка КАК СсылкаНаДокумент
|ИЗ
| Документ.ПеремещениеВЭксплуатации.Товары КАК ТаблицаТовары
|ГДЕ
| ТаблицаТовары.Ссылка В (&МассивОбъектов)
|УПОРЯДОЧИТЬ ПО
| СсылкаНаДокумент,
| НомерСтроки";
Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
РезультатЗапроса = Запрос.Выполнить();
Важный момент: использование оператора В (&МассивОбъектов) вместо равенства позволяет запросу эффективно выбрать данные для всех переданных ссылок сразу. Это значительно повышает производительность системы.
После того как мы получили данные, нам нужно правильно их разбить по печатным страницам. Для этого мы используем обход выборки. Если в массиве несколько документов, каждый из них должен начинаться с новой страницы (в большинстве случаев).
Рассмотрим пример цикла обработки:
ВыборкаПоДокументам = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПоДокументам.Следующий() Цикл
// Номер страницы или разделитель, если документ не первый
Если ТабличныйДокумент.ВысотаТаблицы > 0 Тогда
ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
НачалоОбласти = ТабличныйДокумент.ВысотаТаблицы + 1;
// Вывод шапки документа
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Заполнить(ВыборкаПоДокументам);
ТабличныйДокумент.Вывести(ОбластьШапка);
// Вывод строк документа
ВыборкаСтрок = ВыборкаПоДокументам.Выбрать();
Пока ВыборкаСтрок.Следующий() Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Заполнить(ВыборкаСтрок);
ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
// Регистрируем область печати для формирования содержания (необязательно, но полезно для БСП)
УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабличныйДокумент, НачалоОбласти, ОбъектыПечати, ВыборкаПоДокументам.СсылкаНаДокумент);
КонецЦикла;
Автор вопроса справедливо спрашивает: «Как такое отладить?». Отладка внешних обработок в 1С имеет свои нюансы, так как при запуске из справочника Дополнительные отчеты и обработки код выполняется во временном файле на сервере.
Разберем основные методы отладки:
Печать в самом начале добавьте проверку. Если код запущен не из БСП (например, массив объектов не определен), инициализируйте его вручную.
Если МассивОбъектов = Неопределено Тогда
// Этот блок сработает только при запуске через Файл-Открыть
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(СсылкаНаТестовыйДокумент);
КонецЕсли;
Печать вашей обработки, позволяя останавливаться на точках останова в конфигураторе.-debug).Отладка -> Подключение -> Автоматическое подключение и установить флажок Фоновые задания.УстановитьТочкуОстанова() или просто поставить точку в модуле объекта, предварительно загрузив актуальную версию обработки в базу.Если запрос выполняется, данные есть, но в макете всё равно пусто — проанализируем настройки самого макета в конфигураторе:
Параметр (а не Текст). Если вы хотите комбинировать текст и данные (например, «Документ № [Номер]»), используйте тип Шаблон.Область.Параметры.Заполнить(СтруктураДанных) значительно упрощает жизнь, автоматически сопоставляя имена.Макет.ПолучитьОбласть("Строка ") (с лишним пробелом).Подведем итог. Чтобы ваша внешняя печатная форма работала стабильно в любом режиме, всегда ориентируйтесь на работу с массивом объектов. Даже если вам нужна печать только одного документа, код Ссылка = МассивОбъектов[0]; (как предлагали в сообщении 15) является рабочим, но не самым лучшим вариантом, так как он ломает возможность печати нескольких документов сразу. Используйте полноценный цикл обхода, и ваша разработка будет соответствовать стандартам профессиональной разработки на платформе 1С:Предприятие 8.3.