Как правильно получить значение справочника в пользовательском выражении СКД?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с Системой компоновки данных (СКД) разработчики часто сталкиваются с необходимостью вычисления различных показателей «на лету». Одним из классических примеров является вывод признака в пользовательском или вычисляемом поле на основе сравнения реквизита с конкретным значением справочника. Например, нам нужно установить флаг или вывести единицу, если результатом осмотра животного является «Брак».

Однако при написании формул в СКД легко запутаться в синтаксисе. Платформа 1С:Предприятие использует несколько различных языков в рамках одного отчета: язык запросов, встроенный язык 1С и язык выражений СКД. Ошибки в их смешивании приводят к непонятным предупреждениям системы, таким как «Поле не найдено» или «Ожидается ключевое слово "Тогда"». В этой статье мы подробно разберем, почему возникают эти ошибки, чем отличается синтаксис в разных частях СКД и как правильно решать подобные задачи.

Анализ первой ошибки: Неверный путь к данным в конструкции Значение()

Рассмотрим выражение, которое изначально пытался использовать разработчик:


Выбор 
    Когда РезультатОсмотра = Значение(Справочник.РезультатыОсмотра.Наименование.Брак) 
    Тогда 1 
    Иначе 0 
Конец

При попытке сохранить такое выражение система выдает ошибку «Поле не найдено». Давайте проанализируем ситуацию и выясним причину ее возникновения.

Конструкция Значение() (или ЗНАЧЕНИЕ() в верхнем регистре) в языке запросов предназначена для получения ссылок на предопределенные элементы, значения перечислений, пустые ссылки или точки системных перечислений. Главное правило этой конструкции — в скобках должен быть указан строгий и прямой путь к метаданным предопределенного элемента, заданный в конфигураторе.

В ошибочном примере была предпринята попытка обратиться к реквизиту наименования через точку: .Наименование.Брак. Парсер запросов не понимает такого обращения. Он ожидает увидеть имя предопределенного элемента, а не обращение к физическим полям таблицы БД. Если в справочнике РезультатыОсмотра создан предопределенный элемент с именем Брак, то правильный синтаксис обращения к нему в запросе будет выглядеть следующим образом:

Значение(Справочник.РезультатыОсмотра.Брак)

Обратите внимание, что здесь нет кавычек, и мы не обращаемся к наименованию или коду. Мы получаем непосредственно ссылку на сам предопределенный элемент базы данных.

Анализ второй ошибки: Использование встроенного языка 1С в СКД

В процессе обсуждения возникла еще одна показательная ошибка при попытке обойти ограничение:


Выбор
    Когда РезультатОсмотра = Справочники.рав_РезультатыОсмотра["Брак"]
        Тогда 1
    Иначе 0
Конец

Данный код вызывает ошибку парсера: «Ожидается ключевое слово "Тогда"» (или «Ожидается ключевое слово "Конец"»). Почему так происходит?

Дело в том, что Язык выражений СКД — это не встроенный язык 1С. Это отдельный декларативный язык со своими правилами и ограничениями. В выражениях пользовательских или вычисляемых полей компоновки данных нельзя использовать конструкции типа Справочники.ИмяСправочника[...], Документы.ИмяДокумента или квадратные скобки для получения элементов по индексу или имени. Парсер СКД просто не понимает эти объекты, спотыкается на них и выдает синтаксическую ошибку в самом неожиданном месте (например, жалуясь на отсутствие слова Тогда).

Различие синтаксиса в запросах и выражениях СКД

Для успешной работы в СКД крайне важно разделять, где именно вы пишете выражение сравнения: в самом тексте запроса или на вкладках вычисляемых/пользовательских полей.

  1. В тексте запроса (Набор данных - Запрос):

    Используем классическую конструкцию языка запросов без кавычек:

    ЗНАЧЕНИЕ(Справочник.РезультатыОсмотра.Брак)

  2. В выражениях СКД (Вкладка «Вычисляемые поля» или «Пользовательские поля»):

    В самом интерфейсе схемы компоновки данных для получения предопределенных элементов используются встроенные системные функции СКД. Путь к элементу в этом случае обязательно передается в виде строки в кавычках:

    ПредопределенноеЗначение("Справочник.РезультатыОсмотра.Брак")

    или сокращенный вариант:

    Значение("Справочник.РезультатыОсмотра.Брак")

    Если в вычисляемом поле написать путь без кавычек (как в запросе), СКД воспримет это как обращение к полям набора данных и сообщит об ошибке.

Что делать, если элементы справочника НЕ являются предопределенными?

В рассматриваемом примере все значения справочника были предопределенными, что значительно упростило задачу. Однако на практике структура данных может быть иной, и нужный элемент может быть создан пользователем непосредственно в режиме «1С:Предприятие». В таком случае функции Значение() и ПредопределенноеЗначение() использовать не получится. Рассмотрим три надежных альтернативных варианта решения этой проблемы.

Вариант 1. Использование параметров СКД (Рекомендуемый способ)

Этот способ является наиболее гибким и профессиональным, так как не привязывает логику отчета к жесткому коду конфигурации.

Разберем реализацию по шагам:

  1. Перейдем на вкладку Параметры в схеме компоновки данных.
  2. Создадим новый параметр, например, &РезультатБрак.
  3. Установим для него тип данных СправочникСсылка.РезультатыОсмотра.
  4. В выражении пользовательского или вычисляемого поля напишем простое сравнение с этим параметром:

Выбор 
    Когда РезультатОсмотра = &РезультатБрак Тогда 1 
    Иначе 0 
Конец

Сам параметр мы можем заполнить несколькими способами. Например, предоставить пользователю возможность самостоятельно выбрать значение в настройках отчета. Если же параметр должен быть заполнен строго определенным элементом по умолчанию, мы можем сделать это программно в модуле объекта отчета в процедуре ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем настройки отчета
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Ищем нужный параметр
    ПараметрБрак = Настройки.ПараметрыДанных.Элементы.Найти("РезультатБрак");
    Если ПараметрБрак <> Неопределено Тогда
        // Находим элемент справочника по уникальному коду или иному признаку
        СсылкаНаБрак = Справочники.РезультатыОсмотра.НайтиПоКоду("000000001");
        
        ПараметрБрак.Значение = СсылкаНаБрак;
        ПараметрБрак.Использование = Истина;
    КонецЕсли;
    
    // Применяем настройки обратно в компоновщик
    КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
    
КонецПроцедуры

Вариант 2. Вызов функции общего модуля

Если в вашей конфигурации часто требуется обращаться к конкретным элементам справочников, хорошей практикой будет создание специальной экспортной функции в общем модуле.

Предположим, у нас есть общий модуль РаботаСПроверками с установленными свойствами «Вызов сервера» и «Клиент (управляемое приложение)». Напишем в нем функцию:


Функция ПолучитьСсылкаНаБрак() Экспорт
    Возврат Справочники.РезультатыОсмотра.НайтиПоРеквизиту("Код", "000000001");
КонецФункции

Теперь мы можем напрямую вызвать эту функцию в выражении пользовательского или вычисляемого поля СКД:


Выбор 
    Когда РезультатОсмотра = РаботаСПроверками.ПолучитьСсылкаНаБрак() Тогда 1 
    Иначе 0 
Конец

Этот метод позволяет централизованно управлять получением конкретных ссылок. Если код элемента в базе данных изменится, вам потребуется исправить его только в одном месте — в общем модуле, не переписывая настройки множества отчетов.

Вариант 3. Сравнение по уникальному реквизиту (Менее надежный способ)

В крайних случаях, когда нет возможности использовать параметры или общие модули, можно прибегнуть к прямому сравнению по текстовому реквизиту (коду или наименованию):


Выбор 
    Когда РезультатОсмотра.Код = "000000001" Тогда 1 
    Иначе 0 
Конец

Важное предупреждение: Данный метод считается плохим стилем разработки. Если пользователь в режиме предприятия изменит код элемента справочника или его наименование, логика отчета мгновенно сломается, и отчет перестанет выводить правильные данные. Используйте этот подход только в самых безвыходных ситуациях или при полной уверенности в неизменности данных.

Резюме

Мы подробно разобрали особенности работы с выражениями СКД при обращении к справочникам. Для успешного решения подобных задач всегда определяйте тип элементов справочника (предопределенные или пользовательские) и место написания выражения (запрос или поля СКД). Правильное разграничение этих понятий позволит вам писать чистый, надежный и быстродействующий код без синтаксических ошибок.

← На главную