При разработке отчетов на базе системы компоновки данных (СКД) часто возникает задача: пользователь устанавливает флажок на форме отчета (например, «Учитывать только рабочие дни» или «Исключить выходные»), и в зависимости от этого в одной и той же колонке отчета должны выводиться разные значения.
Попытка перехватить результат запроса в процедуре ПриКомпоновкеРезультата модуля отчета и перезаписать значения непосредственно в ячейках выведенного табличного документа — распространенная ошибка. Разберем, почему прямой ввод новых значений нарушает работу отчета и какие существует правильные технические решения этой задачи.
Проанализируем механику работы СКД. Поток данных в системе компоновки является строго однонаправленным:
Если вы попытаетесь вручную отредактировать сформированный табличный документ или переписать значения после компоновки, платформа не сможет корректно рассчитать групповые и общие итоги по ресурсам, а также сломается стандартный механизм расшифровки. Поэтому обработку пользовательских флагов и параметров всегда необходимо переносить на уровень схемы компоновки данных.
Рассмотрим наилучший по производительности вариант — перенос условий расчета прямо в текст запроса схемы компоновки данных с использованием параметра &УчитыватьВыходные.
Посмотрим на пример реализации запроса:
ВЫБРАТЬ
Взаиморасчеты.Контрагент КАК Контрагент,
ВЫБОР
КОГДА &УчитыватьВыходные ТОГДА
Взаиморасчеты.ДнейПросрочкиКалендарных
ИНАЧЕ
Взаиморасчеты.ДнейПросрочкиРабочих
КОНЕЦ КАК ДниПросрочки
ИЗ
РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты
Разберем по шагам, как настроить передачу пользовательского значения в этот параметр:
УчитыватьВыходные с типом Булево.ПриКомпоновкеРезультата модуля отчета (или при открытии формы) считываем установленное значение. В простом случае, когда параметр выведен в пользовательские настройки, СКД самостоятельно передаст значение флажка в запрос при формировании.Если алгоритм расчета (например, подсчет рабочих дней по производственному календарю) сложно написать на языке запросов, воспользуемся вычисляемыми полями СКД с вызовом экспортной функции общего модуля.
ДниПросрочки.УчетВзаиморасчетовСервер.РассчитатьДни(ДатаНачала, ДатаОкончания, &УчитыватьВыходные)
Важное условие: при использовании внешних функций в СКД платформа по умолчанию может блокировать их исполнение в целях безопасности. Чтобы вызов сработал, в процедуре ПриКомпоновкеРезультата модуля отчета необходимо программно инициализировать процессор компоновки, установив четвертый параметр в значение Истина:
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
Выясним еще один удобный подход, когда в схеме компоновки данных создаются два разных поля (например, ПросрочкаКалендарная и ПросрочкаРабочая), а код отчета динамически управляет тем, какое из полей выводить пользователю.
В процедуре ПриКомпоновкеРезультата мы анализируем пользовательские настройки и подменяем поля в структуре компоновщика:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ИмеющиесяДанные, СтандартнаяОбработка)
// Получаем значение флажка из настроек
ПараметрНастройки = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("БезВыходных"));
Если ПараметрНастройки <> Неопределено И ПараметрНастройки.Использование Тогда
УчитыватьВыходные = ПараметрНастройки.Значение;
Иначе
УчитыватьВыходные = Ложь;
КонецЕсли;
// Управляем составом выбранных полей
ПолеКалендарные = Новый ПолеКомпоновкиДанных("ДниПросрочкиКалендарные");
ПолеРабочие = Новый ПолеКомпоновкиДанных("ДниПросрочкиРабочие");
// В зависимости от флага удаляем лишнее поле и добавляем нужное
// ... (логика обхода ВыбранныеПоля компоновщика настроек)
КонецПроцедуры
Для правильной работы отчетов СКД избегайте ручной постобработки ячеек табличного документа. Используйте перенаправление логики в текст запроса через параметр &Параметр или механизм вычисляемых полей. Это обеспечит высокую скорость работы отчета, корректный расчет итогов и полную функциональность стандартных расшифровок 1С.