Работа с Универсальным отчетом в классических конфигурациях 1С (таких как УПП 1.3, КА 1.1 или УТ 10.3) часто требует ручной модификации запроса для вывода специфических данных, например, дополнительных свойств номенклатуры. Однако новички часто сталкиваются с ситуацией: поле в настройках отчета появилось, колонка в таблице отображается, но она абсолютно пустая. Рассмотрим подробнее, почему это происходит и как правильно добавить поле из регистра сведений ЗначенияСвойствОбъектов в структуру запроса.
Первая и самая распространенная ошибка при ручном редактировании текста запроса — это невнимательность при использовании псевдонимов (алиасов) таблиц. Проанализируем ситуацию: когда мы добавляем несколько левых соединений к одной и той же таблице (например, к регистру ЗначенияСвойствОбъектов), мы обязаны давать каждой таблице уникальное имя, чтобы система понимала, к какому именно набору данных мы обращаемся.
Разберем пример ошибки из практики. Программист пытается соединить таблицу продаж с регистром свойств для получения "Норматива запаса":
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов2
ПО ПродажиОбороты.Номенклатура = ЗначенияСвойствОбъектов2.Объект
И (ЗначенияСвойствОбъектов.Свойство.Наименование = "Норматив запасов, дн")
Выясним причину, по которой это соединение не сработает корректно. Обратите внимание: в условии ПО таблица названа ЗначенияСвойствОбъектов2, а в условии фильтрации по свойству обращение идет к ЗначенияСвойствОбъектов (без двойки). В сложном запросе, где таких соединений может быть три и более, Построитель отчета может либо выдать ошибку, либо (что чаще) вернуть NULL, так как условие соединения не будет выполнено. Всегда проверяйте соответствие имен таблиц во всех частях условия ПО.
Если ваш отчет базируется на запросе с использованием оператора ОБЪЕДИНИТЬ ВСЕ, добавление поля в одну часть запроса — это только половина дела. В Универсальном отчете часто объединяются данные из разных источников (например, обороты продаж и остатки по заказам). Рассмотрим структуру такого запроса:
Значение КАК НормаЗапас.NULL КАК НормаЗапас.Проанализируем ситуацию: если отчет формируется по данным, которые попадают только во вторую часть объединения, вы гарантированно получите пустую колонку, так как там жестко прописано пустое значение. Чтобы исправить это, необходимо продублировать логику соединения во всех частях запроса, которые объединяются. Если поле должно выводиться для номенклатуры, левое соединение с регистром свойств должно присутствовать в каждом блоке ВЫБРАТЬ.
Универсальный отчет управляется Построителем отчета. Для того чтобы поле было доступно для выбора, группировки или отбора, оно должно быть описано в специальных расширениях языка запросов — в фигурных скобках {}. Разберем по шагам правильное описание поля:
В блоке {ВЫБРАТЬ...} мы указываем поля, которые пользователь сможет добавить в колонки. Если ваше поле числовое (например, "Норма запас дн"), не используйте конструкцию .*. Символ "звездочка" после точки предназначен только для ссылочных типов (справочники, документы), чтобы Построитель мог "вытащить" реквизиты этого объекта. Для чисел это избыточно и может привести к некорректной работе вывода.
Правильный пример описания числового показателя в секции выбора:
|{ВЫБРАТЬ
| Номенклатура.*,
| КоличествоОборот КАК КоличествоОтгружено,
| НормаЗапас}
Поскольку значение свойства в регистре ЗначенияСвойствОбъектов хранится в типе Характеристика.СвойстваОбъектов (составной тип данных), Построитель отчета иногда не может самостоятельно определить, как именно форматировать это значение в колонке. Чтобы избежать пустых значений или странного поведения интерфейса, рекомендуется использовать функцию ВЫРАЗИТЬ.
Рассмотрим, как это выглядит в коде запроса:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ВЫРАЗИТЬ(ЗначенияСвойствОбъектов2.Значение КАК ЧИСЛО(15, 3)) КАК НормаЗапас
Это гарантирует, что система будет ожидать число, и Универсальный отчет сможет применить к нему агрегатные функции (например, СУММА или СРЕДНЕЕ), если вы добавите это поле в итоги.
После того как запрос исправлен, нужно убедиться, что код инициализации в модуле отчета написан верно. Выясним, какие методы за что отвечают:
Метод мСтруктураПредставлениеПолей.Вставить отвечает за то, какое имя увидит пользователь в списке доступных полей. А метод ДобавитьПоказатель сообщает отчету, что данное поле является ресурсом (числовым значением), которое можно суммировать.
// Добавляем представление поля для настройки состава колонок
УниверсальныйОтчет.мСтруктураПредставлениеПолей.Вставить("НормаЗапас", "Норма запаса (дн.)");
// Добавляем показатель, чтобы поле можно было выводить как числовой ресурс
// Истина в третьем параметре означает, что поле будет выбрано по умолчанию
УниверсальныйОтчет.ДобавитьПоказатель("НормаЗапас", "Норма запаса (дн.)", Истина, "ЧЦ=15; ЧДЦ=3");
Если вы внесли все правки в код и запрос, но колонка в запущенном отчете все равно пустая или вовсе не появилась, велика вероятность, что сработал механизм сохранения настроек. 1С сохраняет последние настройки отчета для каждого пользователя. Ваши программные изменения (например, добавление показателя по умолчанию) могут "перекрываться" старой сохраненной настройкой, в которой этого поля еще не было.
Что нужно сделать:
В процессе отладки также полезно проверить результат выполнения запроса непосредственно в коде. Поставьте точку останова после выполнения метода Построитель.Выполнить() и проверьте таблицу значений: Построитель.Результат.Выгрузить(). Если в этой таблице колонка НормаЗапас заполнена, значит, проблема в визуализации (настройках колонок). Если таблица пустая или колонка содержит NULL — ищите ошибку в логике соединений JOIN или параметрах запроса.