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