Как вывести дополнительные реквизиты контрагента в форму документа в 1С:УНФ

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет
← На главную

При разработке в среде 1С:Предприятие 8.3, особенно в таких конфигурациях, как 1С:Управление нашей фирмой (УНФ), программисты часто сталкиваются с необходимостью извлечения данных, которые хранятся не в основных реквизитах справочника, а в механизме дополнительных свойств. Обычный подход через обращение к свойству объекта в данном случае не работает. В этой статье мы подробно разберем, почему стандартные методы поиска могут возвращать пустые значения, и научимся правильно извлекать дополнительные реквизиты программными средствами.

Разбор типичной ошибки: почему НайтиПоНаименованию не работает для значений

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

Однако само значение этого реквизита для конкретного контрагента хранится совершенно в другом месте. В 1С:УНФ (как и в других конфигурациях на базе БСП) значения дополнительных реквизитов находятся в табличной части справочника Контрагенты под названием ДополнительныеРеквизиты. Именно поэтому код, пытающийся получить ПаспортСерия.Значение напрямую из ПВХ, всегда будет возвращать пустой результат: у самого определения реквизита нет и не может быть значения «Серия паспорта».

Решение №1: Использование стандартных функций БСП (модуль УправлениеСвойствами)

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

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


&НаСервере
Процедура ЗаполнитьРеквизитыИзКонтрагента(СсылкаНаКонтрагента)
    
    // Получаем ссылку на нужное свойство (доп. реквизит)
    // Внимание: поиск по наименованию чувствителен к изменениям пользователя!
    СвойствоПаспорт = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ПаспортСерия (Контрагенты)");
    
    Если Не СвойствоПаспорт.Пустая() Тогда
        // Используем функцию БСП для получения значения
        ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаКонтрагента, СвойствоПаспорт);
        
        // Записываем результат в реквизит документа на форме
        Объект.ПаспортСерияКонтрагента = ЗначениеРеквизита;
    КонецЕсли;

КонецПроцедуры

Этот метод прост, но имеет недостаток: если нам нужно выгрузить 10–15 реквизитов (как в случае с паспортными данными), вызов функции в цикле или последовательно может замедлить работу системы из-за множественных обращений к базе данных.

Решение №2: Использование запроса для массового получения данных

Если нам необходимо получить сразу целый пакет данных (Серия, Номер, Кем выдан, Дата выдачи и т.д.), мы рекомендуем использовать запрос. Это наиболее производительный способ, так как мы обращаемся к базе данных один раз. Выясним, как составить такой запрос правильно.

Посмотрим на пример функции, которая возвращает структуру со всеми необходимыми данными:


&НаСервере
Функция ПолучитьПакетДопРеквизитов(КонтрагентСсылка)
    
    Результат = Новый Структура;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	КонтрагентыДополнительныеРеквизиты.Свойство.Наименование КАК ИмяСвойства,
        |	КонтрагентыДополнительныеРеквизиты.Значение КАК Значение
        |ИЗ
        |	Справочник.Контрагенты.ДополнительныеРеквизиты КАК КонтрагентыДополнительныеРеквизиты
        |ГДЕ
        |	КонтрагентыДополнительныеРеквизиты.Ссылка = &Контрагент";
    
    Запрос.УстановитьПараметр("Контрагент", КонтрагентСсылка);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Здесь мы сопоставляем наименования из ПВХ с ключами нашей структуры
        Если Найти(Выборка.ИмяСвойства, "ПаспортСерия") > 0 Тогда
            Результат.Вставить("Серия", Выборка.Значение);
        ИначеЕсли Найти(Выборка.ИмяСвойства, "ПаспортНомер") > 0 Тогда
            Результат.Вставить("Номер", Выборка.Значение);
        // ... и так далее для всех полей
        КонецЕсли;
    КонецЦикла;
    
    Возвращает Результат;
КонецФункции

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

Решение №3: Получение всех свойств через УправлениеСвойствами.ЗначенияСвойствОбъекта

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

Проанализируем ситуацию применения:


&НаСервере
Процедура ЗаполнитьДанныеКонтрагентаНаФорме()
    
    Если Объект.Контрагент.Пустая() Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем таблицу всех доп. реквизитов контрагента
    ТаблицаСвойств = УправлениеСвойствами.ЗначенияСвойствОбъекта(Объект.Контрагент);
    
    // Обходим таблицу и заполняем реквизиты документа
    Для Каждого СтрокаСвойства Из ТаблицаСвойств Цикл
        
        ИмяСвойства = Строка(СтрокаСвойства.Свойство);
        
        Если Найти(ИмяСвойства, "ПаспортСерия") > 0 Тогда
            Объект.ПаспортСерияКонтрагента = СтрокаСвойства.Значение;
        ИначеЕсли Найти(ИмяСвойства, "ПаспортНомер") > 0 Тогда
            Объект.ПаспортНомерКонтрагента = СтрокаСвойства.Значение;
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Важные рекомендации по автоматизации процесса

Чтобы данные в документе «Согласие на ПНд» (персональных данных) заполнялись автоматически при выборе клиента, необходимо выполнить следующие действия:

  1. Откройте форму документа в конфигураторе.
  2. Найдите поле Контрагент и перейдите в его свойства.
  3. Создайте обработчик события ПриИзменении.
  4. Внутри этого обработчика вызовите вашу серверную процедуру заполнения данных.

Важный момент по безопасности типов: Дополнительные реквизиты имеют тип Характеристика.ДополнительныеРеквизитыИСведения. При получении значения (например, даты выдачи паспорта) всегда проверяйте, что тип полученного значения совпадает с типом реквизита в вашем документе. Если в доп. реквизите хранится ссылка на другой объект (например, на справочник "Банки"), а вы пытаетесь записать её в текстовое поле, используйте функцию Строка() для приведения типа.

Также стоит учесть нюанс именования. Если реквизиты созданы в Битрикс24 и переданы через синхронизацию, их имена в 1С часто выглядят как ПаспортСерия_545748a4.... В программном коде лучше избегать жесткой привязки к таким длинным именам с UID. Вместо этого можно создать настройку (например, в константах), где пользователь сам выберет, какой доп. реквизит считать "Серией паспорта", а какой — "Номером". Это сделает ваш код устойчивым к изменениям в настройках синхронизации.

Подводя итог, отметим, что работа с дополнительными реквизитами требует понимания структуры хранения данных БСП. Использование стандартных модулей УправлениеСвойствами делает ваш код совместимым с будущими обновлениями 1С:УНФ и значительно упрощает процесс разработки.

← На главную