В процессе разработки на платформе 1С:Предприятие 8.3 (особенно при работе с обычными формами) часто возникает задача массового изменения данных в табличной части документа или обработки. Например, нужно одним нажатием кнопки сбросить все «флажки» (значение Ложь) или проставить статус для нескольких тысяч строк. Рассмотрим подробно, как это сделать максимально эффективно, разберем различные методы и выясним, какой из них быстрее на больших объемах данных.
Многие программисты стараются избегать циклов, считая их медленными. Однако в обычных формах основной причиной «тормозов» является не сам цикл Для каждого, а визуальное обновление таблицы на форме при изменении каждой строки. Если строк около 15 000, платформа пытается перерисовать список 15 000 раз, что и вызывает зависание.
Проанализируем ситуацию: чтобы ускорить процесс, нам нужно временно «заморозить» графическую оболочку. Для этого используем метод Обновление() у элемента формы.
Рассмотрим пример кода:
// Отключаем обновление формы, чтобы ускорить цикл
ЭлементыФормы.ИмяТабличнойЧасти.Обновление(Ложь);
Для Каждого СтрокаТЧ Из Объект.ИмяТабличнойЧасти Цикл
СтрокаТЧ.ИмяКолонки = Ложь;
КонецЦикла;
// Включаем обновление обратно
ЭлементыФормы.ИмяТабличнойЧасти.Обновление(Истина);
Важный нюанс: Этот способ является самым надежным для табличных частей (ТЧ) объектов, так как он работает напрямую с данными коллекции, не требуя выделения дополнительной памяти на копирование всей таблицы.
Если количество строк исчисляется десятками или сотнями тысяч, можно воспользоваться платформенным методом ЗаполнитьЗначения(), который реализован для объекта ТаблицаЗначений. Этот метод написан на уровне ядра платформы и работает крайне быстро.
Разберем по шагам алгоритм действий:
Посмотрим на пример реализации:
// Выгружаем ТЧ в таблицу значений
ПромежуточнаяТЗ = Объект.ИмяТабличнойЧасти.Выгрузить();
// Быстро заполняем нужную колонку во всех строках
ПромежуточнаяТЗ.ЗаполнитьЗначения(Ложь, "ИмяКолонки");
// Загружаем данные обратно
Объект.ИмяТабличнойЧасти.Загрузить(ПромежуточнаяТЗ);
Анализ производительности: Несмотря на скорость ЗаполнитьЗначения, операции Выгрузить() и Загрузить() требуют копирования всех данных таблицы в памяти. На объеме в 15 000 строк, как в вопросе автора, накладные расходы на копирование могут сделать этот метод даже медленнее, чем обычный оптимизированный цикл из первого метода. Этот подход рекомендуется использовать, когда количество строк превышает 50 000–100 000.
Часто задача звучит как «сбросить все установленные флажки». Если из 15 000 строк флажок стоит только в 100, то перебирать все 15 000 строк не имеет смысла. Мы можем отобрать только те строки, которые нужно изменить.
Выясним, как это сделать с помощью метода НайтиСтроки():
// Создаем структуру отбора
ПараметрыОтбора = Новый Структура("ИмяКолонки", Истина);
// Получаем массив только тех строк, где значение равно Истина
НайденныеСтроки = Объект.ИмяТабличнойЧасти.НайтиСтроки(ПараметрыОтбора);
// Перебираем только найденные строки
Для Каждого Строка Из НайденныеСтроки Цикл
Строка.ИмяКолонки = Ложь;
КонецЦикла;
Этот метод значительно быстрее классического перебора, если количество изменяемых строк существенно меньше общего количества строк в таблице.
Если пользователь установил фильтр (отбор) в списке на форме и нажал «Сбросить всё», он обычно ожидает, что изменятся только видимые строки. В обычных формах фильтрация на уровне элемента управления не меняет физический состав коллекции Объект.ИмяТабличнойЧасти.
Чтобы изменить данные только в отфильтрованных строках, нам нужно обратиться к построителю отчета, который управляет отображением данных в элементе формы:
// Пример получения только видимых строк через построитель (для обычных форм)
Построитель = ЭлементыФормы.ИмяТабличнойЧасти.ПостроительОтчета;
Результат = Построитель.Результат.Выгрузить();
// Далее работаем с результатом как с обычной ТЗ
В некоторых случаях, если данных слишком много и менять их физически в таблице накладно, можно использовать технику «виртуальной галки». Суть метода заключается в том, чтобы хранить изменения не в самой ТЧ, а в отдельном массиве или соответствии (ключ — номер строки, значение — состояние флажка).
Проанализируем ситуацию: в событии ПриВыводеСтроки мы можем подменять отображаемое значение колонки. Если в нашей форме стоит общая галка «Выделить всё», мы просто запоминаем это состояние в переменной, а в коде обработки результата проверяем: если галка «Выделить всё» стоит, значит считаем все строки выбранными, за исключением тех, что попали в «список исключений».
Это позволяет мгновенно менять состояние интерфейса для любого количества строк (даже миллиона), так как физической записи в каждую строку не происходит.
Для решения задачи автора (15 000 строк на обычной форме 1С 8.3) наиболее сбалансированным решением будет:
Для каждого) обязательно в связке с ЭлементыФормы.Таблица.Обновление(Ложь). Это просто в реализации и достаточно быстро.НайтиСтроки).