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

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

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

Наша задача состоит в том, чтобы научиться программно заполнять значение дополнительного реквизита номенклатуры на основании другого реквизита, а также разобраться, как вызвать функцию при изменении двух реквизитов одновременно, если стандартное событие «ПриИзменении» не подходит.

1. Общие принципы работы с дополнительными реквизитами в 1С

Прежде чем углубляться в код, разберем основные принципы, лежащие в основе работы с дополнительными реквизитами в 1С.

  1. Использование "Имени" для разработчика: Каждый дополнительный реквизит или свойство в системе 1С имеет не только "Наименование", которое видит пользователь, но и уникальное "Имя", предназначенное для программного использования. Именно по этому "Имени" мы настоятельно рекомендуем выполнять поиск дополнительного реквизита. Это помогает избежать путаницы, если несколько реквизитов имеют одинаковое "Наименование" (например, "Размер" для трусов и "Размер" для галстуков). Обращение по "Наименованию" может привести к непредсказуемым ошибкам в продажах, если система выберет не тот реквизит.
  2. Хранение данных: Важно понимать, что дополнительные реквизиты могут храниться в двух основных местах:
    • Дополнительные реквизиты: Они являются неотъемлемой частью объекта (например, справочника "Номенклатура") и хранятся в его табличной части, обычно называемой ДополнительныеРеквизиты. Эти реквизиты выводятся на форму и тесно связаны с самим объектом.
    • Дополнительные сведения: Эти данные предназначены для хранения информации, которая не является неотъемлемой частью объекта. Они хранятся в отдельном регистре сведений, часто называемом РС.ДополнительныеСведения. Дополнительные сведения доступны для просмотра и редактирования пользователям, которые имеют право только на чтение самого объекта, что расширяет возможности управления доступом.

    В нашем случае, когда речь идет о реквизите в карточке номенклатуры, скорее всего, мы имеем дело с дополнительным реквизитом, хранящимся в табличной части объекта.

  3. Активация механизма: Для использования дополнительных реквизитов и сведений в конфигурациях на БСП необходимо убедиться, что механизм активирован. Для этого устанавливаем флажок "Дополнительные реквизиты и сведения" в общих настройках программы (обычно это раздел "Администрирование" - "Общие настройки").

2. Прямое программное обращение к дополнительному реквизиту через табличную часть объекта (для 1С:УНФ)

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

  1. Получаем ссылку на объект и сам объект: Прежде всего, нам нужна ссылка на элемент справочника (например, номенклатуру), для которого мы хотим изменить дополнительный реквизит. Затем из этой ссылки мы получаем объект.
  2. Находим сам дополнительный реквизит (метаданные): Нам потребуется найти элемент плана видов характеристик, который соответствует нашему дополнительному реквизиту. Это делается с помощью метода НайтиПоРеквизиту(), где мы указываем "Имя" для разработчика.
  3. Обращаемся к табличной части объекта: У объекта НоменклатураОбъект есть табличная часть с именем ДополнительныеРеквизиты. Именно там хранятся значения наших реквизитов.
  4. Находим или добавляем дополнительный реквизит в табличной части: Мы ищем наш реквизит в этой табличной части. Если он уже существует, мы получаем к нему доступ. Если нет (то есть, он еще ни разу не заполнялся и строка в табличной части не создана), мы создаем новую строку.
  5. Устанавливаем значение: После того как у нас есть строка табличной части, мы присваиваем ей нужные значения: ссылку на сам дополнительный реквизит (Свойство) и его значение (Значение).
  6. Записываем изменения: После всех манипуляций не забываем записать объект, чтобы изменения сохранились в базе данных.

Давайте посмотрим на пример кода для записи значения дополнительного реквизита в табличную часть объекта Номенклатура:


// Предполагается, что НоменклатураСсылкаНаФорме - это ссылка на элемент номенклатуры на форме
// или любой другой способ получить ссылку на нужный элемент.

// 1. Получаем объект номенклатуры
НоменклатураОбъект = НоменклатураСсылкаНаФорме.ПолучитьОбъект();

// 2. Находим сам дополнительный реквизит (элемент ПланаВидовХарактеристик)
// Важно использовать "Имя" для разработчика, а не "Наименование"
// "ИндСвойство_a6c5ac5d419a44bebcbe19171c190e40" - это пример имени реквизита для разработчика,
// которое вы найдете в карточке дополнительного реквизита.
ДопРеквизит = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя","ИндСвойство_a6c5ac5d419a44bebcbe19171c190e40");

// Проверим, найден ли реквизит. Если нет, возможно, он удален или имя указано неверно.
Если ДопРеквизит = Неопределено Тогда
    Сообщить("Дополнительный реквизит с указанным именем не найден!", СтатусСообщения.Важное);
    Возврат;
КонецЕсли;

// 3. Ищем строку для этого реквизита в табличной части ДополнительныеРеквизиты объекта
// Мы ищем по колонке "Свойство", которая содержит ссылку на ПВХ.
ДопСвойствоВТаблице = НоменклатураОбъект.ДополнительныеРеквизиты.Найти(ДопРеквизит,"Свойство");

// 4. Если строка не найдена (т.е. реквизит еще ни разу не заполнялся), добавляем новую
Если ДопСвойствоВТаблице = Неопределено Тогда
    ДопСвойствоВТаблице = НоменклатураОбъект.ДополнительныеРеквизиты.Добавить();
    // 5. Для новой строки обязательно устанавливаем ссылку на сам дополнительный реквизит
    ДопСвойствоВТаблице.Свойство = ДопРеквизит;
КонецЕсли;

// 6. Устанавливаем или изменяем значение дополнительного реквизита
// Здесь "НовоеЗначениеДляРеквизита" - это переменная, которая содержит значение,
// которое вы хотите записать. Тип значения должен соответствовать типу дополнительного реквизита.
ДопСвойствоВТаблице.Значение = НовоеЗначениеДляРеквизита; 

// 7. Записываем объект номенклатуры
Попытка
    НоменклатураОбъект.Записать();
    Сообщить("Значение дополнительного реквизита успешно обновлено.");
Исключение
    Сообщить("Ошибка при записи объекта номенклатуры: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;

Этот код сначала находит нужный дополнительный реквизит по его уникальному "Имени", затем проверяет, существует ли уже запись для этого реквизита в табличной части объекта. Если записи нет, она создается, и в нее обязательно прописывается ссылка на сам реквизит (ДопСвойствоВТаблице.Свойство = ДопРеквизит;). После этого можно устанавливать Значение и записывать объект.

3. Использование Библиотеки Стандартных Подсистем (БСП) в 1С:УНФ

В конфигурациях, основанных на БСП (таких как 1С:УНФ, 1С:УТ 11, 1С:КА 2, 1С:ERP), работа с дополнительными реквизитами и сведениями значительно упрощается благодаря наличию общего модуля УправлениеСвойствами. Мы настоятельно рекомендуем использовать его, поскольку он инкапсулирует всю логику работы с табличными частями и регистрами, а также предоставляет удобный интерфейс. Для быстрого поиска функций и примеров работы с библиотекой можно использовать справочник по методам БСП.

Давайте рассмотрим ключевые функции модуля УправлениеСвойствами:

  1. Получение значения дополнительного свойства: Для получения текущего значения дополнительного реквизита используем функцию ЗначениеСвойства().
  2. 
    // ОбъектСсылка - ссылка на объект, для которого запрашивается дополнительный реквизит (например, СправочникСсылка.Номенклатура)
    // "ИмяРеквизитаДляРазработчика" - строковое имя дополнительного свойства (из карточки реквизита).
    ЗнСвойства = УправлениеСвойствами.ЗначениеСвойства(ОбъектСсылка, "ИмяРеквизитаДляРазработчика");
    

    Эта функция позволяет нам получить значение свойства по ссылке на объект и имени реквизита, не углубляясь в структуру табличных частей или регистров сведений.

  3. Запись значений дополнительных свойств: Для массовой или индивидуальной записи значений используем процедуру ЗаписатьСвойстваУОбъекта(). Эта процедура принимает владельца свойств (объект или ссылку) и таблицу соответствия свойств и их значений.
  4. 
    // ВладелецСвойств - ссылка или объект, для которого записываем свойства.
    // ТаблицаСвойствИЗначений - ТаблицаЗначений со колонками "Свойство" (ссылка на ПВХ) и "Значение" (любого типа).
    // Ее нужно предварительно заполнить.
    
    // Пример заполнения ТаблицыСвойствИЗначений:
    ТаблицаСвойствИЗначений = Новый ТаблицаЗначений;
    ТаблицаСвойствИЗначений.Колонки.Добавить("Свойство");
    ТаблицаСвойствИЗначений.Колонки.Добавить("Значение");
    
    // Добавляем первое свойство
    НоваяСтрока = ТаблицаСвойствИЗначений.Добавить();
    НоваяСтрока.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя","ИндСвойство_a6c5ac5d419a44bebcbe19171c190e40");
    НоваяСтрока.Значение = НовоеЗначение1;
    
    // Добавляем второе свойство
    НоваяСтрока = ТаблицаСвойствИЗначений.Добавить();
    НоваяСтрока.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя","ИндСвойство_ДругогоРеквизита");
    НоваяСтрока.Значение = НовоеЗначение2;
    
    // Вызываем процедуру записи
    УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ВладелецСвойств, ТаблицаСвойствИЗначений);
    
  5. Функции для работы с дополнительными реквизитами на форме: Модуль УправлениеСвойствами также предоставляет ряд процедур для корректной интеграции дополнительных реквизитов с управляемыми формами:
    • УправлениеСвойствами.ПриСозданииНаСервере(Форма, ДополнительныеПараметры): Используется при создании формы для инициализации элементов формы, связанных с дополнительными свойствами.
    • УправлениеСвойствами.ПриЧтенииНаСервере(Форма, ТекущийОбъект): Вызывается при чтении данных объекта на сервере, чтобы заполнить поля формы значениями дополнительных реквизитов.
    • УправлениеСвойствами.ПередЗаписьюНаСервере(Форма, ТекущийОбъект): Используется перед записью объекта, чтобы получить значения из полей формы и записать их в дополнительные реквизиты объекта.
    • УправлениеСвойствами.ОбработкаПроверкиЗаполнения(Форма, Отказ, ПроверяемыеРеквизиты, Объект): Позволяет интегрировать проверку заполнения дополнительных реквизитов в общую логику проверки заполнения формы.
    • УправлениеСвойствами.ЗаполнитьДополнительныеРеквизитыВФорме: Этот метод создает или пересоздает элементы управления для дополнительных реквизитов непосредственно на управляемой форме.

    Использование этих функций значительно упрощает разработку и обеспечивает типовое поведение для дополнительных реквизитов в управляемых формах.

4. Отличие дополнительных реквизитов и дополнительных сведений

Как мы уже упоминали, существует важное различие между дополнительными реквизитами и дополнительными сведениями, особенно в контексте их хранения и использования:

  1. Дополнительные реквизиты:
    • Хранение: Хранятся непосредственно в табличной части объекта (например, Номенклатура.ДополнительныеРеквизиты).
    • Назначение: Являются неотъемлемой частью объекта, описывают его основные характеристики.
    • Видимость: Обычно отображаются на основных формах объекта и редактируются вместе с его основными данными.
    • Управление: Чаще всего используются для свойств, которые должны быть доступны и изменяемы при работе с основным объектом.
  2. Дополнительные сведения:
    • Хранение: Хранятся в отдельном регистре сведений (РС.ДополнительныеСведения).
    • Назначение: Предназначены для хранения информации, которая не является критически важной для самого объекта, но может дополнять его описание.
    • Видимость: Могут быть доступны через отдельные формы или команды, и пользователи с правами только на чтение основного объекта могут иметь возможность просматривать/редактировать дополнительные сведения.
    • Управление: Полезны для расширения данных объекта без изменения его структуры или для информации, которая может быть опциональной или менее часто используемой.

Важно помнить, что в разных конфигурациях (например, УТ 10.3 vs УТ 11/УНФ) архитектура хранения и работы с этими данными может существенно различаться. УТ 10.3 использовала "обычные" формы и другую структуру, в то время как УТ 11 и УНФ перешли на управляемые формы и активно используют БСП, что меняет подходы к программной работе.

5. Как реализовать функцию, срабатывающую при заполнении двух реквизитов в обработке

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

Для решения этой задачи мы предлагаем следующие подходы:

  1. Использование события ПриИзменении с дополнительной проверкой:

    Несмотря на кажущееся несоответствие, мы можем использовать событие ПриИзменении для обоих реквизитов, но внутри обработчика выполнять проверку состояния другого реквизита.

    
    &НаКлиенте
    Процедура Реквизит1ПриИзменении(Элемент)
        ПроверитьИВыполнитьЛогику();
    КонецПроцедуры
    
    &НаКлиенте
    Процедура Реквизит2ПриИзменении(Элемент)
        ПроверитьИВыполнитьЛогику();
    КонецПроцедуры
    
    &НаКлиенте
    Процедура ПроверитьИВыполнитьЛогику()
        Если ЗначениеЗаполнено(Реквизит1) И ЗначениеЗаполнено(Реквизит2) Тогда
            // Вызываем основную логику на сервере
            ВыполнитьОсновнуюЛогикуНаСервере();
        Иначе
            // Можно сбросить результат, если логика зависит от обоих реквизитов
            РезультатРасчета = Неопределено;
        КонецЕсли;
    КонецПроцедуры
    
    &НаСервере
    Процедура ВыполнитьОсновнуюЛогикуНаСервере()
        // Здесь реализовываем логику, которая требует заполнения обоих реквизитов.
        // Например:
        // РезультатРасчета = Реквизит1 + Реквизит2;
        // Или вызываем функцию для заполнения дополнительного реквизита:
        // ЗаполнитьДополнительныйРеквизит(Реквизит1, Реквизит2);
    КонецПроцедуры
    

    Такой подход гарантирует, что ВыполнитьОсновнуюЛогикуНаСервере() будет вызвана только тогда, когда оба реквизита заполнены. Если один из реквизитов очищается, вы можете сбросить результат.

  2. Использование события ПередЗаписьюНаСервере (для объектов, не обработки):

    Если речь идет не об обработке, а о форме элемента справочника или документа, и нам нужно выполнить логику перед записью объекта, когда оба реквизита заполнены, мы можем использовать событие формы ПередЗаписьюНаСервере. Здесь мы имеем доступ ко всем данным объекта и можем выполнить проверку.

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

    Этот подход особенно полезен, когда логика должна быть выполнена один раз перед сохранением данных, и мы хотим быть уверены в полноте данных.

  3. Применение событий из модуля УправлениеСвойствами:

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

    Кроме того, в обработчиках ПриЧтенииНаСервере или ПередЗаписьюНаСервере, которые вызываются через модуль УправлениеСвойствами, вы также можете реализовать вашу логику проверки и заполнения. Это обеспечивает консистентность с общей логикой БСП.

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

← На главную