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