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