Как реализовать групповую печать во внешней печатной форме 1С 8.3?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

При разработке внешних печатных форм для 1С 8.3 (особенно в конфигурациях на базе БСП, таких как Бухгалтерия предприятия 3.0) программисты часто сталкиваются с ситуацией, когда форма отлично работает для одного документа, но при попытке распечатать несколько выделенных объектов печатается только первый или возникает ошибка. В этой статье мы подробно разберем, как правильно модифицировать код внешней обработки, чтобы обеспечить полноценную групповую печать.

Анализ структуры внешней печатной формы

Для начала рассмотрим стандартную структуру внешней печатной формы. Она состоит из нескольких ключевых функций, взаимодействие которых определяет логику вывода данных. Проанализируем функцию регистрации СведенияОВнешнейОбработке. Именно здесь мы указываем системе, что наша обработка является печатной формой и к каким документам она привязана.

При регистрации команды важно правильно указать способ вызова. Для серверных печатных форм чаще всего используется ВызовСерверногоМетода. Посмотрим на пример заполнения параметров регистрации:


Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = Новый Структура;
    МассивНазначений = Новый Массив;
    МассивНазначений.Добавить("Документ.РеализацияТоваровУслуг");
    
    ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
    ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
    ПараметрыРегистрации.Вставить("Наименование", "Заказ на реализацию");
    ПараметрыРегистрации.Вставить("БезопасныйРежим", ИСТИНА);
    ПараметрыРегистрации.Вставить("Версия", "1.1");
    
    ТаблицаКоманд = ПолучитьТаблицуКоманд();
    ДобавитьКоманду(ТаблицаКоманд, "Печать заказа", "ПечатьЗаказа", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
    
    ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    Возврат ПараметрыРегистрации;
КонецФункции

Проблема: почему печатается только один документ?

Выясним причину, по которой групповая печать может не работать. Основная ошибка кроется в процедуре Печать. Когда пользователь выделяет в списке несколько документов и нажимает кнопку печати, система передает в эту процедуру массив ссылок МассивОбъектов. Если в коде прописано обращение только к первому элементу массива, например МассивОбъектов[0], то остальные документы будут проигнорированы.

Разберем типичный ошибочный код:


// ОШИБОЧНЫЙ ВАРИАНТ
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    // Здесь берется только первый элемент [0], что ломает групповую печать
    ТабДок = СформироватьПечатнуюФорму(МассивОбъектов[0], ОбъектыПечати);
    УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ПечатьЗаказа", "Заказ", ТабДок);
КонецПроцедуры

Решение проблемы через цикл по массиву объектов

Для того чтобы система обработала все выбранные документы, нам необходимо организовать цикл по МассивОбъектов. Проанализируем правильный подход: мы должны перебрать каждую ссылку, сформировать для нее табличный документ и добавить его в общую коллекцию.

Рассмотрим реализацию корректной процедуры Печать:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Создаем один общий табличный документ для всех объектов
    ТабличныйДокумент = Новый ТабличныйДокумент;
    ТабличныйДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_Заказ";
    
    // Перебираем все выделенные пользователем документы
    Для каждого СсылкаНаДокумент из МассивОбъектов Цикл
        
        // Если это не первый документ в цикле, добавляем разделитель страниц
        Если ТабличныйДокумент.ВысотаТаблицы > 0 Тогда
            ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц();
        КонецЕсли;
        
        // Запоминаем начало печати текущего документа (для навигации в окне предпросмотра)
        НомерОчереди = ОбъектыПечати.Количество() + 1;
        НачалоОбласти = ТабличныйДокумент.ВысотаТаблицы + 1;
        
        // Формируем данные для конкретного документа
        ЗаполнитьДанныеПечати(ТабличныйДокумент, СсылкаНаДокумент);
        
        // Связываем область табличного документа со ссылкой
        УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабличныйДокумент, НомерОчереди, ОбъектыПечати, СсылкаНаДокумент);
        
    КонецЦикла;
    
    // Выводим итоговый результат в коллекцию форм
    УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ПечатьЗаказа", "Заказ", ТабличныйДокумент);
    
КонецПроцедуры

Важный момент: использование метода ВывестиГоризонтальныйРазделительСтраниц() позволяет гарантировать, что каждый новый документ начнется с нового листа бумаги. Если этого не сделать, формы «склеятся» одна за другой на одном листе.

Оптимизация: работа с запросами в групповой печати

Рассмотрим ситуацию, когда документов много (например, более 50). Если внутри цикла мы будем выполнять запросы к базе данных по каждому документу отдельно, это приведет к значительным задержкам и нагрузке на сервер. В среде 1С это называется «запрос в цикле» и считается плохим тоном в разработке.

Посмотрим, как оптимизировать этот процесс. Вместо того чтобы передавать в функцию формирования одну ссылку, передадим туда сразу весь МассивОбъектов. Сделаем один большой запрос, который соберет данные по всем документам за один раз.


Функция СформироватьВсеПечатныеФормы(МассивСсылок)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Реализация.Ссылка КАК Ссылка,
        |   Реализация.Номер КАК Номер,
        |   Реализация.Дата КАК Дата,
        |   Реализация.Контрагент.Наименование КАК Клиент
        |ИЗ
        |   Документ.РеализацияТоваровУслуг КАК Реализация
        |ГДЕ
        |   Реализация.Ссылка В(&МассивСсылок)";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    РезультатЗапроса = Запрос.Выполнить();
    
    // Далее обходим результат запроса и заполняем макеты
    // ...
КонецФункции

Разбор ошибки «Итератор для значения не определен»

При реализации групповой печати разработчики часто сталкиваются с ошибкой Итератор для значения не определен. Проанализируем причину ее возникновения. Обычно это случается, когда функция ожидает массив, а в нее передается одиночная ссылка (или наоборот). Если вы изменили заголовок функции на Для каждого СсылкаНаДокумент из МассивСсылок, убедитесь, что при вызове функции вы передаете именно массив МассивОбъектов, а не МассивОбъектов[0].

Также проверьте, правильно ли определена коллекция ОбъектыПечати. Она необходима для того, чтобы в стандартном окне печати 1С работал список документов слева: при нажатии на название документа в списке справа должен отображаться именно его лист.

Итоги и рекомендации

Подведем итоги нашего исследования. Для реализации качественной групповой печати во внешней обработке необходимо выполнить следующие шаги:

  1. Организовать цикл по входному массиву объектов в процедуре Печать.
  2. Использовать разделители страниц между документами, чтобы печать была корректной.
  3. Минимизировать запросы, стараясь получать данные пакетно по всему списку ссылок.
  4. Заполнять параметры вывода, такие как ОбъектыПечати, для удобства навигации пользователя.
  5. Проверять заполнение данных: если в одном из документов нет строк в табличной части, программа не должна прерывать печать остальных документов.

Следуя этим правилам, вы создадите надежный инструмент, который будет стабильно работать в типовых конфигурациях 1С, таких как БП 3.0, УТ 11 или ERP.

← На главную