При проектировании отчетов на базе Системы компоновки данных (СКД) разработчики часто сталкиваются с требованием заказчиков выводить динамические данные в шапку таблицы. Классический пример — колонка с суммами или остатками, в заголовке которой должна быть указана конкретная дата (например, «Остаток на 31.12.2023» вместо статичного «Остаток»).
Стандартный интерфейс настройки СКД не позволяет напрямую указать параметр в качестве имени колонки. Если мы попробуем написать имя параметра в заголовке поля, платформа выведет его как обычную строку. В этой статье мы подробно разберем, как обойти это ограничение. Мы рассмотрим несколько эффективных методов: от элегантного бескодового решения с использованием условного оформления до универсальных программных методов обработки настроек компоновщика.
Этот способ является наиболее предпочтительным, так как он сохраняет отчет на стандартных настройках СКД, не требует написания кода в модулях и работает полностью в рамках декларативной модели 1С. Мы обойдем ограничение условного оформления, при котором прямая подстановка параметра выводит его техническое имя (например, &КонецПериода), с помощью промежуточного вычисляемого поля.
Разберем этот алгоритм по шагам:
ЗаголовокСДатой."Остаток на " + Формат(&КонецПериода, "ДЛФ=Д").ЗаголовокСДатой.СуммаОстаток.Проанализируем, как это работает. При формировании отчета СКД рассчитывает значение вычисляемого поля ЗаголовокСДатой, подставляя туда актуальное отформатированное значение параметра &КонецПериода. Механизм условного оформления берет полученный текст и заменяет им стандартную шапку выбранной колонки. Благодаря правильной области использования, сами данные в строках отчета остаются нетронутыми, а заголовок становится полностью динамическим.
Иногда бескодовый вариант не подходит — например, когда логика формирования заголовка слишком сложна для выражений СКД или зависит от нескольких внешних факторов. В таких случаях разработчики используют программный код в модуле отчета.
Рассмотрим популярную ошибку. Начинающие программисты часто пытаются изменить заголовок непосредственно в структуре схемы компоновки данных, обращаясь к коллекции полей набора данных. Делать так крайне не рекомендуется, поскольку измененная глобальная схема кэшируется на сервере, что может привести к коллизиям при работе нескольких пользователей с одним отчетом. Правильный путь — менять настройки конкретного сеанса компоновки в процедуре ПриКомпоновкеРезультата модуля отчета.
Рассмотрим пример кода, реализующий этот подход:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем текущие настройки отчета с учетом пользовательских изменений
ТекущиеНастройки = КомпоновщикНастроек.ПолучитьНастройки();
// Извлекаем значение необходимого нам параметра
ПараметрКонецПериода = ТекущиеНастройки.ПараметрыДанных.Найти("КонецПериода");
Если ПараметрКонецПериода <> Неопределено И ПараметрКонецПериода.Использование Тогда
// Форматируем дату для красивого отображения в шапке
ДатаСтрокой = Формат(ПараметрКонецПериода.Значение, "ДФ=dd.MM.yyyy");
НовыйЗаголовок = "Сумма оборот на " + ДатаСтрокой;
// Ищем нужное поле непосредственно в выбранных полях компоновщика
ПолеНастройки = КомпоновщикНастроек.Настройки.ВыбранныеПоля.Элементы.Найти("СуммаОборотКт");
Если ПолеНастройки <> Неопределено Тогда
ПолеНастройки.Заголовок = НовыйЗаголовок;
ПолеНастройки.ИспользованиеЗаголовка = ИспользованиеЗаголовкаКомпоновкиДанных.Использовать;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В данном примере мы манипулируем свойствами поля внутри коллекции ВыбранныеПоля текущего компоновщика настроек. Это абсолютно безопасно для многопользовательской работы и гарантирует корректное отображение заголовков у каждого конкретного пользователя.
Если в вашем отчете десятки колонок и пользователь имеет возможность самостоятельно добавлять, удалять или менять их местами, жестко прописывать имена полей в коде становится неудобно. Для таких систем применяется гибкий механизм шаблонизации.
Идея заключается в том, что в конфигураторе (или пользовательском режиме) разработчик или пользователь задает заголовок поля в специальном формате шаблона, например: Продажи за #ПериодОтчета или Остаток на #КонецПериода. Программа перед выводом отчета автоматически сканирует все выбранные поля, находит символ решетки #, извлекает имя параметра, получает его значение и выполняет подстановку.
Реализуем этот механизм с помощью рекурсивного обхода структуры выбранных полей в модуле отчета:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
Настройки = КомпоновщикНастроек.Настройки;
ПараметрыДанных = Настройки.ПараметрыДанных;
// Запускаем рекурсивную обработку полей (учитывая возможные группировки полей)
ОбработатьВыбранныеПоляРекурсивно(Настройки.ВыбранныеПоля.Элементы, ПараметрыДанных);
КонецПроцедуры
Процедура ОбработатьВыбранныеПоляРекурсивно(КоллекцияЭлементов, ПараметрыДанных)
Для Каждого Элемент Из КоллекцияЭлементов Цикл
// Если это группа полей (папка), заходим внутрь нее
Если ТипЗнч(Элемент) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
ОбработатьВыбранныеПоляРекурсивно(Элемент.Элементы, ПараметрыДанных);
// Если это обычное выбранное поле
ИначеЕсли ТипЗнч(Элемент) = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
СтрокаЗаголовка = Элемент.Заголовок;
ИндексШаблона = Найти(СтрокаЗаголовка, "#");
Если ИндексШаблона > 0 Тогда
// Выделяем имя параметра, идущее после символа '#'
ИмяПараметра = СокрЛП(Сред(СтрокаЗаголовка, ИндексШаблона + 1));
// Находим значение параметра в настройках компоновщика
ПараметрСхемы = ПараметрыДанных.Найти(ИмяПараметра);
Если ПараметрСхемы <> Неопределено И ПараметрСхемы.Использование Тогда
// Форматируем значение в зависимости от его типа
ЗначениеСтрокой = "";
Если ТипЗнч(ПараметрСхемы.Value) = Тип("Дата") Тогда
ЗначениеСтрокой = Формат(ПараметрСхемы.Value, "ДФ=dd.MM.yyyy");
Иначе
ЗначениеСтрокой = Строка(ПараметрСхемы.Value);
КонецЕсли;
// Собираем новый заголовок и заменяем шаблон значением
ШаблонТекста = Лев(СтрокаЗаголовка, ИндексШаблона - 1);
Элемент.Заголовок = ШаблонТекста + " " + ЗначениеСтрокой;
Элемент.ИспользованиеЗаголовка = ИспользованиеЗаголовкаКомпоновкиДанных.Использовать;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот подход невероятно удобен для универсальных отчетов. Пользователь может самостоятельно настраивать структуру колонок, переименовывать их в пользовательском интерфейсе с использованием маски #Параметр, а программный модуль автоматически сформирует красивые и корректные шапки таблиц.
Если отчет спроектирован в виде кросс-таблицы (где колонками выступают группировки по периодам, складам или контрагентам), стандартное изменение заголовков выбранных полей ресурсов работать не будет. В этом случае колонки формируются динамически на основании результатов запроса. Для решения этой задачи можно использовать пример настройки динамического вывода недель и месяцев в шапке отчета СКД.
Для корректной работы с кросс-таблицами рекомендуется использовать следующие приемы:
ПериодШапка)."Январь 2024" или "Неделя №2").Мы детально изучили различные методики динамического формирования заголовков колонок СКД. Выбор конкретного метода зависит от архитектуры вашего решения: для простых локальных задач идеально подойдет бескодовый вариант с условным оформлением, а для сложных корпоративных отчетов с вариативной структурой лучшим выбором станет универсальный программный обход компоновщика настроек. Также в качестве альтернативы можно использовать готовый шаблон отчета для СКД с параметризованными заголовками полей, в котором эта логика уже реализована.