К статье
Практический материал

Разработка и Конфигурация · 10 мин

Что такое цикл в 1С и как его использовать

Что такое цикл в 1С простыми словами: конструкции Для, Для Каждого, Пока, примеры кода, типичные ошибки и способы избежать бесконечного цикла.

Цикл в 1С — это конструкция встроенного языка, которая многократно выполняет один и тот же блок кода, пока соблюдается заданное условие. Без циклов невозможно обойти табличную часть документа, перебрать строки таблицы значений, рассчитать итоги по списку номенклатуры или обработать выборку из запроса — то есть выполнить большинство повседневных задач разработки и доработки конфигураций.

Во встроенном языке 1С существует три основных вида циклов: Для (со счётчиком), Для Каждого (обход коллекции) и Пока (с условием). Они отличаются способом управления количеством повторений и типичными сценариями применения. Выбор конструкции влияет не только на читаемость кода, но и на устойчивость решения к ошибкам — например, к бесконечному выполнению.

Циклы работают одинаково в любых конфигурациях на платформе 1С:Предприятие 8 — в «Управлении торговлей», «Бухгалтерии», «Зарплате и управлении персоналом» и самописных решениях. Синтаксис един, различается только контекст: где-то цикл обходит строки документа, где-то — результат запроса или массив.

Как устроен цикл и когда он нужен

Любой цикл состоит из заголовка (условие или счётчик), тела (повторяемые операторы) и ключевого слова КонецЦикла. На каждом повторении — итерации — платформа проверяет условие продолжения и либо выполняет тело ещё раз, либо переходит к коду после цикла.

Типичные задачи, где без цикла не обойтись: подсчёт суммы по строкам документа, поиск строки с нужным товаром, заполнение табличной части по данным другой таблицы, пакетная обработка документов за период, формирование печатной формы с несколькими позициями. Если одно и то же действие нужно повторить больше одного раза — это задача для цикла.

Цикл Для: повторение по счётчику

Конструкция Для Счетчик = Начало По Конец Цикл ... КонецЦикла; выполняет тело заданное число раз, автоматически увеличивая переменную-счётчик на единицу. Это удобно, когда нужно обратиться к элементам по индексу или повторить действие фиксированное количество раз.

СуммаИтог = 0;

Для Инд = 0 По ТаблицаТоваров.Количество() - 1 Цикл

СуммаИтог = СуммаИтог + ТаблицаТоваров[Инд].Сумма;

КонецЦикла;

Обратите внимание: индексация коллекций в 1С начинается с нуля, поэтому верхняя граница — Количество() - 1. Ошибка в одну единицу здесь приведёт либо к пропуску последней строки, либо к обращению за границу коллекции с падением кода по ошибке.

Цикл Для Каждого: обход коллекций

Конструкция Для Каждого Строка Из Коллекция Цикл последовательно перебирает элементы табличной части, таблицы значений, массива или выборки. Это самый частый вид цикла в прикладном коде: не нужно следить за индексами, переменная сразу содержит текущий элемент.

Для Каждого СтрокаТовара Из Объект.Товары Цикл

Если СтрокаТовара.Количество = 0 Тогда

Сообщить("В строке " + СтрокаТовара.НомерСтроки + " не указано количество");

КонецЕсли;

КонецЦикла;

Используйте Для Каждого всегда, когда индекс элемента не нужен. Код становится короче и безопаснее: исключён выход за границы коллекции. Если же внутри цикла требуется удалять строки той же коллекции, обход «Для Каждого» опасен — состав коллекции меняется прямо во время перебора, и часть элементов будет пропущена. В такой ситуации обходите коллекцию циклом Для с конца или собирайте строки на удаление в отдельный массив.

Цикл Пока: повторение по условию

Конструкция Пока Условие Цикл ... КонецЦикла; выполняется, пока условие истинно. Проверка происходит перед каждой итерацией, поэтому если условие ложно с самого начала, тело не выполнится ни разу.

Классический сценарий — обход выборки из запроса:

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Наименование);

КонецЦикла;

Главный риск цикла Пока — бесконечное выполнение. Если внутри тела ничто не влияет на условие (например, не вызван метод Следующий() или не увеличен счётчик), цикл никогда не завершится, и сеанс «зависнет», пока его не снимет администратор или не сработает таймаут. Перед запуском кода всегда проверяйте, что на каждой итерации условие приближается к завершению.

Типичные ошибки
01
Цикл Пока без изменения условия внутри тела — бесконечное выполнение и зависший сеанс
02
Обращение к элементу по индексу, равному Количество() — ошибка выхода за границы, индексация идёт с нуля
03
Удаление строк коллекции внутри Для Каждого — пропуск элементов при обходе
04
Запрос к базе данных внутри цикла вместо одного запроса с соединением таблиц — резкое падение производительности

Управление циклом: Прервать и Продолжить

Оператор Прервать немедленно завершает цикл — выполнение переходит к коду после КонецЦикла. Его применяют, когда дальнейший перебор бессмыслен: например, нужная строка уже найдена.

Оператор Продолжить пропускает остаток тела текущей итерации и переходит к следующей. Так удобно отсекать неподходящие элементы в начале итерации, не оборачивая весь основной код в глубокие вложенные условия.

Для Каждого Строка Из ТаблицаДокументов Цикл

Если Не Строка.Проведен Тогда

Продолжить; // непроведённые пропускаем

КонецЕсли;

Если Строка.Сумма > 1000000 Тогда

Прервать; // нашли крупный документ, дальше не ищем

КонецЕсли;

КонецЦикла;

Как выбрать вид цикла под задачу

Выбор конструкции определяется источником данных и тем, что происходит внутри тела. Ориентируйтесь на простое правило: есть коллекция — берите Для Каждого; нужен индекс или обход с конца — Для; повторение до наступления события — Пока.

Сравнение вариантов

Для

Подходит, когда нужен индекс элемента или обход в обратном порядке (например, для безопасного удаления строк). Требует аккуратности с границами счётчика.

Для Каждого

Оптимален для чтения табличных частей, массивов и таблиц значений. Не подходит, если внутри цикла меняется состав той же коллекции.

Пока

Стандарт для обхода выборок запросов и задач с заранее неизвестным числом повторений. Требует гарантированного изменения условия в теле цикла.

Производительность: чего не делать внутри цикла

Самая дорогая ошибка — запрос к базе данных внутри цикла. Если в теле цикла на каждой итерации выполняется запрос, обращение к реквизиту через точку от ссылки (что тоже порождает неявное обращение к БД) или поиск документа по номеру, время выполнения растёт пропорционально числу итераций. На тысяче строк это уже заметная пауза для пользователя.

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

Если обработка большого объёма данных занимает больше нескольких секунд, выводите индикатор через СтрШаблон и состояние формы — пользователь должен видеть, что программа работает, а не зависла. Для очень длительных операций рассмотрите выполнение в фоновом задании.
ПЗ
Практическое замечание

Как проверить, что цикл работает правильно

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

Используйте отладчик конфигуратора: поставьте точку останова внутри тела цикла и проследите значения переменной цикла и условия на первых итерациях. Это быстрее и надёжнее, чем расстановка Сообщить() по коду.

Контрольные точки

Как проверить результат

Пустая коллекция
Норма

Цикл не выполнился ни разу, код после цикла отработал без ошибок

Тревожный признак

Ошибка обращения по индексу или обращение к неинициализированной переменной результата

Завершение цикла Пока
Норма

Число итераций конечно и соответствует объёму данных

Тревожный признак

Сеанс зависает, нагрузка на сервер растёт — условие не меняется в теле цикла

Обработанные данные
Норма

Обработаны все элементы ровно по одному разу

Тревожный признак

Часть строк пропущена или обработана дважды — признак изменения коллекции внутри цикла

Частые вопросы о циклах в 1С

Можно ли прервать сразу два вложенных цикла?

Оператор Прервать завершает только текущий цикл. Чтобы выйти из вложенной конструкции целиком, заведите переменную-флаг, установите её перед Прервать во внутреннем цикле и проверьте во внешнем. Альтернатива — вынести логику в функцию и использовать Возврат, который завершит выполнение сразу.

Почему обход выборки запроса делают через Пока, а не Для Каждого?

Выборка из запроса — это не коллекция в памяти, а курсор, движущийся по данным. Метод Следующий() возвращает Истина, пока есть необработанные записи, поэтому конструкция Пока Выборка.Следующий() Цикл — естественный способ обхода. Если выгрузить результат запроса в таблицу значений методом Выгрузить(), тогда станет доступен и Для Каждого.

Как безопасно удалить часть строк табличной части?

Надёжнее всего обходить коллекцию циклом Для с конца к началу (от Количество()-1 до 0 с шагом -1 через конструкцию с индексом или через массив индексов) — тогда удаление не сдвигает ещё не обработанные элементы. Второй вариант: сначала собрать удаляемые строки в массив, затем удалить их отдельным циклом по этому массиву.

Что делать, если сеанс завис из-за бесконечного цикла?

На файловой базе завершите процесс через диспетчер задач. На клиент-серверной — администратор может принудительно завершить сеанс в консоли кластера. После восстановления работы найдите в коде цикл Пока, условие которого не изменяется в теле, и добавьте изменение состояния или защитный счётчик максимального числа итераций.

Есть ли в 1С цикл с постусловием (сначала выполнить, потом проверить)?

Отдельной конструкции вида «повторять... пока» во встроенном языке нет. Если тело должно выполниться минимум один раз, используйте цикл Пока с предварительной установкой условия в Истина либо конструкцию с Прервать в конце тела по нужному условию.

Какой цикл быстрее — Для или Для Каждого?

Для типовых прикладных задач разница в скорости несущественна, выбирайте по удобству и безопасности кода. Реальное влияние на производительность оказывает не вид цикла, а то, что происходит внутри: обращения к базе данных, создание объектов, вложенные циклы по большим коллекциям.

Итог

Что важно запомнить

В 1С есть три цикла: Для (по счётчику), Для Каждого (по коллекции) и Пока (по условию). Для обхода табличных частей используйте Для Каждого, для выборок запросов — Пока. Управляйте выполнением операторами Прервать и Продолжить, не меняйте коллекцию во время её обхода и не выполняйте запросы к базе внутри цикла.