Разработка и Конфигурация · 10 мин
Что такое итерация в 1С и как работают циклы
Что такое итерация в 1С простыми словами: как работают циклы Для, Пока и обход коллекций, примеры кода на встроенном языке, типичные ошибки и советы.
Итерация — это один проход цикла, один шаг повторяющейся операции. Когда программа обрабатывает список товаров, строк табличной части документа или записи регистра, она выполняет одни и те же действия много раз подряд — и каждое такое выполнение тела цикла называется итерацией. Понимание этого термина необходимо любому, кто пишет или дорабатывает код на встроенном языке 1С.
В 1С итерации встречаются повсеместно: обход выборки из запроса, перебор строк документа, суммирование значений по массиву, поиск нужного элемента в справочнике. Почти любая процедура проведения документа содержит хотя бы один цикл, а значит — итерации.
Термин пришёл из общей теории программирования и означает одно и то же во всех языках, но в 1С есть свои особенности: специфические конструкции циклов, работа с выборками запросов и коллекциями, ограничения на обход данных в клиент-серверном режиме. Ниже разобраны виды циклов, примеры кода, способы управления итерациями и типичные ошибки.
Что такое итерация простыми словами
Представьте, что нужно посчитать сумму по каждой строке табличной части «Товары» в документе реализации. Программа берёт первую строку, выполняет расчёт, переходит ко второй строке, снова выполняет тот же расчёт — и так до конца таблицы. Каждый такой шаг — одна итерация.
Тело цикла — это набор команд, которые повторяются. Итерация — это один факт их выполнения. Если табличная часть содержит 50 строк, цикл обхода выполнит 50 итераций. Если строк нет, цикл не выполнится ни разу — итераций будет ноль.
Важно различать сам цикл и итерацию: цикл — это конструкция языка, а итерация — событие её выполнения. В отладчике 1С, нажимая «Шагнуть через», вы фактически наблюдаете, как одна итерация сменяет другую, и можете смотреть значения переменных на каждом шаге.
Виды циклов в 1С и их итерации
Встроенный язык 1С предоставляет три основные конструкции циклов, каждая из которых порождает итерации по-своему.
Цикл Для — счётный цикл
Конструкция Для Счетчик = 1 По 10 Цикл ... КонецЦикла; выполняет тело фиксированное число раз. Счётчик автоматически увеличивается на единицу после каждой итерации. Такой цикл удобен, когда количество повторений известно заранее: например, при обходе массива по индексу или при формировании фиксированного числа записей.
Цикл Пока — цикл с условием
Конструкция Пока Условие Цикл ... КонецЦикла; повторяется, пока условие истинно. Условие проверяется перед каждой итерацией, поэтому если оно ложно с самого начала, тело не выполнится ни разу. Здесь легко допустить бесконечный цикл, если забыть изменять переменные, влияющие на условие.
Цикл Для Каждого — обход коллекции
Конструкция Для Каждого Строка Из ТабличнаяЧасть Цикл ... КонецЦикла; — самый частый вариант в прикладном коде 1С. Цикл перебирает элементы коллекции: строки табличной части, элементы массива, строки таблицы значений, записи выборки запроса. На каждой итерации переменная цикла ссылается на очередной элемент коллекции.
Для Каждого СтрокаТовара Из Документ.Товары Цикл
СтрокаТовара.Сумма = СтрокаТовара.Количество * СтрокаТовара.Цена;
КонецЦикла;
В этом примере каждая итерация пересчитывает сумму в одной строке. Строк тридцать — тридцать итераций, строк нет — тело цикла не выполнится.
Какой цикл выбрать
Когда число повторений известно заранее или нужен доступ по индексу. Не подходит для коллекций, где удобнее перебирать элементы напрямую.
Когда условие выхода нельзя выразить числом: чтение данных до признака конца, итеративные расчёты. Требует контроля изменения условия.
Стандартный обход коллекций и выборок запросов. Не даёт встроенного индекса — при необходимости его ведут отдельной переменной.
Обход выборки запроса — самый частый случай итераций
В серверном коде 1С итерации чаще всего возникают при обходе результата запроса. Метод Выполнить() возвращает результат, метод Выбрать() — выборку, а цикл Пока Выборка.Следующий() Цикл перебирает записи по одной.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура, Количество ИЗ РегистрНакопления.Остатки.Остатки";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Номенклатура);
КонецЦикла;
Здесь метод Следующий() переводит указатель на следующую запись и возвращает Истина, пока записи не закончились. Каждый вызов, вернувший Истину, — это одна итерация. Альтернатива — выгрузить результат в таблицу значений методом Выгрузить() и обойти её циклом Для Каждого, что удобнее, когда нужен повторный обход тех же данных.
Управление итерациями: Прервать и Продолжить
Два оператора позволяют менять ход итераций внутри цикла. Прервать полностью останавливает цикл — текущая итерация завершается досрочно, и управление переходит на код после КонецЦикла. Это стандартный приём при поиске: нашли нужный элемент — дальше перебирать незачем.
Продолжить завершает только текущую итерацию и сразу переходит к следующей. Оператор удобен для пропуска элементов, не подходящих под условие, без вложенных блоков Если.
Для Каждого Строка Из Товары Цикл
Если Строка.Количество = 0 Тогда
Продолжить; // пропускаем пустые строки
КонецЕсли;
Если Строка.Номенклатура = ИскомыйТовар Тогда
НайденнаяСтрока = Строка;
Прервать; // нашли — выходим из цикла
КонецЕсли;
КонецЦикла;
- 1Поставьте точку останова на первой строке тела цикла
- 2Запустите отладку и дождитесь остановки внутри цикла
- 3Добавьте переменную цикла в табло (Ctrl+Shift+W или через контекстное меню)
- 4Нажимайте F10 или F11 и наблюдайте, как на каждой итерации меняются значения
- 5Считайте проходы — это и есть число выполненных итераций
Бесконечные циклы и производительность
Главный риск при работе с итерациями — бесконечный цикл. В цикле Пока он возникает, когда условие никогда не становится ложным: забыли сдвинуть указатель, не изменили счётчик, условие составлено с ошибкой. На толстом клиенте такой код «повесит» сеанс пользователя, на сервере — займёт рабочий процесс.
Вторая проблема — избыточное число итераций. Классический антипаттерн — запрос внутри цикла: на каждой итерации выполняется обращение к базе данных, и обход тысячи строк превращается в тысячу запросов. Правильное решение — один запрос с соединением или группировкой, а цикл используется только для обхода уже полученной выборки.
Также избегайте вложенных циклов с полным перебором: обход тысячи строк внутри обхода тысячи строк даёт миллион итераций. Если нужно сопоставить две таблицы, используйте соединение в запросе или соответствие для быстрого поиска по ключу.
Как проверить, что итерации работают правильно
Простейший способ — временно добавить счётчик итераций и вывести его после цикла через Сообщить(). Если вы ожидали обход 100 строк, а счётчик показывает 0 или 200, проблема в данных или в условии формирования коллекции.
Второй приём — отладчик: точка останова внутри тела цикла и просмотр переменной цикла на каждом шаге. Так видно, какие именно элементы обходятся, в каком порядке и не пропускается ли часть данных.
Как проверить результат
Совпадает с количеством элементов в коллекции или выборке
Меньше или больше ожидаемого — проверьте источник данных и условия Прервать/Продолжить
Растёт примерно пропорционально объёму данных
Резко увеличивается при небольшом росте данных — вероятен запрос в цикле или вложенный перебор
Каждый элемент обработан ровно один раз
Часть элементов пропущена или обработана дважды — проверьте логику Продолжить и изменение коллекции в цикле
Часто задаваемые вопросы
Чем итерация отличается от цикла?
Цикл — это конструкция языка (Для, Пока, Для Каждого), описывающая повторение. Итерация — один факт выполнения тела этого цикла. Один цикл порождает множество итераций или ни одной, если коллекция пуста или условие сразу ложно.
Можно ли узнать номер текущей итерации в цикле Для Каждого?
Встроенного счётчика у Для Каждого нет. Заведите переменную перед циклом, увеличивайте её в начале каждой итерации, либо используйте цикл Для с обращением к элементам по индексу, если коллекция это поддерживает.
Почему цикл Для Каждого пропускает строки при удалении?
Потому что удаление элемента сдвигает коллекцию, и внутренний указатель цикла «перепрыгивает» через следующий элемент. Удаляйте строки в обратном порядке по индексу или соберите элементы для удаления в отдельный массив и удалите их после завершения обхода.
Что быстрее: обход выборки запроса или таблицы значений?
Обход выборки экономит память, так как не материализует весь результат сразу, но допускает только один последовательный проход. Таблица значений требует памяти под все данные, зато позволяет повторные обходы, сортировку и поиск. Разница в скорости самого перебора обычно не критична — выбирайте по задаче.
Как прервать выполнение бесконечного цикла в отладке?
В конфигураторе используйте команду остановки отладки (Shift+F5) или кнопку «Остановить». Если код выполняется на сервере без отладки, сеанс придётся завершать через консоль кластера или администратор может снять зависший сеанс.
Есть ли в 1С аналог итераторов из других языков?
Явного интерфейса итератора нет, но роль итератора выполняют выборка запроса с методом Следующий() и внутренний механизм цикла Для Каждого. Для большинства прикладных задач этого достаточно.
Что важно запомнить
Итерация — один проход тела цикла. В 1С циклы строятся конструкциями Для, Пока и Для Каждого, а управлять итерациями помогают операторы Прервать и Продолжить. Главные риски — бесконечные циклы из-за неизменяющегося условия и потеря производительности из-за запросов внутри цикла; обе проблемы легко выявляются отладчиком и подсчётом числа итераций.