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