Как программно удалить реквизиты и элементы с формы 1С без ошибок?

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

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

Анализ проблемы: почему возникает ошибка?

Когда мы вызываем метод ИзменитьРеквизиты, платформа выполняет глубокую реструктуризацию формы на стороне сервера. Ошибка удаления часто связана с одной из трех причин:

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

Проанализируем ситуацию, когда колонки добавляются в существующую табличную часть Объект.ЦеныКлиентов. Платформа воспринимает такие реквизиты как дочерние по отношению к основной ТЧ объекта. Если логика именования или очистки нарушена, система блокирует удаление, чтобы не нарушить целостность структуры данных формы.

Шаг 1: Правильный порядок удаления элементов и реквизитов

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

Разберем пример кода для корректной очистки формы перед повторным заполнением:


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

// 2. И только теперь удаляем сами реквизиты из структуры формы
Если МассивУдаляемыхРеквизитов.Количество() > 0 Тогда
    ЭтаФорма.ИзменитьРеквизиты(, МассивУдаляемыхРеквизитов);
КонецЕсли;

Важный нюанс: Обратите внимание на обнуление ПутьКДанным перед удалением элемента. Это помогает избежать «зависания» ссылок в памяти платформы при сложных перестроениях формы.

Шаг 2: Проблема имен и путей к данным

Выясним причину ошибки, связанную с именованием. Метод ИзменитьРеквизиты принимает два массива: добавляемые и удаляемые. Для добавления мы используем объекты типа РеквизитФормы, где указываем имя и родителя. Для удаления — просто строковые имена путей.

Если вы добавили реквизит с родителем "Объект.ЦеныКлиентов" и именем "Цена1", то при удалении в массиве должна быть строка "Объект.ЦеныКлиентов.Цена1". Если вы ошибетесь хотя бы в одном символе или попытаетесь удалить только "Цена1" без указания родителя, платформа выдаст ошибку или просто проигнорирует команду.

Проанализируем пример некорректного добавления, который часто встречается в коде:


Для Каждого Стр Из ТаблицаНоменклатуры Цикл
    ИмяРеквизита = "Цена_" + Стр.ID;
    нРеквизиты = Новый Массив;
    нРеквизиты.Добавить(Новый РеквизитФормы(ИмяРеквизита, Новый ОписаниеТипов("Число"), "Объект.Товары", "Цена номенклатуры"));
    
    // ОШИБКА: ИзменитьРеквизиты нельзя вызывать внутри цикла!
    ИзменитьРеквизиты(нРеквизиты); 
КонецЦикла;

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

Шаг 3: Оптимальный алгоритм создания динамических колонок

Рассмотрим, как правильно организовать процесс «удаление — добавление» в одном вызове метода. Это наиболее стабильный и производительный способ.


// Подготавливаем массивы
МассивДобавляемых = Новый Массив;
МассивУдаляемых = Новый Массив;

// Заполняем массив на удаление старых колонок (как показано выше)
// ... (логика поиска старых путей к данным)

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

// Выполняем ОДИН вызов для всех изменений
ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемых, МассивУдаляемых);

// Теперь создаем элементы управления для новых реквизитов
Для Каждого Реквизит Из МассивДобавляемых Цикл
    НовоеПоле = Элементы.Добавить(Реквизит.Имя, Тип("ПолеФормы"), Элементы.ЦеныКлиентов);
    НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
    НовоеПоле.ПутьКДанным = "Объект.ЦеныКлиентов." + Реквизит.Имя;
КонецЦикла;

Альтернативный подход: использование Таблицы Значений вместо ТЧ Объекта

Если вы чувствуете, что работа с динамическими колонками в составе Объекта (документа или справочника) идет тяжело, рассмотрим профессиональный «лайфхак». Часто гораздо проще работать не с реальной табличной частью документа, а с отдельным реквизитом формы типа «ТаблицаЗначений».

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

  1. Вы не рискуете повредить структуру данных самого документа при записи.
  2. Реквизиты типа ТаблицаЗначений на форме гораздо «лояльнее» относятся к программному пересозданию колонок.
  3. Вы можете полностью очистить таблицу и пересоздать её структуру заново в любой момент.

Алгоритм работы в этом случае следующий: при открытии формы данные из Объект.ТабличнаяЧасть перекладываются в ТаблицаФормы (реквизит ТЗ). Пользователь работает с этой таблицей, где программно создаются любые колонки. Перед записью документа данные из ТЗ программно переносятся обратно в ТЧ объекта.

Советы по отладке

Если ошибка «Удаление дочернего реквизита невозможно» продолжает появляться, выполните следующие действия:

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

← На главную