Как программно определить конкретный дополнительный реквизит на управляемой форме 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с типовыми конфигурациями 1С, построенными на базе Библиотеки стандартных подсистем (БСП), разработчики часто сталкиваются с механизмом дополнительных реквизитов и сведений. Этот механизм позволяет пользователям добавлять новые поля в справочники и документы без изменения структуры метаданных в Конфигураторе. Однако при попытке программного обращения к таким полям в коде возникают трудности, так как имена элементов на форме генерируются динамически и выглядят как трудночитаемые строки (например, ДополнительныйРеквизитЗначение_5CA41B80x...).

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

Суть проблемы динамических имен

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

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

Решение 1: Обращение через табличную часть объекта

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

Для начала нам необходимо получить ссылку на нужное свойство. Это можно сделать через поиск по наименованию (менее надежно) или через предопределенные элементы, если они созданы. Предположим, мы знаем наименование нашего реквизита.


// Пример поиска значения конкретного дополнительного реквизита
СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Флажок1");

Если Не СвойствоСсылка.Пустая() Тогда
    // Ищем строку в табличной части объекта
    ПараметрыПоиска = Новый Структура("Свойство", СвойствоСсылка);
    НайденныеСтроки = Объект.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыПоиска);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        ТекущееЗначение = НайденныеСтроки[0].Значение;
        // Теперь мы точно знаем, что работаем с "Флажком1"
        Если ТекущееЗначение = Истина Тогда
            Сообщить("Нажат флажок 1, выполняем Алгоритм №1");
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Этот метод хорош тем, что он работает непосредственно с данными объекта и не зависит от того, как именно называются элементы на форме.

Решение 2: Использование программного интерфейса БСП (API)

В современных конфигурациях 1С (ERP, КА, УТ 11, БП 3.0) предусмотрены специальные общие модули для работы со свойствами. Использование функций БСП — это "правильный" путь, который гарантирует стабильность кода при обновлениях системы. Разберем работу с модулем УправлениеСвойствами.

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


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

Если ЗначениеРеквизита = Истина Тогда
    Сообщить("Выполняется Алгоритм №2 для второго флажка");
КонецЕсли;

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

Решение 3: Интерактивная обработка изменения на форме

Если нам нужно выполнить действие не в момент записи, а сразу после того, как пользователь нажал на флажок, нам придется работать с событиями формы. В типовых конфигурациях для всех динамических реквизитов назначено общее событие Подключаемый_ПриИзмененииДополнительногоРеквизита.

Разберем по шагам, как вклиниться в этот процесс:

  1. Найдем в модуле формы процедуру Подключаемый_ПриИзмененииДополнительногоРеквизита.
  2. Внутри этой процедуры мы можем получить имя элемента, который вызвал событие.
  3. Используя свойство элемента ПутьКДанным, мы можем понять, на какую строку коллекции ДополнительныеРеквизиты он указывает.

Проанализируем пример кода для обработки нажатия:


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

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

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

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

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

← На главную