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