В процессе разработки в среде 1С:Предприятие часто возникает задача массового изменения данных в табличных частях документов или обработок. Типичный сценарий: необходимо найти определенные строки по условию (например, по конкретному товару или статусу) и обнулить в них значения сразу нескольких числовых колонок. Если таких колонок две-три, задача решается быстро, но что делать, если их десятки (например, 37, как у автора вопроса)?
В этой статье мы разберем несколько подходов к решению данной задачи: от самого простого «в лоб» до максимально оптимизированных методов, которые будут быстро работать даже на больших объемах данных.
Рассмотрим самый очевидный вариант. Если нам нужно проверить условие в каждой строке и обнулить значения в конкретных колонках, мы можем использовать цикл Для Каждого. Этот метод хорош своей наглядностью и простотой отладки.
Проанализируем пример кода:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
Если СтрокаТЧ.Номенклатура = ВыбраннаяНоменклатура Тогда
СтрокаТЧ.Количество = 0;
СтрокаТЧ.Сумма = 0;
СтрокаТЧ.СуммаНДС = 0;
КонецЕсли;
КонецЦикла;
Преимущества: код понятен любому разработчику. Недостатки: если колонок много (например, 37), код становится громоздким. Кроме того, перебор абсолютно всех строк таблицы может быть медленным, если в табличной части их тысячи, а условию соответствуют лишь две-три.
Чтобы не перебирать всю таблицу, мы можем воспользоваться встроенным методом платформы НайтиСтроки(). Рассмотрим ситуацию, когда нам нужно отобрать строки по конкретному значению в одной колонке.
Разберем алгоритм действий:
Отбор = Новый Структура("Склад", СкладДляОбнуления);
НайденныеСтроки = Объект.Товары.НайтиСтроки(Отбор);
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
СтрокаТЧ.Количество = 0;
// И так далее для всех нужных колонок...
КонецЦикла;
Это значительно эффективнее прямого перебора, так как платформа использует внутренние механизмы поиска.
Если стоит задача обнулить вообще все числовые показатели в строке, не перечисляя их имена вручную, мы можем проанализировать метаданные колонок. Выясним, как это реализовать с помощью вложенного цикла по коллекции колонок.
Посмотрим на пример реализации:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
Если СтрокаТЧ.Статус = Перечисления.Статусы.Неактивен Тогда
// Перебираем все колонки таблицы
Для Каждого Колонка Из Объект.Товары.Выгрузить().Колонки Цикл
// Проверяем, является ли тип данных в колонке числовым
Если Колонка.ТипЗначения.СодержитТип(Тип("Число")) Тогда
СтрокаТЧ[Колонка.Имя] = 0;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Важное замечание по оптимизации: проверка типа колонки ТипЗначения.СодержитТип внутри цикла по строкам — это ресурсозатратная операция. Если у вас 1000 строк и 37 колонок, проверка выполнится 37 000 раз. Проанализируем, как сделать это лучше: правильнее будет один раз составить список имен числовых колонок (в массив), а затем в основном цикле обращаться только к ним.
Это, пожалуй, самый элегантный и быстрый способ для случая с большим количеством колонок. Мы можем использовать метод ЗаполнитьЗначенияСвойств(), который работает на уровне платформы очень эффективно.
Рассмотрим пошагово, как это реализовать:
НайтиСтроки для получения нужного подмножества данных.ЗаполнитьЗначенияСвойств к каждой строке.
// 1. Готовим структуру-маску (можно заполнить программно в цикле по метаданным)
СтруктураОбнуления = Новый Структура;
СтруктураОбнуления.Вставить("Количество", 0);
СтруктураОбнуления.Вставить("Сумма", 0);
СтруктураОбнуления.Вставить("Вес", 0);
// ... и так далее для всех 37 полей
// 2. Получаем нужные строки
НайденныеСтроки = Объект.Товары.НайтиСтроки(Новый Структура("Обнулить", Истина));
// 3. Быстрое заполнение
Для Каждого ТекущаяСтрока Из НайденныеСтроки Цикл
ЗаполнитьЗначенияСвойств(ТекущаяСтрока, СтруктураОбнуления);
КонецЦикла;
Этот метод избавляет от написания 37 строк присваивания и работает быстрее, чем обращение к каждой колонке через квадратные скобки СтрокаТЧ[ИмяКолонки].
Разберем еще несколько нюансов, которые помогут сделать ваш код профессиональнее:
ТаблицаЗначений методом Выгрузить(), обработать её там и загрузить обратно Загрузить(). В ТЗ поиск и замена происходят быстрее, но помните, что метод Загрузить полностью перезаписывает строки, что может повлиять на связи (например, если у строк есть уникальные идентификаторы).ТаблицаЗначений есть метод ЗаполнитьЗначения(0, "ИмяКолонки"). Он работает мгновенно, но заполняет все строки в колонке. Если вам нужно обнулить только определенные строки, этот метод не подойдет в чистом виде, но его можно использовать, если предварительно скопировать нужные строки в отдельную временную ТЗ.РассчитатьИтоги() или через обработчики событий при изменении.Резюме: Для обнуления большого количества колонок в 1С оптимальным является сочетание метода НайтиСтроки() для фильтрации и ЗаполнитьЗначенияСвойств() с заранее подготовленной структурой-маской для записи нулей. Это обеспечивает баланс между скоростью разработки, читаемостью кода и производительностью системы.