При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью гибкой фильтрации данных. Одной из типичных задач является проверка типа параметра или значения поля. В стандартном языке запросов 1С существуют конструкции ЗНАЧЕНИЕ(), ТИП() и ТИПЗНАЧЕНИЯ(), но их возможности ограничены типами, существующими непосредственно в базе данных. Рассмотрим подробнее, как работают эти конструкции, и как обойти их ограничения при работе с коллекциями, такими как Массив или Список значений.
Функция ЗНАЧЕНИЕ() позволяет обратиться к конкретным объектам метаданных или системным перечислениям прямо в тексте запроса. Это статический метод, который возвращает ссылку на объект. Рассмотрим основные варианты использования, которые часто применяются в СКД:
ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка), ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка).
ЗНАЧЕНИЕ(Справочник.Валюты.Рубль).
ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Новый).
ЗНАЧЕНИЕ(ДатаВремя.ДД.ММ.ГГГГ) или ЗНАЧЕНИЕ(ДатаВремя.1.1.0001).
Проанализируем ситуацию, когда нам нужно проверить тип данных поля. Для этого используется пара функций ТИПЗНАЧЕНИЯ() и ТИП(). Это особенно актуально для полей составного типа. Например, если поле Владелец может быть как справочником Контрагенты, так и ФизическиеЛица, мы можем написать условие:
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(Заказ.Контрагент) = ТИП(Справочник.Контрагенты)
ТОГДА "Юридическое лицо"
ИНАЧЕ "Прочее"
КОНЕЦ
Выясним причину, по которой стандартная конструкция ТИП(Массив) не работает. В языке запросов 1С (и, соответственно, в СКД) можно использовать только те типы данных, которые определены в метаданных (таблицы БД) или являются примитивными (строка, число, дата, булево). Массив и Список значений — это типы программного интерфейса (языка 1С), а не базы данных. Поэтому попытка написать ТИП(Массив) приведет к синтаксической ошибке.
Рассмотрим пример из практики: автор темы хотел реализовать проверку, если параметр является списком, то применять оператор В ИЕРАРХИИ, а если нет — выполнять другую логику. Попытка использовать ВЫБОР КОГДА с проверкой на тип коллекции внутри запроса обречена на провал.
Разберем самый правильный и "нативный" способ решения задачи в рамках СКД. Вместо того чтобы пытаться программно определить тип параметра в ВЫБОР КОГДА, воспользуемся механизмом фигурных скобок {}. СКД обладает мощным процессором, который сам модифицирует текст запроса перед исполнением.
Если мы напишем условие в блоке ГДЕ следующим образом:
ГДЕ ЗаказПокупателя.Ответственный {В (&ВозможныйСЗИлиМассив)}
Проанализируем, что произойдет:
&ВозможныйСЗИлиМассив, СКД просто удалит это условие из итогового запроса.ЗаказПокупателя.Ответственный = &ВозможныйСЗИлиМассив.В (...).Таким образом, нам не нужно вручную проверять тип параметра — система компоновки сделает это за нас на этапе генерации макета.
Если логика требует обязательной проверки типа именно в коде или в выражениях параметров, мы можем воспользоваться функциями общих модулей. Посмотрим на алгоритм настройки:
РаботаСПараметрамиСКД) с флагами Сервер и Вызов сервера.
Функция ЭтоКоллекция(ЗначениеПараметра) Экспорт
Возврат ТипЗнч(ЗначениеПараметра) = Тип("Массив")
ИЛИ ТипЗнч(ЗначениеПараметра) = Тип("СписокЗначений");
КонецФункции
РаботаСПараметрамиСКД.ЭтоКоллекция(&Параметр).
Важно помнить, что использование функций общих модулей должно быть разрешено в настройках процессора компоновки данных при программном выводе отчета.
Рассмотрим ситуацию, когда мы не можем менять общие модули. В этом случае можно использовать "флаг-переключатель", как предлагалось в сообщении форума. Мы добавляем второй параметр &ОтборПоОтветственным (Булево). Логика в запросе будет выглядеть так:
ГДЕ (НЕ &ОтборПоОтветственным)
ИЛИ (ЗаказПокупателя.Ответственный В ИЕРАРХИИ (&ВозможныйСЗИлиМассив))
Проанализируем эту конструкцию. Если &ОтборПоОтветственным равно Ложь, первая часть условия (НЕ &ОтборПоОтветственным) всегда истинна, и вторая часть (с проверкой в иерархии) не влияет на результат. Если же флаг установлен в Истина, начинает работать отбор по списку или массиву.
Для более глубокого понимания работы СКД, рассмотрим, какие еще объекты мы можем получать через ЗНАЧЕНИЕ(), помимо стандартных справочников и документов:
ЗНАЧЕНИЕ(ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПустаяСсылка).ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ТоварыНаСкладах).ЗНАЧЕНИЕ(ПланОбмена.СинхронизацияДанных.ПустаяСсылка).Подводя итог, можно сказать, что прямое использование ТИП(Массив) в запросе невозможно из-за архитектуры платформы 1С. Однако, СКД предоставляет гибкие инструменты для обхода этого ограничения:
ТИПЗНАЧЕНИЯ() в запросе работает только с типами, которые "знает" база данных (ссылки, строки, числа и т.д.).Разберем по шагам выбор решения: если ваша задача — просто фильтровать данные, всегда выбирайте расширение языка запросов. Если же вам нужно менять структуру отчета или выполнять сложные расчеты в зависимости от типа входного параметра, переходите к использованию внешних функций в выражениях СКД. Это сделает ваш отчет более надежным и понятным для поддержки другими разработчиками.