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