В процессе разработки сложных интерфейсов на платформе 1С:Предприятие 8.3 часто возникает необходимость динамического изменения состава данных формы. Если создание реквизитов программным путем — задача привычная, то их корректное удаление вызывает ряд вопросов, связанных с производительностью системы и целостностью графического интерфейса. В этой статье мы подробно разберем, как правильно избавляться от ненужных программных реквизитов, избегая типичных ошибок начинающих разработчиков.
Для манипуляции структурой данных формы в языке 1С предусмотрен универсальный метод ИзменитьРеквизиты. Важно понимать, что этот метод доступен только на стороне сервера. Проанализируем его синтаксис и особенности работы, чтобы заложить фундамент для правильного кода.
Метод ИзменитьРеквизиты принимает два основных параметра:
РеквизитФормы.Важный нюанс: платформа 1С спроектирована так, что любое изменение структуры формы (добавление или удаление хотя бы одного реквизита) инициирует полную пересборку контекста формы. Это крайне ресурсоемкая операция. Рассмотрим, почему нельзя выполнять удаление в цикле.
Часто новички пытаются удалять реквизиты сразу же, как только нашли их в коллекции. Проанализируем пример «плохого» кода:
// НЕПРАВИЛЬНО: Вызов ИзменитьРеквизиты внутри цикла
Для каждого Рек Из ЭтаФорма.ПолучитьРеквизиты() Цикл
Если СтрНайти(Рек.Имя, "Смета") <> 0 Тогда
МассивУдаляемых = Новый Массив;
МассивУдаляемых.Добавить(Рек.Имя);
ЭтаФорма.ИзменитьРеквизиты(, МассивУдаляемых); // Каждый вызов тормозит сервер
КонецЕсли;
КонецЦикла;
В данном случае, если у нас 10 реквизитов, сервер 10 раз будет перестраивать всю структуру формы. Это приведет к заметным задержкам в интерфейсе (так называемым «фризам»). Выясним, как сделать это правильно.
Рассмотрим оптимальный алгоритм. Основная идея заключается в том, чтобы сначала собрать все имена реквизитов, подлежащих удалению, в один массив, и лишь затем передать этот массив методу ИзменитьРеквизиты. Таким образом, тяжелая операция пересборки формы выполнится ровно один раз.
Разберем по шагам реализацию этого подхода:
// ПОДХОДИТ ДЛЯ ПРОДАКШЕНА: Пакетное удаление
РеквизитыФормы = ЭтаФорма.ПолучитьРеквизиты();
МассивУдаляемых = Новый Массив;
Для Каждого РеквизитФормы Из РеквизитыФормы Цикл
ИмяРеквизита = РеквизитФормы.Имя;
// Используем комбинированное условие для точности
// Например, удаляем все реквизиты, содержащие "Смета", кроме "ТекущаяСмета"
Если СтрНайти(ИмяРеквизита, "Смета") И Не СтрНайти(ИмяРеквизита, "ТекущаяСмета") Тогда
МассивУдаляемых.Добавить(ИмяРеквизита);
КонецЕсли;
КонецЦикла;
// Выполняем удаление одним пакетом
Если МассивУдаляемых.Количество() > 0 Тогда
ЭтаФорма.ИзменитьРеквизиты(, МассивУдаляемых);
КонецЕсли;
В этом примере мы используем переменную ИмяРеквизита для оптимизации. Посмотрим на причину: обращение через точку (РеквизитФормы.Имя) — это по сути поиск свойства в объекте. Если нам нужно обратиться к имени несколько раз внутри итерации, лучше сохранить его в локальную переменную.
Проанализируем ситуацию, о которой часто забывают. Удаление реквизита из данных формы не удаляет автоматически связанные с ним визуальные элементы (поля ввода, надписи, кнопки). Если вы удалите реквизит Смета1, но на форме останется поле ввода, связанное с этим путем данных, платформа выдаст ошибку при отрисовке или оставит «мертвое» поле.
Поэтому порядок действий всегда должен быть следующим:
Пример комплексной очистки группы на форме:
// Очистка группы и удаление связанных данных
ИмяГруппы = "ГруппаДинамическихРеквизитов";
ГруппаЭлементов = ЭтаФорма.Элементы[ИмяГруппы];
МассивУдаляемыхДанных = Новый Массив;
// 1. Удаляем визуальные элементы
Для Каждого Элемент Из ГруппаЭлементов.ПодчиненныеЭлементы Цикл
ПутьКДанным = Элемент.ПутьКДанным;
МассивУдаляемыхДанных.Добавить(ПутьКДанным);
ЭтаФорма.Элементы.Удалить(Элемент);
КонецЦикла;
// 2. Удаляем данные
Если МассивУдаляемыхДанных.Количество() > 0 Тогда
ЭтаФорма.ИзменитьРеквизиты(, МассивУдаляемыхДанных);
КонецЕсли;
Иногда требуется удалить не основной реквизит формы, а программно созданную колонку в таблице. В этом случае в массив удаляемых реквизитов нужно передавать полный путь к данным через точку.
Например, если у нас есть программная таблица ТаблицаРезультатов и мы хотим удалить колонку СуммаИтого, строка в массиве должна выглядеть так: "ТаблицаРезультатов.СуммаИтого".
Важно: Если вы удаляете родительский реквизит (всю таблицу целиком), то все вложенные в неё реквизиты (колонки) будут удалены автоматически. Отдельно перечислять их в массиве нет необходимости.
Начиная с версии платформы 8.3.16, механизмы работы с формой были оптимизированы. Однако общие рекомендации остаются прежними. Посмотрим на дополнительные советы по повышению быстродействия:
ИзменитьРеквизиты(МассивДобавляемых, МассивУдаляемых). Платформа сначала обработает удаление, а затем добавление, что сэкономит целый цикл перестроения контекста.Видимость. Это работает значительно быстрее, чем физическое удаление и создание.ИзменитьРеквизиты нельзя удалить реквизиты, созданные вручную в конфигураторе. Попытка сделать это приведет к исключительной ситуации.Мы выяснили, что программное управление составом реквизитов — мощный инструмент, требующий аккуратности. Для успешного удаления придерживайтесь следующих правил:
ИзменитьРеквизиты на одну логическую операцию).Следуя этим инструкциям, вы обеспечите стабильную и быструю работу ваших динамических форм в 1С.