Разработка и Конфигурация · 11 мин
Как программно получить дополнительный реквизит в 1С
Как программно получить значение дополнительного реквизита в 1С: через БСП, запрос к табличной части и свойство по имени. Примеры кода, ошибки и FAQ.
Дополнительные реквизиты и сведения в 1С хранятся не в реквизитах объекта, а в отдельных таблицах, поэтому обратиться к ним напрямую через точку, как к обычному полю, нельзя. Попытка написать Справочник.Номенклатура.Цвет завершится ошибкой, если «Цвет» — это дополнительный реквизит, добавленный через механизм БСП без изменения конфигурации.
Способ получения значения зависит от того, как реализован механизм в вашей конфигурации. В типовых решениях на базе Библиотеки стандартных подсистем (УТ 11, ERP, КА, БП 3.0 и другие) используется подсистема «Свойства»: дополнительные реквизиты хранятся в табличной части объекта «ДополнительныеРеквизиты», а дополнительные сведения — в регистре сведений «ДополнительныеСведения». В самописных конфигурациях механизм может быть иным.
Ниже разобраны рабочие способы: чтение через табличную часть объекта, запросом, через функции БСП, а также получение значения дополнительного сведения. Каждый вариант сопровождается примером кода и указанием, когда его применять.
Как устроено хранение дополнительных реквизитов
Механизм дополнительных реквизитов и сведений в БСП разделяет два понятия. Дополнительный реквизит «принадлежит» объекту и хранится прямо в его табличной части ДополнительныеРеквизиты — она видна в дереве метаданных у справочника или документа. Дополнительное сведение хранится централизованно — в регистре сведений ДополнительныеСведения с измерением «Объект» и измерением «Свойство».
Описание самих свойств (их имена, типы, заголовки) находится в плане видов характеристик ДополнительныеРеквизитыИСведения. Именно ссылка на элемент этого ПВХ используется как ключ при поиске значения. Поэтому первый шаг любого программного обращения — получить ссылку на нужное свойство.
Получение ссылки на свойство
Чтобы найти значение, сначала нужна ссылка на элемент плана видов характеристик. Самый простой способ — поиск по наименованию:
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения
.НайтиПоНаименованию("Цвет", Истина);
Если Свойство.Пустая() Тогда
ВызватьИсключение "Свойство ""Цвет"" не найдено";
КонецЕсли;
Учтите: поиск по наименованию ненадёжен, если свойство могут переименовать в пользовательском режиме. Более устойчивый вариант — поиск по имени свойства, которое формируется автоматически и обычно не меняется. Имя можно посмотреть в форме свойства (поле «Имя» для использования в программах) или через запрос к реквизиту Имя:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Свойства.Ссылка КАК Свойство
|ИЗ
| ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК Свойства
|ГДЕ
| Свойства.Имя = &Имя");
Запрос.УстановитьПараметр("Имя", "Цвет");
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Свойство = Выборка.Свойство;
КонецЕсли;
Чтение значения через табличную часть объекта
Если у вас есть объект (не ссылка), значение дополнительного реквизита читается прямым перебором табличной части. Это самый быстрый способ, когда объект уже получен для записи или изменения:
ОбъектНоменклатуры = СсылкаНоменклатура.ПолучитьОбъект();
ПараметрыОтбора = Новый Структура("Свойство", Свойство);
НайденныеСтроки = ОбъектНоменклатуры.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
ЗначениеЦвета = НайденныеСтроки[0].Значение;
Иначе
ЗначениеЦвета = Неопределено; // реквизит не заполнен
КонецЕсли;
Обратите внимание: если реквизит не заполнен, строки в табличной части может вообще не быть. Поэтому всегда проверяйте результат поиска, иначе получите ошибку обращения к несуществующему индексу. Также помните, что ПолучитьОбъект() читает объект целиком — при массовой обработке это дорого, и лучше использовать запрос.
Получение значения запросом без чтения объекта
Когда нужно прочитать значение по ссылке, не открывая объект, используйте запрос к табличной части. У справочников и документов табличная часть доступна в запросах как отдельная таблица:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| ДопРеквизиты.Значение КАК Значение
|ИЗ
| Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
|ГДЕ
| ДопРеквизиты.Ссылка = &Ссылка
| И ДопРеквизиты.Свойство = &Свойство");
Запрос.УстановитьПараметр("Ссылка", СсылкаНоменклатура);
Запрос.УстановитьПараметр("Свойство", Свойство);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ЗначениеЦвета = Выборка.Значение;
КонецЕсли;
Этот способ оптимален для отчётов, обработок и обменов: он не блокирует объект, не вызывает обработчики событий и работает быстрее при обходе больших выборок. Для массового получения одного свойства по списку объектов передайте в параметр массив ссылок и используйте условие В (&МассивСсылок).
Сравнение способов
Подходит, когда объект уже получен для изменения. Не подходит для массового чтения — дорого по производительности.
Оптимален для чтения по ссылке и массовых выборок. Не вызывает обработчики, не блокирует объект.
Универсально и устойчиво к изменениям конфигурации, но требует наличия подсистемы «Свойства» в составе решения.
Использование функций БСП
В конфигурациях на БСП есть готовые программные интерфейсы, которые скрывают детали хранения. Актуальные имена зависят от версии библиотеки: в старых версиях использовался общий модуль УправлениеСвойствами, в новых — Свойства. Типовой вызов выглядит так:
// Новые версии БСП
ЗначениеСвойства = Свойства.ЗначениеСвойства(СсылкаНоменклатура, "Цвет");
// Старые версии БСП
ЗначениеСвойства = УправлениеСвойствами.ЗначениеСвойства(СсылкаНоменклатура, Свойство);
Преимущество функций БСП в том, что они сами определяют, где хранится свойство (реквизит или сведение), и корректно обрабатывают отсутствие значения. Минус — при обновлении библиотеки сигнатуры могут меняться, поэтому перед использованием откройте модуль в конфигураторе и проверьте точное имя функции и порядок параметров.
- 1Определите, где хранится свойство: реквизит (табличная часть объекта) или сведение (регистр сведений)
- 2Получите ссылку на свойство по имени из ПВХ «ДополнительныеРеквизитыИСведения»
- 3Выберите способ чтения: функция БСП, запрос или табличная часть объекта
- 4Прочитайте значение и проверьте случай, когда свойство не заполнено
- 5Проверьте тип возвращаемого значения перед использованием в расчетах
Получение дополнительного сведения
Дополнительные сведения читаются из регистра сведений ДополнительныеСведения. Здесь нет табличной части — только запрос или менеджер записи:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| ДопСведения.Значение КАК Значение
|ИЗ
| РегистрСведений.ДополнительныеСведения КАК ДопСведения
|ГДЕ
| ДопСведения.Объект = &Объект
| И ДопСведения.Свойство = &Свойство");
Запрос.УстановитьПараметр("Объект", СсылкаНоменклатура);
Запрос.УстановитьПараметр("Свойство", Свойство);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ЗначениеСведения = Выборка.Значение;
КонецЕсли;
Функции БСП (Свойства.ЗначениеСвойства) обычно работают и со сведениями — библиотека сама определяет место хранения по метаданным свойства. Это ещё один аргумент в пользу программного интерфейса БСП, если он доступен в вашей конфигурации.
Проверка результата и типичные ошибки
После получения значения проверьте три вещи: найдено ли свойство вообще, заполнено ли оно у конкретного объекта и соответствует ли тип ожиданиям. Свойства могут иметь составной тип (например, строка или ссылка на значение свойств), и сравнение без приведения типов даст неожиданный результат.
Как проверить результат
Свойство не пустое, тип — ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения
Свойство = Неопределено или пустая ссылка — имя указано неверно
Переменная содержит значение ожидаемого типа
Неопределено — реквизит не заполнен у объекта или искали не в том хранилище
Для заполненных объектов значение есть, для незаполненных — Неопределено без ошибок
Ошибка на объектах, где реквизит не заполнен
Если значение «не находится», хотя в карточке объекта оно видно, чаще всего причина в том, что вы ищете реквизит, а это сведение (или наоборот). Откройте свойство в режиме предприятия и посмотрите, к какому виду оно относится, либо проверьте оба хранилища запросом.
FAQ
Как получить дополнительный реквизит в запросе для СКД?
Добавьте в запрос левое соединение с табличной частью объекта (например, Справочник.Номенклатура.ДополнительныеРеквизиты) по ссылке и свойству, передав свойство параметром. Для дополнительных сведений соединяйтесь с регистром сведений ДополнительныеСведения по полям Объект и Свойство.
Чем дополнительный реквизит отличается от дополнительного сведения?
Реквизит хранится в табличной части самого объекта и виден на его форме как поле. Сведение хранится в отдельном регистре сведений и обычно выводится в отдельной панели. Программно это разные источники данных, и запрос нужно строить соответственно.
Почему НайтиПоНаименованию не находит свойство?
Наименование могло быть изменено пользователем, либо в базе есть несколько свойств с похожими названиями в разных наборах. Надёжнее искать по полю «Имя», которое формируется автоматически и отображается в форме свойства.
Как получить значения сразу нескольких дополнительных реквизитов?
Используйте один запрос к табличной части с условием «Свойство В (&СписокСвойств)» — он вернёт все значения за одно обращение к базе. Это значительно быстрее, чем вызывать функцию БСП в цикле по каждому свойству.
Что возвращается, если реквизит у объекта не заполнен?
Строка в табличной части отсутствует, поэтому запрос и поиск строк вернут пустой результат. Ваш код должен обрабатывать этот случай — присваивать Неопределено или значение по умолчанию, а не обращаться к несуществующей строке.
Работает ли этот подход в самописной конфигурации без БСП?
Только если в ней реализован аналогичный механизм. Если дополнительные реквизиты добавлены как обычные реквизиты объекта через конфигуратор, они читаются напрямую через точку, как любое другое поле, и описанные в статье способы не нужны.
Что важно запомнить
Дополнительный реквизит читается из табличной части «ДополнительныеРеквизиты» по ссылке на свойство, дополнительное сведение — из регистра «ДополнительныеСведения». В типовых конфигурациях используйте функции БСП, для массового чтения — запросы. Всегда проверяйте, найдено ли свойство и заполнено ли значение.