Как присвоить тип пустому значению свойства ПВХ в запросе 1С?

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

Часто при разработке на платформе 1С мы сталкиваемся с задачей вывода свойств объектов (например, номенклатуры или контрагентов), которые хранятся в Плане Видов Характеристик (ПВХ) и регистрах сведений. Если значение свойства для конкретного объекта не заполнено, в результате левого соединения мы получаем пустое значение. При выгрузке такого результата в таблицу значений на форме пользователю приходится сначала вручную выбирать тип значения (так как реквизит имеет составной тип), и только потом вводить само значение. Разберем по шагам, можно ли динамически присвоить пустому значению тип прямо в запросе и какие существуют оптимальные способы решения этой задачи.

Проанализируем ситуацию: ограничения языка запросов 1С

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

Если мы заранее знаем возможные типы, мы можем перечислить их с помощью оператора ВЫБОР. Посмотрим на пример, как это выглядело бы для пары известных типов:


ВЫБРАТЬ
    СвойстваОбъектов.Ссылка КАК Свойство,
    ВЫБОР 
        КОГДА ЗначенияСвойствОбъектов.Значение ССЫЛКА Справочник.Номенклатура 
            ТОГДА ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
        КОГДА ЗначенияСвойствОбъектов.Значение ССЫЛКА Справочник.Контрагенты 
            ТОГДА ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
        ИНАЧЕ ЗначенияСвойствОбъектов.Значение
    КОНЕЦ КАК Значение
ИЗ
    ПланВидовХарактеристик.СвойстваОбъектов КАК СвойстваОбъектов
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
    ПО ...

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

Решение 1: Программная типизация колонок Таблицы Значений

Вместо того чтобы выгружать результат запроса сразу в нетипизированную таблицу через Запрос.Выполнить().Выгрузить(), рассмотрим более изящный программный путь. Мы можем заранее создать пустую Таблицу Значений и строго задать типы её колонок.

  1. Создаем таблицу значений и описываем нужные колонки.
  2. Для колонки значений получаем ОписаниеТипов из свойств ПВХ.
  3. Когда данные из запроса будут загружаться в такую типизированную таблицу, платформа автоматически приведет NULL или НЕОПРЕДЕЛЕНО к пустой ссылке нужного типа.

В результате пользователю при редактировании ячейки больше не нужно будет выбирать тип — он уже будет установлен.

Решение 2: Постобработка результата запроса

Если нет возможности заранее построить типизированную таблицу, проанализируем решение, которое применил автор исходного вопроса. Оно заключается в обходе полученного результата в цикле и принудительном приведении типов.

Для этого в платформе 1С предусмотрен метод ПривестиЗначение() объекта ОписаниеТипов. Рассмотрим пример:


ТаблицаРезультата = Запрос.Выполнить().Выгрузить();

Для Каждого СтрокаТЗ Из ТаблицаРезультата Цикл
    Если СтрокаТЗ.Значение = Неопределено ИЛИ СтрокаТЗ.Значение = NULL Тогда
        // Получаем описание типов из самого свойства (элемента ПВХ)
        ОписаниеТипаСвойства = СтрокаТЗ.Свойство.ТипЗначения;
        
        // Приводим пустое значение к нужному типу
        СтрокаТЗ.Значение = ОписаниеТипаСвойства.ПривестиЗначение(СтрокаТЗ.Значение);
    КонецЕсли;
КонецЦикла;

Этот код программно заполняет пустые ячейки правильным "пустым значением" конкретного типа (например, пустой ссылкой на нужный справочник или пустой строкой), избавляя пользователя от лишних кликов.

Решение 3: Динамическая генерация текста запроса

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


ТекстУсловия = "";
Для Каждого ЭлементСвойства Из МассивСвойств Цикл
    ТекстУсловия = ТекстУсловия + "
    | КОГДА Свойство = &Свойство_" + Индекс + " ТОГДА ЕСТЬNULL(Значение, &ПустоеЗначение_" + Индекс + ")";
    
    // Передаем в параметры пустую ссылку нужного типа
    Запрос.УстановитьПараметр("Свойство_" + Индекс, ЭлементСвойства);
    Запрос.УстановитьПараметр("ПустоеЗначение_" + Индекс, ЭлементСвойства.ТипЗначения.ПривестиЗначение());
КонецЦикла;

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

Решение 4: Использование Системы Компоновки Данных (СКД)

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

В СКД есть вкладка "Характеристики" (или специальная инструкция {ХАРАКТЕРИСТИКИ ...} прямо в тексте запроса). Выясним причину, почему это лучше: если правильно настроить связь между вашим справочником (объектами), ПВХ (свойствами) и регистром сведений (значениями), СКД сама "под капотом" свяжет типы.

Важное примечание по пустым значениям: при левом соединении с регистром сведений отсутствующая запись вернет NULL. Но если запись в регистре есть, а само значение не было указано, в базе будет храниться НЕОПРЕДЕЛЕНО (из-за составного типа реквизита). Поэтому в запросах всегда проверяйте оба варианта пустых данных, используя конструкцию вида ЕСТЬNULL(Значение, НЕОПРЕДЕЛЕНО).

Выбирайте подходящий метод исходя из контекста вашей задачи. Если вы строите интерфейс ввода данных — лучшим выбором будет программная постобработка или предварительная типизация колонок ТЗ. Если формируете отчет — смело используйте механизмы СКД.

← На главную