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

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

Дополнительные реквизиты 1С: как обратиться из кода, запроса и формы

Как обратиться к дополнительным реквизитам в 1С из кода, запроса и формы. Примеры обращения к табличной части ДополнительныеРеквизиты и свойствам.

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

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

Ниже разобраны все основные сценарии: чтение и запись из кода, обращение в запросе, работа в форме, обращение в отчётах СКД, а также типичные ошибки, из-за которых значение «не находится», хотя оно заполнено в карточке объекта.

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

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

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

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

Как получить значение дополнительного реквизита из кода

Базовый приём — найти строку в табличной части по ссылке на свойство и прочитать поле Значение. Ссылку на свойство обычно получают по предопределённому имени или поиском по наименованию.

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

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

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

Новый Структура("Свойство", Свойство));

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

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

Иначе

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

КонецЕсли;

Метод НайтиСтроки возвращает массив, потому что в общем случае отбор по структуре может вернуть несколько строк. Для дополнительных реквизитов одно свойство встречается у объекта один раз, поэтому безопасно брать нулевой элемент — но только после проверки, что массив не пустой. Обращение Строки[0] без проверки — одна из самых частых причин ошибки «Индекс находится за границами массива».

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

Как записать значение дополнительного реквизита

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

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

Новый Структура("Свойство", Свойство));

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

Строка = Строки[0];

Иначе

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

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

КонецЕсли;

Строка.Значение = НовоеЗначение;

Объект.Записать();

Ключевой момент — тип записываемого значения должен соответствовать типу, заданному в свойстве. Если свойство имеет тип «СправочникСсылка.ЗначенияСвойствОбъектов», а вы пытаетесь записать строку, при записи объекта получите ошибку несоответствия типов или «тихую» очистку значения. Проверить тип можно в описании свойства: Свойство.ТипЗначения.

Порядок записи дополнительного реквизита
  1. 1
    Получите ссылку на свойство по предопределённому имени или наименованию
  2. 2
    Найдите строку в табличной части ДополнительныеРеквизиты через НайтиСтроки
  3. 3
    Если строки нет — добавьте новую и заполните поле Свойство
  4. 4
    Присвойте полю Значение значение подходящего типа
  5. 5
    Запишите объект и убедитесь, что запись прошла без исключений

Как обратиться к дополнительному сведению

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

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

Запрос.Текст =

"ВЫБРАТЬ

| ДополнительныеСведения.Значение

|ИЗ

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

|ГДЕ

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

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

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

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

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

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

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

КонецЕсли;

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

Как обратиться к дополнительному реквизиту в запросе и СКД

В запросе к табличной части обращаются через точку от имени объекта: Справочник.Номенклатура.ДополнительныеРеквизиты. Типовой приём — левое соединение табличной части с основной таблицей и отбор по свойству:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар,

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

ИЗ

Справочник.Номенклатура КАК Номенклатура

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

ПО ДопРеквизиты.Ссылка = Номенклатура.Ссылка

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

Если нужно вывести несколько дополнительных реквизитов, для каждого добавляют отдельное соединение с собственным псевдонимом и своим параметром свойства. Альтернатива — вывести все свойства «в лоб» через одно соединение и развернуть их группировкой, но это усложняет дальнейшую обработку.

В отчётах на СКД дополнительные реквизиты и сведения обычно доступны автоматически: механизм свойств добавляет их в набор полей отчёта, если в схеме компоновки включён соответствующий режим (в типовых отчётах поля появляются в группе «Дополнительные реквизиты» / «Дополнительные сведения»). Если отчёт самописный, соединения с табличной частью и регистром прописывают в тексте запроса набора данных вручную.

Как обратиться к дополнительному реквизиту в форме объекта

В управляемой форме объекта дополнительные реквизиты выводятся динамически: БСП создаёт реквизиты формы и элементы в момент создания формы на сервере. Путь к значению зависит от версии БСП: в современных версиях значения хранятся в реквизитах формы вида ДополнительныйРеквизитЗначение_<хеш>, а сопоставление свойств и реквизитов лежит в таблице описания (например, Свойства_ОписаниеДополнительныхРеквизитов).

Прямое обращение к этим автогенерируемым реквизитам формы — хрупкое решение: имена реквизитов зависят от версии библиотеки и могут измениться при обновлении. Надёжнее работать с данными объекта: при чтении формы значения уже находятся в Объект.ДополнительныеРеквизиты, а при записи — переносятся обратно в объект автоматически.

Если нужно программно изменить значение на форме (например, подставить значение по умолчанию при создании), правильное место — обработчики ПриСозданииНаСервере или ПередЗаписью модуля объекта, где вы работаете с данными, а не с элементами формы. Изменение элемента формы напрямую не гарантирует, что значение попадёт в объект при записи.

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

Как найти свойство: по имени, наименованию или в наборе

Способ получения ссылки на свойство влияет на устойчивость кода к изменениям настроек. Есть три основных варианта.

  • Предопределённое имя. Если свойство создано в конфигураторе как предопределённый элемент ПВХ, обращение ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ИмяСвойства — самый надёжный способ: имя не меняется пользователем.
  • Поиск по наименованию. НайтиПоНаименованию("Цвет товара", Истина) — работает для свойств, созданных в пользовательском режиме, но ломается при переименовании. Второй параметр (точное соответствие) стоит ставить всегда.
  • Через набор свойств. Если известен набор (справочник НаборыДополнительныхРеквизитовИСведений), можно перебрать его табличную часть и найти нужное свойство по заголовку — так код привязан к набору, а не к глобальному наименованию.

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

Контрольные точки

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

Значение найдено в коде
Норма

НайтиСтроки вернул массив с одной строкой, Значение заполнено

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

Массив пуст, хотя в карточке значение видно — проверьте ссылку на свойство

Записанное значение
Норма

После Записать() значение отображается в карточке объекта на вкладке Дополнительно

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

В карточке пусто — тип значения не совпал с типом свойства или объект не записан

Отбор в запросе
Норма

Соединение возвращает строки с заполненным реквизитом

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

Все значения NULL — параметр Свойство передан строкой или из другого набора

Часто задаваемые вопросы

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

Реквизит — это строка табличной части объекта, читается и пишется вместе с объектом. Сведение — запись регистра сведений ДополнительныеСведения, работа с ним идёт через запрос или набор записей независимо от объекта. В коде это два разных механизма обращения.

Почему НайтиСтроки не находит значение, хотя в карточке оно заполнено?

Чаще всего ссылка на свойство не совпадает: свойство найдено по похожему наименованию, но это другой элемент ПВХ, или в базе несколько свойств с одинаковым названием в разных наборах. Проверьте ссылку на свойство в строке табличной части через консоль кода или отчёт по объекту.

Можно ли обратиться к дополнительному реквизиту через точку, как к обычному?

Нет. Конструкции вида Объект.Цвет для дополнительного реквизита не существует — платформа выдаст ошибку «Поле объекта не обнаружено». Только поиск строки в табличной части ДополнительныеРеквизиты или запрос.

Как вывести дополнительный реквизит в печатную форму?

В модуле менеджера печати получите значение из табличной части ДополнительныеРеквизиты объекта по ссылке на свойство, поместите его в структуру параметров макета и выведите в область шаблона как обычный параметр.

Надёжно ли искать свойство по наименованию?

Только как временное решение. Пользователь с правами администратора может переименовать свойство, и код перестанет находить значение. Для постоянного кода используйте предопределённые имена или храните ссылку на свойство в константе либо параметре настройки.

Итог

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

Дополнительный реквизит ищут в табличной части ДополнительныеРеквизиты по ссылке на свойство, сведение — в регистре ДополнительныеСведения. В запросах используют соединение с отбором по Свойство, передавая ссылку, а не строку. Ссылку на свойство надёжнее получать по предопределённому имени, а после поиска всегда проверять результат на пустоту.