Почему печатная форма выводит шапку несколько раз и как это исправить в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

Анализ проблемы: почему шапка выводится повторно

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

Посмотрим на фрагмент кода, где скрывается основная причина повторного вывода шапки:


Для каждого ст из ДляРаспечаткиКоличествоДог Цикл
    Колонки1Мес = МакетРаспечатки.ПолучитьОбласть("Колонки");
    Колонки1Мес.Параметры.Договор1 = ст.Договор;
    ТабДок.Вывести(Колонки1Мес);
КонецЦикла;

Выясним причину некорректного поведения. Здесь допущены сразу две логические ошибки:

  1. Многократный вызов метода Вывести() в цикле: метод Вывести() добавляет область табличного документа строго вниз (по вертикали). Если вызывать его внутри цикла по таблице значений ДляРаспечаткиКоличествоДог, каждая новая ячейка договорной колонки будет выводиться новой строкой ниже предыдущей.
  2. Отсутствие контроля условий: если в коде закомментировать проверки количества договоров (например, Если ДляРаспечаткиКоличествоДог.Количество = 1 Тогда), итерация выполняется безусловно по всем строкам таблицы, приводя к зацикленному формированию секции шапки.

Кроме того, если дальше по тексту процедуры встречается повторный цикл по той же самой таблице значений без логического разделения ветвей исполнения, программа заново начинает обращаться к области макета и добавлять её в документ.

Разбор работы методов Вывести() и Присоединить()

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

Проанализируем правильный порядок вывода шапки с динамическими колонками:


// 1. Выводим фиксированную левую часть шапки
Шапка = МакетРаспечатки.ПолучитьОбласть("Шапка");
Шапка.Параметры.Заказ = НужныйЗаказ;
ТабДок.Вывести(Шапка);

// 2. В цикле присоединяем динамические колонки справа
Для Каждого СтрДог Из ДляРаспечаткиКоличествоДог Цикл
    Колонка = МакетРаспечатки.ПолучитьОбласть("КолонкаДоговор");
    Колонка.Параметры.Договор1 = СтрДог.Договор;
    ТабДок.Присоединить(Колонка);
КонецЦикла;

Как избежать дублирования строк при обходе данных

Вторая частая проблема в процедурах вывода печатных форм — дублирование номенклатурных позиций. Это происходит, когда во внешнем цикле выполняется обход таблицы, а внутри используется метод НайтиСтроки(), но уже обработанные записи не помещаются флагом или не пропускаются при следующей итерации.

Посмотрим, как правильно организовать обработку уникальных позиций:


// Создаем копию таблицы и оставляем только уникальные позиции
ТЗУникальные = ДляРаспечаткиОконч.Скопировать();
ТЗУникальные.Свернуть("Артикул, Обозначение, Наименование");

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

Рекомендации по оптимизации кода печатной формы

Для предотвращения путаницы в переменных-счетчиках (сч1, сч2, с) и оптимизации работы печатных форм придерживайтесь следующих правил:

  1. Заменяйте ручную обработку табличной части запросами: вместо нескольких временных табличных значений и использования метода Свернуть() используйте язык запросов 1С. Группировка СГРУППИРОВАТЬ ПО в запросе мгновенно вернет уникальные данные без дублей.
  2. Давайте переменным понятные имена: избегайте названий вроде сч1 или ст. Использование названий СчетчикДоговоров, ТекущийДоговор делает код читаемым.
  3. Используйте режим отладки: при появлении лишних строк устанавливайте точку останова на начале цикла вывода и проверяйте количество строк в таблице значений с помощью вычислителя выражений (Shift + F9).
← На главную