Разработка и Конфигурация · 8 мин
Как начать цикл заново в 1С
Как начать итерацию цикла заново в 1С: операторы Продолжить и Прервать, циклы Для и Пока, типичные ошибки, примеры кода и проверка результата.
Во встроенном языке 1С нет отдельной команды «начать цикл заново» вроде restart или continue to start, как в некоторых других языках. Вместо этого используются два управляющих оператора: Продолжить — досрочно завершает текущую итерацию и переходит к началу следующей, и Прервать — полностью выходит из цикла. Если нужно именно повторить текущую итерацию с нуля (например, при ошибке обработки элемента), применяют цикл Пока с ручным управлением счётчиком или оборачивают тело цикла в попытку с флагом повтора.
Выбор подхода зависит от задачи: пропустить «плохой» элемент и идти дальше, остановить обход при найденном результате или повторить операцию до успешного завершения. Ниже разобраны оба вида циклов, работа управляющих операторов, приёмы перезапуска итерации и типичные ошибки, которые приводят к бесконечным циклам и пропуску данных.
Какие циклы есть в 1С и чем они отличаются
Встроенный язык 1С поддерживает два вида циклов. Первый — Для ... Цикл ... КонецЦикла, который перебирает значения счётчика в заданном диапазоне или элементы коллекции через конструкцию Для Каждого Элемент Из Коллекция Цикл. Счётчик в таком цикле управляется автоматически, и вручную «откатить» его назад штатными средствами нельзя.
Второй вид — Пока Условие Цикл ... КонецЦикла. Здесь условие проверяется перед каждой итерацией, а все переменные, участвующие в условии, разработчик изменяет сам. Именно цикл Пока даёт полный контроль: можно не увеличивать счётчик, сбросить его или изменить условие так, чтобы итерация фактически началась заново.
Оператор Продолжить: переход к следующей итерации
Оператор Продолжить немедленно завершает текущую итерацию: весь код ниже него в теле цикла пропускается, и выполнение переходит к началу цикла — проверке условия или получению следующего элемента. Это основной способ «начать заново» шаг цикла, когда текущий элемент обрабатывать не нужно.
Для Каждого Строка Из ТаблицаДокументов Цикл
Если Строка.ПометкаУдаления Тогда
Продолжить; // пропускаем помеченные, идём к следующей строке
КонецЕсли;
ОбработатьСтроку(Строка);
КонецЦикла;
Важно понимать: Продолжить не повторяет текущий элемент, а переходит к следующему. Если в цикле Для со счётчиком вы вызвали Продолжить на пятом элементе, следующим будет шестой — пятый обработан не будет. Для повторной обработки того же элемента нужны другие приёмы, описанные ниже.
Оператор Прервать: полный выход из цикла
Оператор Прервать полностью прекращает выполнение цикла и передаёт управление на первый оператор после КонецЦикла. Типичный сценарий — поиск: как только нужный элемент найден, дальнейший перебор бессмысленен, и цикл прерывают ради экономии времени.
НайденныйДокумент = Неопределено;
Для Каждого Док Из СписокДокументов Цикл
Если Док.Номер = ИскомыйНомер Тогда
НайденныйДокумент = Док;
Прервать; // дальше искать не нужно
КонецЕсли;
КонецЦикла;
Частая потребность — прервать сразу два вложенных цикла. Штатного «прервать внешний цикл» в 1С нет, поэтому используют флаг: внутренний цикл устанавливает переменную НужноВыйти = Истина и прерывается, а внешний проверяет флаг и тоже выполняет Прервать.
Как повторить текущую итерацию заново
Если требуется именно повторить обработку того же элемента — например, при временной ошибке записи в базу или при обращении к внешнему сервису — цикл Для не подходит: его счётчик не откатить. Используйте цикл Пока с ручным управлением индексом.
Индекс = 0;
Пока Индекс < МассивЭлементов.Количество() Цикл
Элемент = МассивЭлементов[Индекс];
Попытка
ОбработатьЭлемент(Элемент);
Индекс = Индекс + 1; // успех — идём дальше
Исключение
// не увеличиваем индекс — итерация повторится с тем же элементом
Если ПревышеноЧислоПопыток() Тогда
Индекс = Индекс + 1; // сдаёмся и переходим дальше, чтобы не зависнуть
КонецЕсли;
КонецПопытки;
КонецЦикла;
Альтернатива — вложенный цикл попыток вокруг обработки одного элемента: внешний цикл перебирает коллекцию, внутренний Пока Не Успешно повторяет операцию. Внутри него после успеха ставится Прервать, а после исчерпания попыток — тоже Прервать с записью ошибки.
- 1Определите, что нужно: пропустить элемент (Продолжить), выйти (Прервать) или повторить тот же элемент
- 2Для повтора замените цикл Для на цикл Пока с ручным счётчиком
- 3Добавьте счётчик попыток и его лимит
- 4В блоке Исключение решайте: повторять или пропустить элемент
- 5Проверьте на тестовых данных, что цикл завершается и при успехе, и при постоянной ошибке
Типичные ошибки при управлении циклами
Самая распространённая ошибка — бесконечный цикл Пока, когда переменная условия не изменяется внутри тела или изменяется только в ветке успеха, а ошибка повторяется постоянно. Сеанс зависает, и завершить его можно только принудительно через консоль кластера или диспетчер задач.
Вторая группа ошибок связана с модификацией коллекции во время обхода. Удалять или добавлять элементы коллекции внутри цикла Для Каждого нельзя — это приводит к пропуску элементов или ошибке обхода. Если нужно удалять, обходите коллекцию с конца по индексу или соберите элементы для удаления в отдельный массив и удалите их после цикла.
Проверка результата и отладка
Чтобы убедиться, что цикл работает как задумано, используйте отладчик конфигуратора: поставьте точку останова на операторах Продолжить и Прервать и смотрите, на каком элементе они срабатывают. Для циклов с повторами полезно выводить в журнал регистрации или через Сообщить() номер итерации и номер попытки — так видно, что повтор действительно происходит и завершается.
Контрольный признак корректной работы: количество обработанных элементов плюс количество пропущенных равно размеру исходной коллекции. Если сумма меньше — часть данных потеряна, чаще всего из-за некорректного Продолжить или изменения коллекции внутри цикла.
Как проверить результат
Цикл заканчивается за предсказуемое время и при ошибках данных
Сеанс зависает, цикл не завершается
Обработано + пропущено = всего элементов
Часть элементов потеряна без записи в журнал
Повтор происходит ограниченное число раз, затем ошибка фиксируется
Элемент повторяется бесконечно
FAQ
Есть ли в 1С аналог goto для возврата к началу цикла?
Нет, оператора безусловного перехода во встроенном языке 1С нет. Возврат к началу организуется логически: оператором Продолжить для перехода к следующей итерации или циклом Пока с ручным управлением счётчиком для повторения текущей.
Как прервать сразу два вложенных цикла?
Заведите переменную-флаг, например ПрекратитьОбход. Во внутреннем цикле установите её в Истина и выполните Прервать. Во внешнем цикле сразу после внутреннего проверьте флаг и тоже выполните Прервать. Либо вынесите обход в функцию и используйте Возврат.
Можно ли использовать Продолжить внутри конструкции Попытка...Исключение?
Да, операторы Продолжить и Прервать допустимы внутри блоков Попытка и Исключение. Это удобный приём: в блоке Исключение можно залогировать ошибку и выполнить Продолжить, чтобы перейти к следующему элементу.
Почему цикл Для Каждого пропускает элементы при удалении?
Потому что коллекция изменяется во время обхода, и внутренний указатель смещается. Обходите коллекцию по индексу с конца к началу или сначала соберите удаляемые элементы в отдельный массив, а удаляйте их уже после завершения цикла.
Как ограничить время выполнения цикла с повторами?
Запомните время начала через ТекущаяДатаСеанса() и на каждой итерации проверяйте, не превышен ли лимит. При превышении записывайте состояние в журнал регистрации и прерывайте цикл, чтобы не блокировать сеанс пользователя или регламентное задание.
Что важно запомнить
Продолжить — переход к следующей итерации, Прервать — полный выход из цикла, повтор текущего элемента — только через цикл Пока с ручным счётчиком. Любой механизм повтора обязан иметь лимит попыток и запись ошибок, иначе цикл превратится в бесконечный.