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

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

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

Причина возникновения ошибки «Недопустимый путь к реквизиту»

Проанализируем типичную ситуацию: при программном создании реквизитов разработчик передает в метод ИзменитьРеквизиты() массив объектов типа РеквизитФормы. Однако при попытке удаления реквизитов через тот же метод передача массива таких же объектов приводит к аварийному завершению с ошибкой.

Выясним причину такого поведения. Метод ИзменитьРеквизиты() принимает два параметра с принципиально разными типами элементов:

  1. Параметр 1 (Добавляемые реквизиты) — принимает массив объектов типа РеквизитФормы.
  2. Параметр 2 (Удаляемые реквизиты) — принимает массив строк, содержащих полные имена (пути) удаляемых реквизитов.

Если во второй параметр передать объекты типа РеквизитФормы, платформа пытается неявно преобразовать объект в строку и получает строковое представление типа "РеквизитФормы", после чего сообщает, что путь с таким именем не найден на форме.

Пошаговое создание и удаление реквизитов формы

Рассмотрим правильный алгоритм работы с динамическими реквизитами на сервере.

1. Программное создание реквизита

Для создания реквизита верхнего уровня создается объект РеквизитФормы, где указывается имя реквизита и его тип. Параметр пути для реквизитов верхнего уровня оставляется пустым. Затем реквизит добавляется в массив и регистрируется на форме:


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

2. Корректное программное удаление реквизита

Чтобы удалить ранее созданный реквизит, необходимо собрать в массив строковые имена реквизитов, которые требуется удалить, и передать их во второй параметр метода ИзменитьРеквизиты():


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

Удаление реквизитов вместе с элементами интерфейса

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


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

Важные правила и ограничения платформы

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