Как динамически изменить заголовок расчетной колонки в отчете СКД 1С на управляемых формах?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Торговля и дистрибуция
← На главную

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

Программное изменение заголовка вычисляемого поля в обработчике ПриКомпоновкеДанных()

Наиболее гибким и рекомендуемым способом для динамического изменения заголовков колонок в СКД является использование обработчика события ПриКомпоновкеДанных. Этот обработчик выполняется на этапе формирования макета компоновки данных, до того как начнется вывод самого отчета. Это позволяет нам внести изменения в структуру и настройки отчета, которые будут учтены при его последующей генерации.

Рассмотрим по шагам, как это сделать:

  1. Определимся с местом размещения кода. Наш код необходимо разместить в модуле объекта отчета, в обработчике события ПриКомпоновкеДанных. Если обработчик еще не создан, мы создадим его.

    Для этого в конфигураторе откроем отчет, перейдем на вкладку "Прочее", выберем "Модуль объекта", и найдем или создадим процедуру ПриКомпоновкеДанных.

  2. Получим доступ к настройкам компоновщика. Внутри обработчика ПриКомпоновкеДанных нам доступен объект КомпоновщикНастроек, который содержит все текущие настройки отчета, заданные пользователем или по умолчанию.

    
    Процедура ПриКомпоновкеДанных(КомпоновщикМакета, НастройкиКомпоновкиДанных, ДанныеРасшифровки, СтандартнаяОбработка)
        // Доступ к текущим настройкам отчета
        Настройки = КомпоновщикНастроек.Настройки;
        // ... дальнейшая логика
    КонецПроцедуры
    

    Обратите внимание, что объект НастройкиКомпоновкиДанных, переданный как параметр, также содержит настройки, но КомпоновщикНастроек.Настройки является более универсальным способом получить доступ к полным настройкам компоновщика, включая параметры.

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

    
    ДатаОкончанияПериода = Неопределено;
    Для Каждого ЭлементПараметра Из Настройки.ПараметрыДанных.Элементы Цикл
        Если ЭлементПараметра.Параметр.Имя = "ПериодОтчетаКонец" Тогда // Или другое имя вашего параметра даты окончания
            ДатаОкончанияПериода = ЭлементПараметра.Значение;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ДатаОкончанияПериода = Неопределено Тогда
        Возврат; // Или установить значение по умолчанию / вывести ошибку
    КонецЕсли;
    

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

  4. Сформируем новый заголовок. Используя полученную дату, мы можем сформировать динамическую строку для заголовка. Например, нам нужен месяц окончания периода.

    НовыйЗаголовок = "Отгрузка за " + Формат(ДатаОкончанияПериода, "ДФ=MMMM ГГГГ");

    Функция Формат() позволяет гибко форматировать дату в нужное нам представление (например, "Январь 2023").

  5. Найдем вычисляемое поле и изменим его заголовок. Расчетная колонка (вычисляемое поле) должна быть включена в выбранные поля отчета. Мы должны найти этот элемент в коллекции Настройки.ВыбранныеПоля.Элементы и изменить его свойство Заголовок.

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

    Если ваша расчетная колонка является частью группировки, возможно, потребуется искать ее в Настройки.Группировки.Элементы, а затем в ПоляГруппировки или ВыбранныеПоля внутри этой группировки. В большинстве случаев достаточно поиска по ВыбранныеПоля.

Полный пример кода для обработчика ПриКомпоновкеДанных:


Процедура ПриКомпоновкеДанных(КомпоновщикМакета, НастройкиКомпоновкиДанных, ДанныеРасшифровки, СтандартнаяОбработка)

    СтандартнаяОбработка = Истина; // Обычно оставляем стандартную обработку

    Настройки = КомпоновщикНастроек.Настройки;

    // 1. Получаем значение параметра даты окончания периода
    ДатаОкончанияПериода = Неопределено;
    Для Каждого ЭлементПараметра Из Настройки.ПараметрыДанных.Элементы Цикл
        Если ЭлементПараметра.Параметр.Имя = "ПериодОтчетаКонец" Тогда // Предполагаем, что у вас есть параметр с таким именем
            ДатаОкончанияПериода = ЭлементПараметра.Значение;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Если ДатаОкончанияПериода = Неопределено Тогда
        // Если параметр не установлен, используем текущую дату или дату по умолчанию
        ДатаОкончанияПериода = КонецМесяца(ТекущаяДата());
    КонецЕсли;

    // 2. Формируем новый заголовок
    // Пример: "Отгрузка за Январь 2023"
    НовыйЗаголовок = "Отгрузка за " + Формат(ДатаОкончанияПериода, "ДФ=MMMM ГГГГ");

    // 3. Находим вычисляемое поле и изменяем его заголовок
    // Предполагаем, что имя вашего вычисляемого поля в СКД - "ОтгрузкаПоследнегоМесяца"
    Для Каждого ВыбранноеПоле Из Настройки.ВыбранныеПоля.Элементы Цикл
        Если ВыбранноеПоле.Поле = "ОтгрузкаПоследнегоМесяца" Тогда
            ВыбранноеПоле.Заголовок = НовыйЗаголовок;
            // Можно также изменить Представление, если требуется для других целей
            // ВыбранноеПоле.Представление = НовыйЗаголовок;
            Прервать;
        КонецЕсли;
    КонецЦикла;

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

    КонецЦикла;
    
    // Также можно проверить другие коллекции, например, Поля
    Для Каждого ПолеСКД Из НастройкиКомпоновкиДанных.Поля Цикл
        Если ПолеСКД.Поле = "ОтгрузкаПоследнегоМесяца" Тогда
            ПолеСКД.Заголовок = НовыйЗаголовок;
            Прервать;
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Преимущества данного подхода:

  1. Универсальность: Изменения вносятся до формирования макета, что делает отчет универсальным. Он всегда будет использовать актуальный заголовок, соответствующий выбранным параметрам.
  2. Простота: Относительно простая логика для реализации, не требующая глубокого погружения в механизмы компоновки макета вручную.
  3. Надежность: Работает с исходными настройками СКД, минимизируя риск непредвиденного поведения.

Решение 2: Использование макетов для заголовков (Дополнительный подход)

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

Когда макеты могут быть полезны:

  1. Для заголовков группировок: Если расчетная колонка фактически является частью динамической группировки (например, "Отгрузка за [Месяц]", где [Месяц] — это поле группировки), можно создать макет для этой группировки. В макете можно указать шаблон, который будет заполняться автоматически значениями поля группировки. Например, в макете для поля группировки по месяцу можно разместить текст "[Месяц]", и СКД автоматически подставит название месяца. Однако это не изменяет заголовок *самого* вычисляемого поля, а только представление элемента группировки.
  2. Для статических или условно статических заголовков: Если заголовок зависит от определенного статического значения или просто должен быть фиксированным, макеты поля могут быть использованы. Но для заголовка, который должен динамически отражать параметр отчета (например, "Месяц окончания периода"), макеты сами по себе без программной доработки не справятся.

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

Почему попытка изменить заголовок в ПриКомпоновкеРезультата() привела к пустому отчету?

Автор в сообщении 7 пытался изменить заголовок, используя ручную компоновку данных в обработчике ПриКомпоновкеРезультата. Давайте проанализируем ситуацию и выясним причину возникновения "пустого отчета".

Суть проблемы:

Обработчик события ПриКомпоновкеРезультата предназначен для работы с уже сгенерированным результатом компоновки данных, который представлен в виде ТабличногоДокумента или через ПроцессорВыводаРезультатаКомпоновкиДанных. Это событие возникает, когда отчет уже почти сформирован и готов к выводу. Его основная цель — пост-обработка или корректировка оформления уже сформированных ячеек, строк или колонок, но не изменение базовой структуры или данных отчета.

Код, приведенный автором:


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

Пошаговый анализ ошибки:

  1. СтандартнаяОбработка = Ложь;

    Отключение стандартной обработки означает, что платформа не будет самостоятельно формировать отчет. Всю работу по компоновке и выводу берет на себя наш код.

  2. КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(...);

    Здесь мы создаем новый экземпляр КомпоновщикаМакетаКомпоновкиДанных и вручную запускаем процесс формирования макета. Критическая проблема заключается в том, что в качестве второго параметра (настройки компоновки) передается ЭтотОбъект.КомпоновщикНастроек.Настройки. Как справедливо отмечено в сообщении 10, на момент вызова ПриКомпоновкеРезультата, если отчет не был скомпонован стандартным образом, или если параметры не были корректно инициализированы в КомпоновщикНастроек, эти настройки могут быть пустыми или содержать неполную информацию.

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

  3. ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(...);

    Далее мы создаем новый ПроцессорКомпоновкиДанных и инициализируем его. Это еще один шаг ручной компоновки, который будет использовать макет, сформированный на предыдущем шаге. Если макет был сформирован с пустыми настройками, процессор также не сможет получить данные.

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

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

  5. Ячейка = ДокументРезультат.НайтиТекст("ОтгрузкаПоследнегоМесяца");
    Если Ячейка <> Неопределено Тогда Ячейка.Текст = НовыйЗаголовок; КонецЕсли;

    Эта часть кода сама по себе корректна для поиска и изменения текста в уже сформированном табличном документе. Проблема в том, что к этому моменту ДокументРезультат уже пуст или не содержит искомого текста, поскольку весь отчет был сформирован некорректно.

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

Когда использовать ПриКомпоновкеРезультата?

Этот обработчик следует использовать для:

Для изменения структуры отчета, таких как заголовки колонок, влияющих на сбор данных, всегда предпочтительнее использовать ПриКомпоновкеДанных.

Заключение

В ходе нашего анализа мы выяснили, что наиболее эффективным и надежным способом динамического изменения заголовка расчетной колонки в отчете СКД, основанном на параметрах отчета (например, периоде), является программное изменение свойств поля в коллекции ВыбранныеПоля или ПоляГруппировки внутри обработчика события ПриКомпоновкеДанных.

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

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

← На главную