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