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