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