К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно получить дополнительный реквизит в 1С

Как программно получить значение дополнительного реквизита в 1С: через БСП, запрос к табличной части и свойство по имени. Примеры кода, ошибки и FAQ.

Дополнительные реквизиты и сведения в 1С хранятся не в реквизитах объекта, а в отдельных таблицах, поэтому обратиться к ним напрямую через точку, как к обычному полю, нельзя. Попытка написать Справочник.Номенклатура.Цвет завершится ошибкой, если «Цвет» — это дополнительный реквизит, добавленный через механизм БСП без изменения конфигурации.

Способ получения значения зависит от того, как реализован механизм в вашей конфигурации. В типовых решениях на базе Библиотеки стандартных подсистем (УТ 11, ERP, КА, БП 3.0 и другие) используется подсистема «Свойства»: дополнительные реквизиты хранятся в табличной части объекта «ДополнительныеРеквизиты», а дополнительные сведения — в регистре сведений «ДополнительныеСведения». В самописных конфигурациях механизм может быть иным.

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

Как устроено хранение дополнительных реквизитов

Механизм дополнительных реквизитов и сведений в БСП разделяет два понятия. Дополнительный реквизит «принадлежит» объекту и хранится прямо в его табличной части ДополнительныеРеквизиты — она видна в дереве метаданных у справочника или документа. Дополнительное сведение хранится централизованно — в регистре сведений ДополнительныеСведения с измерением «Объект» и измерением «Свойство».

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

Получение ссылки на свойство

Чтобы найти значение, сначала нужна ссылка на элемент плана видов характеристик. Самый простой способ — поиск по наименованию:

Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения

.НайтиПоНаименованию("Цвет", Истина);

Если Свойство.Пустая() Тогда

ВызватьИсключение "Свойство ""Цвет"" не найдено";

КонецЕсли;

Учтите: поиск по наименованию ненадёжен, если свойство могут переименовать в пользовательском режиме. Более устойчивый вариант — поиск по имени свойства, которое формируется автоматически и обычно не меняется. Имя можно посмотреть в форме свойства (поле «Имя» для использования в программах) или через запрос к реквизиту Имя:

Запрос = Новый Запрос(

"ВЫБРАТЬ

| Свойства.Ссылка КАК Свойство

|ИЗ

| ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК Свойства

|ГДЕ

| Свойства.Имя = &Имя");

Запрос.УстановитьПараметр("Имя", "Цвет");

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Свойство = Выборка.Свойство;

КонецЕсли;

Чтение значения через табличную часть объекта

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

ОбъектНоменклатуры = СсылкаНоменклатура.ПолучитьОбъект();

ПараметрыОтбора = Новый Структура("Свойство", Свойство);

НайденныеСтроки = ОбъектНоменклатуры.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() > 0 Тогда

ЗначениеЦвета = НайденныеСтроки[0].Значение;

Иначе

ЗначениеЦвета = Неопределено; // реквизит не заполнен

КонецЕсли;

Обратите внимание: если реквизит не заполнен, строки в табличной части может вообще не быть. Поэтому всегда проверяйте результат поиска, иначе получите ошибку обращения к несуществующему индексу. Также помните, что ПолучитьОбъект() читает объект целиком — при массовой обработке это дорого, и лучше использовать запрос.

Получение значения запросом без чтения объекта

Когда нужно прочитать значение по ссылке, не открывая объект, используйте запрос к табличной части. У справочников и документов табличная часть доступна в запросах как отдельная таблица:

Запрос = Новый Запрос(

"ВЫБРАТЬ

| ДопРеквизиты.Значение КАК Значение

|ИЗ

| Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты

|ГДЕ

| ДопРеквизиты.Ссылка = &Ссылка

| И ДопРеквизиты.Свойство = &Свойство");

Запрос.УстановитьПараметр("Ссылка", СсылкаНоменклатура);

Запрос.УстановитьПараметр("Свойство", Свойство);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ЗначениеЦвета = Выборка.Значение;

КонецЕсли;

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

Сравнение способов

Табличная часть объекта

Подходит, когда объект уже получен для изменения. Не подходит для массового чтения — дорого по производительности.

Запрос к табличной части

Оптимален для чтения по ссылке и массовых выборок. Не вызывает обработчики, не блокирует объект.

Функции БСП

Универсально и устойчиво к изменениям конфигурации, но требует наличия подсистемы «Свойства» в составе решения.

Использование функций БСП

В конфигурациях на БСП есть готовые программные интерфейсы, которые скрывают детали хранения. Актуальные имена зависят от версии библиотеки: в старых версиях использовался общий модуль УправлениеСвойствами, в новых — Свойства. Типовой вызов выглядит так:

// Новые версии БСП

ЗначениеСвойства = Свойства.ЗначениеСвойства(СсылкаНоменклатура, "Цвет");

// Старые версии БСП

ЗначениеСвойства = УправлениеСвойствами.ЗначениеСвойства(СсылкаНоменклатура, Свойство);

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

Порядок действий
  1. 1
    Определите, где хранится свойство: реквизит (табличная часть объекта) или сведение (регистр сведений)
  2. 2
    Получите ссылку на свойство по имени из ПВХ «ДополнительныеРеквизитыИСведения»
  3. 3
    Выберите способ чтения: функция БСП, запрос или табличная часть объекта
  4. 4
    Прочитайте значение и проверьте случай, когда свойство не заполнено
  5. 5
    Проверьте тип возвращаемого значения перед использованием в расчетах

Получение дополнительного сведения

Дополнительные сведения читаются из регистра сведений ДополнительныеСведения. Здесь нет табличной части — только запрос или менеджер записи:

Запрос = Новый Запрос(

"ВЫБРАТЬ

| ДопСведения.Значение КАК Значение

|ИЗ

| РегистрСведений.ДополнительныеСведения КАК ДопСведения

|ГДЕ

| ДопСведения.Объект = &Объект

| И ДопСведения.Свойство = &Свойство");

Запрос.УстановитьПараметр("Объект", СсылкаНоменклатура);

Запрос.УстановитьПараметр("Свойство", Свойство);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ЗначениеСведения = Выборка.Значение;

КонецЕсли;

Функции БСП (Свойства.ЗначениеСвойства) обычно работают и со сведениями — библиотека сама определяет место хранения по метаданным свойства. Это ещё один аргумент в пользу программного интерфейса БСП, если он доступен в вашей конфигурации.

Проверка результата и типичные ошибки

После получения значения проверьте три вещи: найдено ли свойство вообще, заполнено ли оно у конкретного объекта и соответствует ли тип ожиданиям. Свойства могут иметь составной тип (например, строка или ссылка на значение свойств), и сравнение без приведения типов даст неожиданный результат.

Типичные ошибки
01
Поиск свойства по наименованию без проверки результата — после переименования свойства код молча перестаёт работать или падает с ошибкой
02
Обращение к НайденныеСтроки[0] без проверки количества — ошибка индекса, если реквизит у объекта не заполнен
03
Путаница между дополнительным реквизитом и сведением: запрос к табличной части не найдёт значение сведения и наоборот
04
Использование ПолучитьОбъект() в цикле по тысячам ссылок — резкое падение производительности вместо одного запроса
05
Сравнение значения составного типа со строкой без приведения — условие никогда не выполняется
Контрольные точки

Как проверить результат

Ссылка на свойство получена
Норма

Свойство не пустое, тип — ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения

Тревожный признак

Свойство = Неопределено или пустая ссылка — имя указано неверно

Значение прочитано
Норма

Переменная содержит значение ожидаемого типа

Тревожный признак

Неопределено — реквизит не заполнен у объекта или искали не в том хранилище

Код работает на разных объектах
Норма

Для заполненных объектов значение есть, для незаполненных — Неопределено без ошибок

Тревожный признак

Ошибка на объектах, где реквизит не заполнен

Если значение «не находится», хотя в карточке объекта оно видно, чаще всего причина в том, что вы ищете реквизит, а это сведение (или наоборот). Откройте свойство в режиме предприятия и посмотрите, к какому виду оно относится, либо проверьте оба хранилища запросом.

FAQ

Как получить дополнительный реквизит в запросе для СКД?

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

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

Реквизит хранится в табличной части самого объекта и виден на его форме как поле. Сведение хранится в отдельном регистре сведений и обычно выводится в отдельной панели. Программно это разные источники данных, и запрос нужно строить соответственно.

Почему НайтиПоНаименованию не находит свойство?

Наименование могло быть изменено пользователем, либо в базе есть несколько свойств с похожими названиями в разных наборах. Надёжнее искать по полю «Имя», которое формируется автоматически и отображается в форме свойства.

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

Используйте один запрос к табличной части с условием «Свойство В (&СписокСвойств)» — он вернёт все значения за одно обращение к базе. Это значительно быстрее, чем вызывать функцию БСП в цикле по каждому свойству.

Что возвращается, если реквизит у объекта не заполнен?

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

Работает ли этот подход в самописной конфигурации без БСП?

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

Итог

Что важно запомнить

Дополнительный реквизит читается из табличной части «ДополнительныеРеквизиты» по ссылке на свойство, дополнительное сведение — из регистра «ДополнительныеСведения». В типовых конфигурациях используйте функции БСП, для массового чтения — запросы. Всегда проверяйте, найдено ли свойство и заполнено ли значение.