Как скрыть пустые колонки в отчете на СКД, если в них нет данных?

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

При разработке отчетов на Системе Компоновки Данных (СКД) часто возникает задача динамического управления структурой отчета. Типичная ситуация: у нас есть набор колонок (например, дни просрочки: "1 день", "2 день", "3 день"), которые добавлены в выбранные поля. Если, скажем, ни у одного контрагента нет просрочки во "2 день", эту колонку показывать не нужно — она будет пустой и лишь занимает место на экране. Стандартный отбор в СКД (Отбор) обычно работает на уровне записей (строк). Если мы установим отбор "Сумма > 0", то строка с нулевой суммой исчезнет, но сама колонка в шапке останется, если она явно указана в "Выбранных полях". Условное оформление с видимостью "Ложь" часто скрывает только содержимое ячеек, оставляя пустые клетки и заголовки. Давайте разберем подробно и структурно несколько профессиональных способов решения этой задачи, от архитектурных изменений до внедрения подсистемы предопределенных настроек и программной постобработки.

Почему так происходит?

Прежде чем переходить к коду, разберемся в природе проблемы. В настройках СКД структура отчета может быть представлена в виде:

  1. Таблица (Кросс-таблица): здесь колонки формируются динамически на основе группировки (например, по периодам). В этом случае отбор на группировку колонок работает отлично — если данных за период нет, колонка не выводится.
  2. Список (Группировка детальных записей): здесь колонки задаются в списке "Выбранные поля". Для системы это жесткая структура. Даже если во всех строках ячейка пуста, поле присутствует в макете.

Если вы не можете переделать отчет в кросс-таблицу (например, из-за сложной шапки "Задолженность"), нам придется прибегнуть к программному вмешательству.

Способ 1. Программное управление настройками (Предварительный анализ)

Это наиболее производительный и правильный с точки зрения архитектуры метод. Идея заключается в следующем: перед тем как компоновщик макета соберет отчет, мы должны проверить, есть ли данные для наших спорных колонок. Если данных нет — мы программно отключаем эти поля в настройках. Чтобы значительно упростить этот процесс и сократить объем кода, можно использовать СКДБилдер для программного управления компоновкой. Рассмотрим алгоритм действий в модуле объекта отчета или формы (в процедуре ПриКомпоновкеРезультата): Шаг 1. Выполняем проверочный запрос Нам не нужно получать все данные отчета. Достаточно легкого запроса, который вернет Максимум или Сумму по интересующим нас полям. Для быстрой отладки таких запросов и анализа структуры компоновщика удобно использовать инструменты разработчика для анализа СКД — для этого подойдёт инструментарий разработчика с консолью СКД и запросов.


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

НужноВыводитьДень1 = Ложь;
НужноВыводитьДень2 = Ложь;

Если Не РезультатПроверки.Пустой() Тогда
    Выборка = РезультатПроверки.Выбрать();
    Выборка.Следующий();
    // Если сумма или максимум больше 0, значит данные есть
    НужноВыводитьДень1 = (Выборка.МаксДень1 > 0);
    НужноВыводитьДень2 = (Выборка.МаксДень2 > 0);
КонецЕсли;

Шаг 2. Модифицируем настройки компоновщика Теперь, зная, какие колонки пустые, мы отключаем их использование в коллекции ВыбранныеПоля текущих настроек компоновщика.


// Получаем текущие настройки (важно брать пользовательские настройки, если они приоритетны)
Настройки = КомпоновщикНастроек.ПолучитьНастройки();

// Функция для рекурсивного поиска и отключения поля
Для Каждого ПолеИзСписка Из Настройки.Выбор.Элементы Цикл
    // Проверяем, является ли элемент полем (а не группой)
    Если ТипЗнч(ПолеИзСписка) = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
        
        ИмяПоля = Строка(ПолеИзСписка.Поле);
        
        Если ИмяПоля = "Просрочка1День" И Не НужноВыводитьДень1 Тогда
            ПолеИзСписка.Использование = Ложь;
        ИначеЕсли ИмяПоля = "Просрочка2День" И Не НужноВыводитьДень2 Тогда
            ПолеИзСписка.Использование = Ложь;
        КонецЕсли;
        
    КонецЕсли;
КонецЦикла;

// Важно: применяем измененные настройки обратно перед компоновкой макета
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);

Таким образом, при формировании макета СКД просто проигнорирует отключенные поля, и колонки (вместе с их заголовками в шапке) не будут созданы.

Способ 2. Постобработка Табличного документа

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


// Формируем отчет стандартным способом в ТабличныйДокумент
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ...);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// --- Начало постобработки ---

// Определяем область для анализа.
// Допустим, мы знаем, что данные находятся начиная со 2-й строки (после шапки)
ВысотаТаблицы = ТабДок.ВысотаТаблицы;
ШиринаТаблицы = ТабДок.ШиринаТаблицы;

// Идем по колонкам с конца
Для НомКол = -ШиринаТаблицы По -1 Цикл
    
    ИндексКолонки = -НомКол; // Превращаем обратно в положительное число
    
    // Пропускаем фиксированные колонки (например, Контрагент), если они слева
    Если ИндексКолонки <= 2 Тогда 
        Продолжить; 
    КонецЕсли;
    
    // Проверяем, пустая ли колонка. 
    // Можно проверить Итог, если он есть, или пройтись по ячейкам.
    ЕстьДанные = Ложь;
    
    // Пример проверки по области ячеек колонки
    // (для оптимизации лучше проверять только строку итогов, если она есть)
    Для НомСтр = 3 По ВысотаТаблицы Цикл
        ТекущаяЯчейка = ТабДок.Область(НомСтр, ИндексКолонки, НомСтр, ИндексКолонки);
        Если ЗначениеЗаполнено(ТекущаяЯчейка.Текст) И ТекущаяЯчейка.Текст <> "0" Тогда
            ЕстьДанные = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если данных нет - удаляем колонку
    Если Не ЕстьДанные Тогда
        ОбластьДляУдаления = ТабДок.Область(, ИндексКолонки, , ИндексКолонки);
        ТабДок.УдалитьОбласть(ОбластьДляУдаления, ТипСмещенияТабличногоДокумента.ПоГоризонтали);
    КонецЕсли;
    
КонецЦикла;

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

Способ 3. Переход на структуру "Таблица"

В обсуждении упоминалось, что отборы работают для таблиц. Если ваши дни просрочки ("1 день", "2 день") можно представить не как разные ресурсы, а как значение одного измерения, то лучше перестроить запрос. В некоторых архитектурных решениях для этого могут использоваться даже две разные схемы в одном отчете СКД. Вместо плоской таблицы: Контрагент | Сумма1День | Сумма2День Сделать таблицу вида: Контрагент | ВидПросрочки | Сумма Тогда в настройках СКД мы добавляем группировку колонок по полю ВидПросрочки. В этом случае:

  1. Мы можем наложить Отбор на группировку колонок: Сумма > 0.
  2. СКД автоматически не выводит колонку группировки, если в ней нет данных (если в настройках вывода не сказано обратного).

Это самый "нативный" способ работы с СКД, но он требует изменения текста запроса и структуры данных.

Способ 4. Трюк с макетом и шириной (Частичное решение)

Если вам категорически нельзя менять запрос и программный код, можно попробовать использовать Условное оформление, но не свойство Видимость, а свойство МаксимальнаяШирина. Иногда это требует дополнительных манипуляций, таких как программное изменение заголовка группировки, чтобы скрыть остаточные элементы оформления.

  1. Создаем элемент условного оформления.
  2. Условие: Поле "Просрочка2День" Равно 0 (или не заполнено).
  3. Оформляемые поля: "Просрочка2День".
  4. Значение параметра Максимальная ширина: 0.1 (или 0).

Результат: Колонка "схлопнется". Минусы: В зависимости от версии платформы заголовок колонки может не исчезнуть полностью. Поэтому данный метод менее надежен, чем способы 1 и 2.

Резюме

Для качественного решения задачи скрытия колонок без данных рекомендуем использовать Способ 1 (Предварительный анализ и отключение полей). Он обеспечивает наилучшую производительность и корректное отображение сложных шапок отчета. Также для расширения возможностей интерфейса можно внедрить инструменты пользовательской СКД для тонкого клиента.

Если же выводить отчет нужно "как есть", а потом подчищать — используйте Способ 2 (Метод УдалитьОбласть), но будьте внимательны с индексами колонок.

Рекомендуемые публикации:

← На главную