Как использовать конструкции ЗНАЧЕНИЕ() и ТИП() в СКД и можно ли проверить параметр на тип Массив?

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

При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью гибкой фильтрации данных. Одной из типичных задач является проверка типа параметра или значения поля. В стандартном языке запросов 1С существуют конструкции ЗНАЧЕНИЕ(), ТИП() и ТИПЗНАЧЕНИЯ(), но их возможности ограничены типами, существующими непосредственно в базе данных. Рассмотрим подробнее, как работают эти конструкции, и как обойти их ограничения при работе с коллекциями, такими как Массив или Список значений.

Базовое использование конструкции ЗНАЧЕНИЕ()

Функция ЗНАЧЕНИЕ() позволяет обратиться к конкретным объектам метаданных или системным перечислениям прямо в тексте запроса. Это статический метод, который возвращает ссылку на объект. Рассмотрим основные варианты использования, которые часто применяются в СКД:

Проанализируем ситуацию, когда нам нужно проверить тип данных поля. Для этого используется пара функций ТИПЗНАЧЕНИЯ() и ТИП(). Это особенно актуально для полей составного типа. Например, если поле Владелец может быть как справочником Контрагенты, так и ФизическиеЛица, мы можем написать условие:


ВЫБОР
    КОГДА ТИПЗНАЧЕНИЯ(Заказ.Контрагент) = ТИП(Справочник.Контрагенты)
        ТОГДА "Юридическое лицо"
    ИНАЧЕ "Прочее"
КОНЕЦ

Проблема проверки на тип Массив или Список значений

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

Рассмотрим пример из практики: автор темы хотел реализовать проверку, если параметр является списком, то применять оператор В ИЕРАРХИИ, а если нет — выполнять другую логику. Попытка использовать ВЫБОР КОГДА с проверкой на тип коллекции внутри запроса обречена на провал.

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

Разберем самый правильный и "нативный" способ решения задачи в рамках СКД. Вместо того чтобы пытаться программно определить тип параметра в ВЫБОР КОГДА, воспользуемся механизмом фигурных скобок {}. СКД обладает мощным процессором, который сам модифицирует текст запроса перед исполнением.

Если мы напишем условие в блоке ГДЕ следующим образом:

ГДЕ ЗаказПокупателя.Ответственный {В (&ВозможныйСЗИлиМассив)}

Проанализируем, что произойдет:

  1. Если пользователь не заполнил параметр &ВозможныйСЗИлиМассив, СКД просто удалит это условие из итогового запроса.
  2. Если в параметр передан одиночный элемент (ссылка), СКД преобразует это в ЗаказПокупателя.Ответственный = &ВозможныйСЗИлиМассив.
  3. Если передан Массив или Список значений, СКД автоматически использует оператор В (...).

Таким образом, нам не нужно вручную проверять тип параметра — система компоновки сделает это за нас на этапе генерации макета.

Решение 2: Использование функций общих модулей

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

  1. Создадим в конфигурации общий модуль (например, РаботаСПараметрамиСКД) с флагами Сервер и Вызов сервера.
  2. Напишем функцию, проверяющую тип:
    
    Функция ЭтоКоллекция(ЗначениеПараметра) Экспорт
        Возврат ТипЗнч(ЗначениеПараметра) = Тип("Массив") 
            ИЛИ ТипЗнч(ЗначениеПараметра) = Тип("СписокЗначений");
    КонецФункции
    
  3. В СКД на вкладке Параметры в поле Выражение мы можем вызвать эту функцию: РаботаСПараметрамиСКД.ЭтоКоллекция(&Параметр).

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

Решение 3: Логическая подмена через вспомогательный параметр

Рассмотрим ситуацию, когда мы не можем менять общие модули. В этом случае можно использовать "флаг-переключатель", как предлагалось в сообщении форума. Мы добавляем второй параметр &ОтборПоОтветственным (Булево). Логика в запросе будет выглядеть так:


ГДЕ (НЕ &ОтборПоОтветственным) 
    ИЛИ (ЗаказПокупателя.Ответственный В ИЕРАРХИИ (&ВозможныйСЗИлиМассив))

Проанализируем эту конструкцию. Если &ОтборПоОтветственным равно Ложь, первая часть условия (НЕ &ОтборПоОтветственным) всегда истинна, и вторая часть (с проверкой в иерархии) не влияет на результат. Если же флаг установлен в Истина, начинает работать отбор по списку или массиву.

Расширенный список объектов для функции ЗНАЧЕНИЕ()

Для более глубокого понимания работы СКД, рассмотрим, какие еще объекты мы можем получать через ЗНАЧЕНИЕ(), помимо стандартных справочников и документов:

Итоги и рекомендации

Подводя итог, можно сказать, что прямое использование ТИП(Массив) в запросе невозможно из-за архитектуры платформы 1С. Однако, СКД предоставляет гибкие инструменты для обхода этого ограничения:

  1. Для простых отборов используйте фигурные скобки (расширение языка запросов), это позволит СКД автоматически обрабатывать и одиночные значения, и массивы.
  2. Для сложной логики внутри вычисляемых полей или параметров используйте функции общих модулей.
  3. Помните, что ТИПЗНАЧЕНИЯ() в запросе работает только с типами, которые "знает" база данных (ссылки, строки, числа и т.д.).

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

← На главную