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

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

Часто перед разработчиками 1С встает задача получить какие-либо данные при формировании отчета или печатной формы. Если эти данные хранятся в дополнительном реквизите, может возникнуть соблазн обратиться к форме объекта, чтобы "считать" значение из поля. Однако этот подход не сработает в серверных модулях, например, в модуле менеджера печатной формы. Попытка вызвать метод ПолучитьФорму() на сервере приведет к ожидаемой ошибке: "Интерактивные операции недоступны".

В этой статье разберем, как правильно и надежно получать значения дополнительных реквизитов на сервере. Проанализируем ситуацию на примере конфигурации "Управление торговлей 11", где потребовалось вывести в печатную форму УПД значение доп. реквизита, созданного для элемента справочника "Структура предприятия".

Почему нельзя обращаться к форме и где на самом деле хранятся данные

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

Механизм дополнительных реквизитов в типовых конфигурациях устроен так, что для каждого объекта, у которого они есть, создается специальная табличная часть. Чаще всего она называется ДополнительныеРеквизиты. Именно в ней хранятся пары "Свойство" (ссылка на сам доп. реквизит из плана видов характеристик) и "Значение".

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

Способ 1: Прямой запрос к табличной части объекта

Это самый прямой и очевидный способ, который и был предложен в качестве решения на форуме. Он заключается в написании запроса, который обращается к табличной части нужного нам справочника или документа и отбирает значение по ссылке на объект и свойству.

Разберем по шагам:

  1. Определяем точное имя объекта и реквизита.

    В исходной теме возникла путаница: автор искал справочник "Подразделения", но в "Управлении торговлей 11" организационная структура хранится в справочнике СтруктураПредприятия. А "Подразделение" — это его синоним (представление для пользователя). Всегда проверяйте имя объекта в конфигураторе.

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

    • Перейдите в раздел "НСИ и администрирование" -> "Администрирование" -> "Общие настройки".
    • Откройте "Дополнительные реквизиты и сведения".
    • Найдите в дереве нужный объект (например, "Структура предприятия") и выберите его.
    • В списке справа найдите ваш реквизит и откройте его карточку. В разделе "Для разработчиков" будет указано "Имя". Это имя и нужно использовать в коде.
  2. Составляем запрос.

    Запрос будет выбирать поле Значение из табличной части ДополнительныеРеквизиты справочника СтруктураПредприятия. В условиях отбора укажем ссылку на конкретный элемент справочника и наименование нашего свойства.

    Посмотрим на пример кода:

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

    Этот метод надежен и эффективен, но он жестко привязан к структуре хранения данных. Если в будущих версиях конфигурации разработчики 1С изменят ее (например, переименуют табличную часть), наш код перестанет работать.

Способ 2: Использование общего модуля из Библиотеки стандартных подсистем (БСП)

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

Для работы со свойствами предназначен общий модуль УправлениеСвойствами.

Как его использовать:

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

Посмотрим на пример кода:


// Предполагаем, что в переменной СсылкаНаПодразделение у нас есть ссылка
// на нужный элемент справочника "Структура предприятия".
СсылкаНаПодразделение = ДанныеОбъекта.СтруктурнаяЕдиница;

// Наименование доп. реквизита, как оно задано в режиме "Предприятие"
// или "Имя для разработчиков".
ИмяРеквизита = "НаименованиеГрузоотправителяДляУПД"; 

// Вызываем функцию из общего модуля для получения значения.
// Механизм БСП сам определит, где и как хранится значение, и вернет его.
ЗначениеРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаПодразделение, ИмяРеквизита);

// Теперь в переменной "ЗначениеРеквизита" хранится нужное вам значение.
// Если реквизит не найден или не заполнен, функция вернет Неопределено.
Если ЗначениеРеквизита = Неопределено Тогда
    ЗначениеРеквизита = "";
КонецЕсли;

Преимущества этого подхода:

В итоге, оба способа решают поставленную задачу. Однако использование функций БСП является предпочтительным как более современный и правильный подход в разработке для типовых конфигураций 1С.

← На главную