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

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

1С: как получить значение дополнительного сведения

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

Дополнительные сведения в типовых конфигурациях 1С (УТ, ERP, БП, ЗУП) позволяют расширять карточки объектов без изменения конфигурации. Но когда нужно получить значение такого сведения программно — в отчёте, обработке, обмене или печатной форме — разработчик сталкивается с тем, что данные лежат не в реквизитах объекта, а в отдельном регистре сведений.

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

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

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

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

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

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

Как найти нужное свойство в плане видов характеристик

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

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

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

Если Свойство = Неопределено Или Свойство.Пустая() Тогда

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

КонецЕсли;

Обратите внимание на второй параметр НайтиПоНаименованию — он включает поиск по точному совпадению. Альтернатива — запрос с отбором по имени:

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

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

"ВЫБРАТЬ ПЕРВЫЕ 1

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

|ИЗ

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

|ГДЕ

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

| И НЕ Свойства.ПометкаУдаления";

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

Получение значения запросом к регистру сведений

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

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

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

"ВЫБРАТЬ

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

|ИЗ

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

|ГДЕ

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

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

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

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

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

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

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

Иначе

ЗначениеСведения = Неопределено; // сведение не заполнено

КонецЕсли;

Если записи нет — запрос вернёт пустой результат. Это нормальная ситуация: сведение просто не заполняли. Обязательно обрабатывайте её через проверку Выборка.Следующий(), иначе получите ошибку обращения к полю.

Порядок действий
  1. 1
    Определите, сведение это или реквизит (проверьте табличную часть объекта)
  2. 2
    Найдите ссылку на свойство в ПВХ ДополнительныеРеквизитыИСведения по имени или заголовку
  3. 3
    Выполните запрос к РегистрСведений.ДополнительныеСведения с отбором по Объект и Свойство
  4. 4
    Проверьте, что выборка не пустая, и прочитайте поле Значение
  5. 5
    Проверьте тип полученного значения перед использованием

Чтение через менеджер записи

Для одиночной записи можно обойтись без запроса — через менеджер записи регистра:

МенеджерЗаписи = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Объект = КонтрагентСсылка;

МенеджерЗаписи.Свойство = Свойство;

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

ЗначениеСведения = МенеджерЗаписи.Значение;

КонецЕсли;

Этот вариант удобен, когда дальше планируется изменение значения: прочитали, поменяли, записали тем же менеджером. Для массового чтения по множеству объектов он не подходит — на каждую запись будет отдельное обращение к базе.

Массовое получение значений для списка объектов

В отчётах и обработках обычно нужно вытащить сведение сразу для тысячи контрагентов или номенклатуры. Делать это циклом с запросом внутри — грубая ошибка производительности. Правильный подход — один запрос с левым соединением:

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

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

"ВЫБРАТЬ

| Контрагенты.Ссылка КАК Контрагент,

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

|ИЗ

| Справочник.Контрагенты КАК Контрагенты

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДополнительныеСведения КАК ДопСведения

| ПО ДопСведения.Объект = Контрагенты.Ссылка

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

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

Левое соединение важно: объекты без заполненного сведения попадут в результат со значением NULL, и вы не потеряете строки. В СКД тот же приём реализуется набором данных-запросом с аналогичным соединением — это стандартный способ вывести допсведения в отчёт.

Если допсведений несколько, не делайте отдельное соединение на каждое — добавьте один запрос к регистру со сгруппировкой по объекту и разворачивайте значения через МАКСИМУМ(ВЫБОР КОГДА Свойство = &Свойство1 ТОГДА Значение КОНЕЦ). Это существенно быстрее на больших таблицах.
ПЗ
Практическое замечание

Особенности типов значений и проверка результата

Ресурс «Значение» — составного типа, поэтому вернуться может строка, число, дата, булево или ссылка на справочник (если тип свойства — «Дополнительное значение»). Перед использованием проверяйте тип через ТипЗнч(), особенно если дальше идёт сравнение или арифметика.

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

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

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

Результат запроса
Норма

Выборка содержит строку с заполненным полем Значение

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

Пустой результат при заведомо заполненном сведении — проверьте, не реквизит ли это

Тип значения
Норма

ТипЗнч() возвращает ожидаемый тип (Строка, Число, ссылка)

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

Значение = NULL — объект есть, но сведение не заполнено

Свойство
Норма

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

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

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

Типичные ошибки и ограничения

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

Типичные ошибки
01
Поиск значения в табличной части ДополнительныеРеквизиты вместо регистра ДополнительныеСведения — результат всегда пустой
02
Поиск свойства по заголовку, который администратор переименовал — свойство не находится, код молча возвращает Неопределено
03
Запрос в цикле по объектам — на больших объёмах обработка работает в десятки раз медленнее, чем один запрос с соединением
04
Отсутствие проверки на пустую выборку — ошибка «Поле не обнаружено» при первом же незаполненном сведении
05
Сравнение составного значения без приведения типа — сравнение строки с числом или NULL даёт неожиданный результат

Отдельное ограничение — права доступа. Если у пользователя, под которым выполняется код, нет прав на регистр «Дополнительные сведения», запрос вернёт пустой результат без ошибки. В серверных процедурах общих модулей с признаком «Привилегированный» эта проблема снимается, но в пользовательских обработках её нужно учитывать.

Альтернативные варианты: БСП и расширения

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

Сравнение вариантов

Прямой запрос к регистру

Максимальная гибкость и скорость, работает в любой конфигурации с БСП. Минус — зависимость от структуры регистра

Менеджер записи

Простой код для одной записи, удобен для чтения с последующим изменением. Не подходит для массовой обработки

API БСП (УправлениеСвойствами)

Устойчив к изменениям платформы хранения, но доступен не во всех версиях и требует изучения состава модуля

СКД с левым соединением

Оптимально для отчётов: пользователь сам строит отборы. Не подходит для программной логики обработки

При доработке через расширение прямые запросы к регистру работают без ограничений — регистр доступен расширению так же, как и основной конфигурации. Это позволяет выводить допсведения в собственные формы и отчёты расширения без снятия конфигурации с поддержки.

Итог

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

Дополнительное сведение читается из РегистрСведений.ДополнительныеСведения по паре «Объект + Свойство»; свойство ищется в ПВХ ДополнительныеРеквизитыИСведения по имени. Для списков объектов используйте один запрос с левым соединением и всегда обрабатывайте пустой результат.

Частые вопросы

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

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

Запрос возвращает пусто, хотя сведение заполнено в карточке. Что проверить?

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

Как получить значение сведения в запросе динамически, без заранее известного свойства?

Передайте ссылку на свойство параметром запроса — это стандартный приём. Если нужно получить сразу все сведения объекта, уберите отбор по свойству и выберите пары «Свойство — Значение» с соединением к ПВХ для получения заголовков.

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

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

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

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

Работает ли этот подход во внешних обработках и расширениях?

Да, регистр и ПВХ доступны из внешних обработок и расширений без ограничений. Ограничение одно: в безопасном режиме внешней обработки могут быть недоступны некоторые операции, но обычное чтение запросом работает.