При работе с Системой компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда при написании выражения в вычисляемом поле система выдает ошибку о том, что указанное поле не найдено. Это происходит даже в тех случаях, когда поле явно присутствует в тексте запроса и выбрано на закладке «Наборы данных». В этой статье мы подробно разберем причины возникновения этой ошибки, выясним, чем «Путь к данным» отличается от псевдонима в запросе, и рассмотрим лучшие практики написания выражений для вычисляемых полей.
Проанализируем типичную ситуацию. Программист пишет запрос к документу ЗаказПокупателя и дает таблице псевдоним ЗаказПокупателя. В тексте запроса это выглядит так:
ВЫБРАТЬ
ЗаказПокупателя.ВалютаДокумента,
ЗаказПокупателя.СуммаДокумента
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
Пытаясь создать вычисляемое поле, разработчик использует привычный синтаксис обращения через точку: ЗаказПокупателя.СуммаДокумента. Однако СКД выдает ошибку. Выясним причину: Система компоновки данных работает не напрямую с текстом запроса, а с итоговым набором полей, которые сформировались в результате выполнения этого запроса.
Рассмотрим, как это устроено внутри. На вкладке «Наборы данных» у каждого выбранного поля есть колонка «Путь к данным». По умолчанию, если вы не меняли псевдонимы в запросе вручную, СКД назначает путь к данным, совпадающий с именем поля в базе. Если в запросе выбрано ЗаказПокупателя.ВалютаДокумента, то путем к данным будет просто ВалютаДокумента. Обращение к объекту через алиас таблицы (ЗаказПокупателя) в вычисляемых полях недоступно, так как этот объект существует только внутри SQL-контекста запроса, но не в контексте компоновки.
Правило: В вычисляемом поле можно использовать только те имена полей, которые указаны в колонке «Путь к данным» на первой закладке конструктора СКД.
Рассмотрим правильный вариант выражения для задачи автора. Если нам нужно выделить сумму только для валюты "BYN", наше выражение должно выглядеть следующим образом:
ВЫБОР
КОГДА ВалютаДокумента.Код = "933"
ТОГДА СуммаДокумента
ИНАЧЕ 0
КОНЕЦ
Обратите внимание на несколько важных моментов, которые мы здесь применили:
ЗаказПокупателя.Код через точку от поля ВалютаДокумента. Это возможно, если ВалютаДокумента является ссылочным типом.Сравнение со строковыми литералами вроде "BYN" — это не самый надежный способ. Если в справочнике Валюты есть предопределенные элементы, правильнее использовать функцию ЗНАЧЕНИЕ(). Посмотрим на пример кода, который будет работать максимально стабильно:
ВЫБОР
КОГДА ВалютаДокумента = ЗНАЧЕНИЕ(Справочник.Валюты.БелорусскийРубль)
ТОГДА СуммаДокумента
ИНАЧЕ 0
КОНЕЦ
Такой подход гарантирует, что даже если бухгалтер переименует "BYN" в "Бел. рубль" или изменит код валюты, ваш отчет продолжит работать корректно, так как привязка идет к внутреннему идентификатору (UUID) предопределенного элемента.
В ходе обсуждения на форуме прозвучал важный совет: стараться не получать табличные части в основном запросе СКД без явной необходимости. Разберем, почему это важно для вычисляемых полей и итогов отчета.
Когда мы выбираем в запросе ЗаказПокупателя.Товары.(Сумма, Цена), СКД выполняет неявное соединение (LEFT JOIN) основной таблицы документа с его строками. Если в одном заказе 50 строк товаров, то в результирующей выборке строка документа с его общей суммой повторится 50 раз. Если вы создадите вычисляемое поле, которое просто суммирует СуммаДокумента, вы получите огромную ошибку в итогах (сумма будет завышена в 50 раз).
Для корректной работы в таких случаях необходимо:
Максимум(СуммаДокумента) или Среднее(СуммаДокумента) в разрезе документа, чтобы дублирующиеся строки не суммировались.Проанализируем еще одну потенциальную проблему. Если ваше вычисляемое поле использует данные из левого соединения (например, вы присоединяете данные о менеджере или договоре), поле может содержать значение NULL. В языке выражений СКД операции с NULL всегда возвращают NULL.
Допустим, вы пишете: СуммаДокумента - СуммаСкидки. Если СуммаСкидки окажется NULL, результат всего выражения тоже будет NULL, и в отчете вы увидите пустоту. Чтобы этого избежать, используем функцию ЕстьNULL:
ЕстьNULL(СуммаДокумента, 0) - ЕстьNULL(СуммаСкидки, 0)
Иногда логика вычисления слишком сложна для оператора ВЫБОР. В СКД мы можем вызывать экспортные функции из общих модулей прямо в вычисляемом поле.
Условия для использования функции:
Экспорт.Пример обращения к функции в выражении вычисляемого поля:
МойОбщийМодуль.РассчитатьНалог(СуммаДокумента, СтавкаНДС)
Подведем итоги нашего анализа. Чтобы успешно использовать вычисляемые поля в СКД и не встречать ошибку «Поле не найдено», всегда следуйте этим шагам:
1. Проверьте путь к данным. Откройте вкладку «Наборы данных» и убедитесь, что имя поля, которое вы используете в формуле, совпадает с тем, что написано в колонке «Путь к данным». Забудьте про алиасы таблиц из запроса.
2. Используйте типизацию. Если вы сравниваете ссылочное поле со строкой (код, наименование), делайте это через точку (Валюта.Код). Но лучше используйте ЗНАЧЕНИЕ() или параметры компоновки.
3. Следите за типами. Все ветки оператора ВЫБОР должны возвращать значения одного типа. Нельзя в одной ветке вернуть число, а в другой — строку.
4. Проверяйте наличие NULL. Всегда оборачивайте потенциально пустые поля в функцию ЕстьNULL(), чтобы не терять данные при расчетах.
Соблюдение этих простых правил позволит вам создавать сложные и отказоустойчивые отчеты, избегая типичных ошибок начинающих разработчиков 1С.