При разработке отчетов в системе 1С:Предприятие без использования Системы компоновки данных (СКД) программисты часто сталкиваются с задачей динамического формирования структуры колонок. Типичный пример — отчет, где количество колонок зависит от выбранного периода (например, по месяцам). В данной статье мы разберем, как правильно управлять видимостью колонок и как формировать макет так, чтобы не приходилось ничего скрывать.
Представим ситуацию: у нас есть макет с заранее определенными областями для 12 месяцев. Пользователь выбирает период, например, три месяца. Нам нужно либо скрыть лишние 9 колонок, либо вывести только нужные 3. Разберем оба подхода, их плюсы и минусы, а также проанализируем программный код для реализации этой логики.
Рассмотрим наиболее эффективный и правильный с точки зрения производительности метод. Вместо того чтобы выводить фиксированную "шапку" со всеми месяцами и затем скрывать ненужные, мы будем "собирать" шапку только из тех периодов, которые присутствуют в данных.
Для этого в макете необходимо разделить шапку на три части:
Разберем алгоритм вывода в коде. Сначала мы выводим левую часть методом Вывести(), а затем в цикле добавляем нужное количество колонок месяца методом Присоединить().
// Подготовительный этап: формирование массива периодов
СтандартныйПериод = Отчет.Период;
МассивПериодов = Новый Массив;
ТекущаяДата = НачалоМесяца(СтандартныйПериод.ДатаНачала);
Пока ТекущаяДата <= СтандартныйПериод.ДатаОкончания Цикл
МассивПериодов.Добавить(ТекущаяДата);
ТекущаяДата = ДобавитьМесяц(ТекущаяДата, 1);
КонецЦикла;
// Вывод в табличный документ
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МакетОтчета");
// 1. Выводим фиксированную левую часть
ОбластьЛево = Макет.ПолучитьОбласть("Шапка|Лево");
ТабДок.Вывести(ОбластьЛево);
// 2. В цикле присоединяем колонки месяцев
ОбластьМесяц = Макет.ПолучитьОбласть("Шапка|Центр");
Для Каждого МесяцДата Из МассивПериодов Цикл
// Заполняем параметр месяца (например, "Январь 2024")
ОбластьМесяц.Параметры.ПериодНаименование = Формат(МесяцДата, "ДФ='ММММ гггг'");
ТабДок.Присоединить(ОбластьМесяц);
КонецЦикла;
// 3. Присоединяем правую часть с итогами
ОбластьПраво = Макет.ПолучитьОбласть("Шапка|Право");
ТабДок.Присоединить(ОбластьПраво);
Проанализируем преимущества этого метода: мы создаем в памяти ровно столько объектов ячеек, сколько нужно для отображения. Это значительно ускоряет работу с большими отчетами и упрощает поддержку кода, так как нам не нужно писать сложные условия для скрытия.
Если структура макета уже жестко задана и переделывать её под метод Присоединить() слишком трудозатратно, можно воспользоваться свойством Видимость или ШиринаКолонки. Это может понадобиться, если макет очень сложный и состоит из множества пересекающихся областей.
Для реализации этого метода нам нужно определить номера колонок, которые подлежат скрытию. Выясним причину, по которой это может быть неудобно: при изменении структуры макета индексы колонок могут "поехать", и код придется переписывать. Чтобы избежать этого, рекомендуется использовать именованные области.
Посмотрим на пример кода, который скрывает колонку, если в массиве периодов нет соответствующего месяца:
// Предположим, у нас в макете колонки с 3 по 14 — это месяцы года
Для НомерКолонки = 3 По 14 Цикл
// Определяем, какой месяц соответствует данной колонке (условно)
ТекущийНомерМесяца = НомерКолонки - 2;
// Проверяем наличие этого месяца в нашем массиве данных
Если МесяцНеНайденВМассиве(ТекущийНомерМесяца) Тогда
// Скрываем колонку
ОбластьДляСкрытия = ТабДок.Область(, НомерКолонки);
ОбластьДляСкрытия.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
Рассмотрим важный нюанс: использование Видимость = Ложь иногда может приводить к некорректному отображению границ при печати или сохранении в PDF. В таких случаях мы рекомендуем альтернативный способ — установку ширины колонки в значение 0.
// Альтернативный способ скрытия через ширину
ТабДок.Область(, НомерКолонки).ШиринаКолонки = 0;
Часто программисты застревают на условии: "как понять, что эта колонка — январь?". Выясним, как сделать это элегантно. Если вы используете дату начала периода, функция Месяц(Дата) вернет число от 1 до 12. Это число можно использовать как индекс для поиска в макете или сопоставления с номером колонки.
Рассмотрим пример заполнения заголовков с использованием форматирования, чтобы не писать длинные конструкции Если...Тогда:
Полезный совет: Для вывода красивого названия месяца используйте метод Формат() с параметром ДФ='ММММ'. Это автоматически подставит название месяца в нужном падеже в зависимости от локализации системы.
Проанализируем ситуацию, когда отчет очень большой. Ошибка многих начинающих разработчиков заключается в том, что они проверяют условия скрытия непосредственно в момент вывода каждой строки. Это замедляет формирование документа.
Правильный алгоритм должен выглядеть так:
Таким образом, если в феврале не было продаж, колонка "Февраль" даже не начнет формироваться, что избавит нас от необходимости её скрывать.
При работе с динамическими колонками (особенно если их много, например, за 2-3 года) полезно применять дополнительные возможности ТабличногоДокумента:
ТабДок.ФиксацияСлева = КоличествоКолонокЛевойЧасти;.ТабДок.СгруппироватьКолонки(Начало, Конец);.Мы разобрали основные подходы к управлению областями макета в 1С. Подведем итоги:
1. Метод Присоединить() — наиболее универсальный и профессиональный. Он позволяет строить отчет "на лету", добавляя только те секции, которые нужны.
2. Свойство Видимость — подходит для простых правок в уже существующих сложных макетах, где переписывание логики вывода нецелесообразно.
3. ШиринаКолонки = 0 — надежная альтернатива скрытию, гарантирующая отсутствие "пустых мест" при печати.
Выбирайте метод в зависимости от сложности вашего макета и требований к производительности. Помните, что чистота кода и отсутствие лишних циклов проверки при выводе — залог быстрого отчета, который будет радовать пользователей.