Как в 1С 7.7 выполнить обход таблицы значений с конца?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью обработать данные в таблице значений (ТЗ) в обратном порядке. Несмотря на то что эта задача кажется тривиальной, встроенный язык версии 7.7 имеет ряд особенностей и ограничений, которые отличают его от более современной версии 8.х. В частности, стандартный цикл Для здесь не поддерживает отрицательный шаг.

В этой статье мы подробно разберем, зачем нужен обратный обход, проанализируем основные способы его реализации и выясним, какой из них является наиболее эффективным и безопасным с точки зрения производительности.

Зачем нужен обход таблицы значений с конца?

Прежде чем перейти к коду, давайте выясним причину возникновения такой задачи. Хотя автор исходного вопроса уточнил, что удаление строк не требуется, в подавляющем большинстве случаев обход «с хвоста» используется именно для удаления строк по условию.

Разберем ситуацию: если мы удаляем строки, двигаясь от первой к последней (от 1 до N), то после удаления, например, второй строки, третья строка автоматически становится второй. Счетчик цикла при этом переходит к индексу «3», и в итоге строка, которая была третьей, просто пропускается алгоритмом. При обходе с конца (от N до 1) индекс текущей обрабатываемой строки никак не влияет на номера тех строк, которые нам еще только предстоит проверить. Именно поэтому умение «разворачивать» цикл является базовым навыком для разработчика 7.7.

Метод 1: Использование стандартного цикла «Пока»

Поскольку цикл Для в 1С 7.7 умеет работать только на увеличение (инкремент), самым правильным и читаемым способом реализации обратного обхода считается использование цикла Пока. Рассмотрим этот алгоритм по шагам:

  1. Определяем общее количество строк в таблице с помощью метода КоличествоСтрок().
  2. Устанавливаем счетчик на номер последней строки.
  3. Внутри цикла уменьшаем счетчик на единицу вручную.

Посмотрим на пример кода:


// Предположим, у нас есть заполненная ТаблицаЗначений ТЗ
Счетчик = ТЗ.КоличествоСтрок();

Пока Счетчик > 0 Цикл
    // Делаем строку с текущим номером активной
    ТЗ.ПолучитьСтрокуПоНомеру(Счетчик);
    
    // Здесь выполняется полезная работа с данными строки
    Сообщить("Обрабатываем строку номер: " + Счетчик);
    
    // Уменьшаем счетчик для перехода к предыдущей строке
    Счетчик = Счетчик - 1;
КонецЦикла;

Этот метод считается «золотым стандартом» для 7.7, так как он нагляден, не требует математических ухищрений и работает максимально быстро.

Метод 2: Математическая хитрость с циклом «Для»

Иногда программисты хотят во что бы то ни стало использовать конструкцию Для. Так как шаг цикла всегда равен +1, мы можем использовать отрицательные числа, чтобы имитировать обратный порядок. Разберем этот оригинальный подход, предложенный в сообществе.

Суть заключается в том, чтобы запустить цикл от «минус максимальное количество строк» до «минус один». Тогда, применяя оператор «минус» к счетчику внутри цикла, мы получим положительный индекс строки.

Проанализируем пример кода:


ВсегоСтрокМинус = - ТЗ.КоличествоСтрок();

Для Счетчик = ВсегоСтрокМинус По -1 Цикл
    // Инвертируем знак счетчика, чтобы получить номер строки (например, -(-10) = 10)
    ТЗ.ПолучитьСтрокуПоНомеру(-Счетчик);
    
    // Обработка данных
    Сообщить("Текущая строка: " + ТЗ.НомерСтроки);
КонецЦикла;

Важно: Несмотря на работоспособность, такой код сложнее читать другим разработчикам. Используйте его только в том случае, если это обусловлено специфическими требованиями архитектуры вашего модуля.

Метод 3: Сортировка таблицы значений

Еще один способ «перевернуть» данные — это физически изменить их порядок в таблице. Метод Сортировать() позволяет выстроить строки в порядке убывания по определенной колонке.

Рассмотрим ситуацию, когда у нас есть колонка, по которой можно однозначно определить порядок (например, «Дата», «Номер» или «Сумма»):


// Сортировка по колонке "Номенклатура" в обратном алфавитном порядке
ТЗ.Сортировать("Номенклатура-");

// Теперь можно идти обычным циклом с начала, так как конец стал началом
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    // Обработка уже "развернутых" данных
КонецЦикла;

Однако у этого метода есть два существенных недостатка, которые мы должны учитывать:

  1. Изменение структуры: После завершения работы алгоритма строки останутся в новом порядке. Если для других частей программы важен исходный порядок, вам придется либо сортировать таблицу обратно, либо отказываться от этого метода.
  2. Производительность: Сортировка — это ресурсозатратная операция, особенно если в таблице десятки тысяч строк. Простой перебор индексов (как в методе 1) всегда будет быстрее.

Метод 4: Использование временной индексной колонки

Что делать, если нужно обойти таблицу в обратном порядке относительно того, как строки добавлялись, но при этом в таблице нет подходящей колонки для сортировки (данные повторяются или хаотичны)? Профессиональные разработчики используют метод «служебного индекса».

Разберем этот метод по шагам:

  1. Добавляем в таблицу временную колонку типа «Число».
  2. Заполняем её порядковыми номерами (1, 2, 3...).
  3. Сортируем таблицу по этой колонке с пометкой «-» (убывание).
  4. Проводим обработку и в конце удаляем служебную колонку.

// Добавляем служебную колонку
ТЗ.НоваяКолонку("СлужебныйПорядок", "Число");

// Заполняем её
ТЗ.ВыбратьСтроки();
Ном = 0;
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    Ном = Ном + 1;
    ТЗ.СлужебныйПорядок = Ном;
КонецЦикла;

// Разворачиваем таблицу
ТЗ.Сортировать("СлужебныйПорядок-");

// ... производим действия ...

// Удаляем колонку, чтобы не портить вид ТЗ (например, в печатной форме)
ТЗ.УдалитьКолонку("СлужебныйПорядок");

Важный технический нюанс: Метод ПолучитьСтрокуПоНомеру()

При использовании любого из вышеперечисленных методов (кроме прямой выборки) крайне важно помнить: функция ТЗ.ПолучитьСтрокуПоНомеру(Номер) делает указанную строку текущей в контексте объекта таблицы. Это означает, что если вы внутри цикла вызываете другую процедуру, которая также обращается к этой же таблице значений, позиция строки может «сбиться».

Совет: Если ваш цикл сложный, старайтесь сразу после позиционирования на строке считывать все нужные значения колонок в локальные переменные, чтобы избежать ошибок при случайном переключении контекста строки.

Мы рассмотрели все основные способы обхода таблицы значений с конца в среде 1С 7.7. Для большинства задач оптимальным выбором будет цикл «Пока» с декрементом счетчика, так как он сочетает в себе высокую производительность и чистоту кода.

← На главную