Как в запросе 1С получить значение дополнительного реквизита или ПВХ через ЗНАЧЕНИЕ

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

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

В чем заключается главная ошибка при использовании ЗНАЧЕНИЕ() для ПВХ?

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


НоменклатураДополнительныеРеквизиты.Свойство = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ДополнительныеРеквизиты.ДопустимоеОтклонение).Значение

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


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

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

Когда мы пишем ЗНАЧЕНИЕ(ПланВидовХарактеристик.ДополнительныеРеквизиты.ДопустимоеОтклонение), система возвращает нам ссылку на сам элемент плана видов характеристик (ПВХ), то есть на само свойство «Допустимое отклонение» как на объект метаданных (его описание, тип, уникальный идентификатор).

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

Где на самом деле хранятся значения дополнительных реквизитов?

В типовых конфигурациях фирмы 1С (таких как ERP, Комплексная автоматизация, Управление торговлей, УНФ), построенных на базе Библиотеки стандартных подсистем (БСП), архитектура хранения свойств разделена на два направления:

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

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

Решение 1. Получение значения предопределенного свойства в запросе

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

Обратите внимание на синтаксис: внутри функции ЗНАЧЕНИЕ() имя типа ПВХ всегда пишется в единственном числе — ПланВидовХарактеристик (а не в множественном «ПланыВидовХарактеристик»).

Проанализируем правильный пример запроса для получения значения предопределенного реквизита «Допустимое отклонение» из табличной части номенклатуры:


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

В данном запросе мы обращаемся к табличной части ДополнительныеРеквизиты справочника Номенклатура. С помощью секции ГДЕ мы отсекаем все лишние строки, оставляя только те, у которых в колонке Свойство записана ссылка на наше предопределенное свойство «Допустимое отклонение». Из этих строк мы и забираем поле Значение.

Решение 2. Обязательное использование функции ВЫРАЗИТЬ()

Поскольку поле Значение в табличных частях дополнительных реквизитов БСП имеет составной тип данных (в него могут записываться числа, строки, даты, ссылки на другие справочники), СУБД не знает точного типа данных в процессе выполнения запроса.

Если вам в дальнейшем нужно производить с полученным значением какие-либо операции (например, складывать числа, сравнивать даты или выводить реквизиты ссылочного объекта), СУБД выполнит неоптимальное неявное приведение типов (JOIN ко всем возможным таблицам). Чтобы избежать этого и повысить производительность, обязательно используйте функцию ВЫРАЗИТЬ().

Посмотрим на пример приведения значения к числовому типу данных:


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

Использование ВЫРАЗИТЬ() строго типизирует результирующую колонку выборки, что гарантирует высокую скорость работы и предотвращает потенциальные ошибки СУБД.

Решение 3. Работа с динамическими (пользовательскими) свойствами

В реальной практике 99% дополнительных реквизитов и сведений создаются пользователями непосредственно в режиме «1С:Предприятие». У таких элементов нет предопределенного имени в конфигураторе, а значит, использовать конструкцию ЗНАЧЕНИЕ() для них принципиально невозможно.

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

Рассмотрим детально этот шаблон разработки:


// 1. Находим свойство программно по его имени для разработчиков
ИмяСвойства = "ДопустимоеОтклонение";
СвойствоОтклонение = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", ИмяСвойства);

Если НЕ ЗначениеЗаполнено(СвойствоОтклонение) Тогда
	ВызватьИсключение "Критическая ошибка: в системе не настроен дополнительный реквизит '" + ИмяСвойства + "'!";
КонецЕсли;

// 2. Строим запрос с передачей параметра свойства
Запрос = Новый Запрос;
Запрос.Текст = 
	"ВЫБРАТЬ
	|	НоменклатураДопРеквизиты.Ссылка КАК Номенклатура,
	|	ВЫРАЗИТЬ(НоменклатураДопРеквизиты.Значение КАК Число(15, 2)) КАК ЗначениеОтклонения
	|ИЗ
	|	Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДопРеквизиты
	|ГДЕ
	|	НоменклатураДопРеквизиты.Свойство = &СвойствоОтклонение";

Запрос.УстановитьПараметр("СвойствоОтклонение", СвойствоОтклонение);
РезультатЗапроса = Запрос.Выполнить();

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

Решение 4. Получение значения свойства через программный интерфейс БСП (без написания запросов)

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

В составе БСП есть общий модуль УправлениеСвойствами. Рассмотрим два удобных метода этого модуля, которые значительно упрощают разработку.

Вариант А. Получение значения конкретного реквизита для одного объекта:


// Сначала находим само свойство (или получаем его предопределенную ссылку)
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "ДопустимоеОтклонение");

// Получаем значение свойства для конкретной номенклатуры с помощью БСП
ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаНоменклатуру, Свойство);

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

Вариант Б. Получение всех заполненных дополнительных реквизитов и сведений объекта:


// Метод возвращает таблицу значений со всеми свойствами данного объекта
ТаблицаСвойств = УправлениеСвойствами.ЗначенияСвойств(СсылкаНаНоменклатуру);

Для Каждого СтрокаСвойства Из ТаблицаСвойств Цикл
	Сообщить("Свойство: " + СтрокаСвойства.Свойство + " | Значение: " + СтрокаСвойства.Значение);
КонецЦикла;

Использование готовых методов БСП гарантирует, что ваш код останется работоспособным даже при обновлении конфигурации и изменении внутренней структуры хранения данных платформы 1С.

← На главную