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