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

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

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

Зачем проверять наличие реквизита?

Рассмотрим стандартную ситуацию: вы пишете универсальный механизм, который должен добавить на форму поле для ввода дополнительных сведений. Если процедура инициализации формы вызовется дважды (например, при перечитывании данных или в сложных цепочках событий), попытка повторного добавления реквизита ИспользоватьДопСведения приведет к аварийному завершению работы кода. Нам важно научиться определять, существует ли уже такой «динамический гость» на нашей форме.

Способ 1. Использование метода ПолучитьРеквизиты() и перебор коллекции

Самый надежный и «чистый» с точки зрения отладки способ — это анализ массива, который возвращает метод формы ПолучитьРеквизиты(). Проанализируем, как это работает на практике.

Метод ПолучитьРеквизиты() возвращает массив объектов типа РеквизитФормы. Каждый такой объект имеет свойство Имя. Рассмотрим пример функции, которая возвращает булево значение в зависимости от наличия реквизита:


&НаСервере
Функция РеквизитФормыСуществует(ИмяРеквизита)
    
    МассивРеквизитов = ЭтаФорма.ПолучитьРеквизиты();
    Для Каждого Реквизит Из МассивРеквизитов Цикл
        Если Реквизит.Имя = ИмяРеквизита Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Ложь;
    
КонецФункции

Почему это лучше других методов? Во-первых, вы не используете исключения для логики программы (что считается плохим тоном в программировании). Во-вторых, при отладке вы всегда видите реальный список того, что сейчас «живет» на форме.

Способ 2. Проверка через блок Попытка...Исключение

Некоторые разработчики предпочитают краткость и используют механизм обработки ошибок. Суть проста: мы пытаемся обратиться к реквизиту «напрямую». Если он есть — код выполняется, если нет — управление переходит в блок Исключение.

Разберем пример такого кода:


ЕстьРеквизит = Истина;
Попытка
    Значение = ЭтаФорма["ИспользоватьДопСведения"];
Исключение
    ЕстьРеквизит = Ложь;
КонецПопытки;

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

Способ 3. Оптимизация поиска через Соответствие (для частых проверок)

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

Посмотрим, как оптимизировать этот процесс:


&НаСервере
Процедура ПроверитьМножествоРеквизитов()
    
    // Собираем все имена в карту (Соответствие) для быстрого доступа
    КартаРеквизитов = Новый Соответствие;
    Для Каждого Рекв Из ПолучитьРеквизиты() Цикл
        КартаРеквизитов.Вставить(Рекв.Имя, Истина);
    КонецЦикла;
    
    // Теперь проверка занимает доли секунды вне зависимости от количества реквизитов
    Если КартаРеквизитов["Реквизит1"] <> Неопределено Тогда
        // Действие...
    КонецЕсли;
    
КонецПроцедуры

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

В ходе обсуждения на форуме выяснилось, что автору требовалось не просто проверить наличие, а «пересоздать» реквизит или избежать ошибки уникальности при использовании ИзменитьРеквизиты().

Метод ИзменитьРеквизиты() принимает два основных параметра:

  1. Массив объектов РеквизитФормы, которые нужно добавить.
  2. Массив строк (имен), которые нужно удалить.

Важное правило: Вы не можете удалить реквизиты, которые были созданы в конфигураторе (статические). Удалению подлежат только те, что были добавлены программно.

Разберем ситуацию, когда нам нужно гарантированно добавить реквизит, удалив старый, если он мешает:


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

Типичные ошибки при работе с ИзменитьРеквизиты()

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

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

Итоги

Для надежной работы с управляемыми формами мы рекомендуем придерживаться следующего алгоритма:

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

← На главную