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

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

Как в 1С выйти из цикла

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

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

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

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

Оператор Прервать — основной способ выйти из цикла

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

Классический пример — поиск строки в табличной части документа по значению реквизита:

НайденнаяСтрока = Неопределено;

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

Если СтрокаТовара.Номенклатура = ИскомаяНоменклатура Тогда

НайденнаяСтрока = СтрокаТовара;

Прервать;

КонецЕсли;

КонецЦикла;

Если НайденнаяСтрока = Неопределено Тогда

Сообщить("Товар в табличной части не найден");

КонецЕсли;

Прерывать цикл имеет смысл только по условию — оператор почти всегда стоит внутри конструкции Если ... Тогда. Безусловный Прервать на первой строке тела цикла делает цикл бессмысленным: он выполнит одну итерацию и завершится.

Оператор Продолжить — пропуск итерации без выхода

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

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

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

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

КонецЕсли;

// обработка только строк с количеством

ПересчитатьСумму(СтрокаТовара);

КонецЦикла;

Использование Продолжить вместо глубокой вложенности Если делает код плоским и читаемым: условия-фильтры выносятся в начало итерации, а основная логика не утопает в отступах. Такой стиль называют «ранним выходом», и он рекомендован стандартами разработки.

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

Оператор Возврат — выход из цикла вместе с процедурой

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

Функция НайтиСтрокуПоНоменклатуре(Товары, Номенклатура)

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

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

Возврат СтрокаТовара;

КонецЕсли;

КонецЦикла;

Возврат Неопределено;

КонецФункции

Это предпочтительный приём для функций поиска: не нужна промежуточная переменная, не нужен Прервать, а код после цикла выполняется только когда ничего не найдено. Важно лишь помнить, что Возврат «сносит» всё — если после цикла должна выполняться завершающая логика (запись, закрытие ресурсов, установка признаков), использовать его нельзя, иначе этот код никогда не выполнится.

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

Прервать

Завершает ближайший цикл, код после цикла выполняется. Подходит для поиска и досрочного завершения перебора.

Продолжить

Пропускает текущую итерацию, цикл продолжается. Подходит для фильтрации элементов коллекции.

Возврат

Завершает всю процедуру или функцию. Подходит, когда после цикла ничего выполняться не должно.

Выход из вложенных циклов

Во вложенных конструкциях Прервать завершает только внутренний цикл — внешний продолжит перебор. Встроенный язык 1С не поддерживает меток и конструкций вида «прервать два уровня», поэтому для выхода сразу из нескольких циклов применяют обходные приёмы.

Приём с флагом

Самый распространённый способ — ввести переменную-флаг, которую проверяет внешний цикл:

НужноПрервать = Ложь;

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

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

Если СтрокаТовара.Номенклатура = Искомая Тогда

НужноПрервать = Истина;

Прервать; // прерываем внутренний цикл

КонецЕсли;

КонецЦикла;

Если НужноПрервать Тогда

Прервать; // прерываем внешний цикл

КонецЕсли;

КонецЦикла;

Выделение в функцию

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

Маршрут решения

Как выбрать действие

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

Прерывание цикла Пока и защита от бесконечных циклов

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

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

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

Если ПревышенЛимитОбработки(Выборка) Тогда

Прервать;

КонецЕсли;

ОбработатьСтроку(Выборка);

КонецЦикла;

Главная опасность цикла Пока — бесконечное выполнение, если условие никогда не станет ложным либо Прервать недостижим. Зависший цикл на клиенте «подвешивает» интерфейс пользователя, а на сервере — занимает рабочий процесс и может привести к превышению допустимой длительности вызова.

Надёжная практика — страховочный счётчик, когда число итераций заранее неизвестно:

Счетчик = 0;

Пока ЕстьНеобработанныеДанные() Цикл

Счетчик = Счетчик + 1;

Если Счетчик > 100000 Тогда

Прервать; // аварийный выход

КонецЕсли;

ОбработатьПорцию();

КонецЦикла;

Типичные ошибки при выходе из цикла

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

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

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

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

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

Поведение после нахождения элемента
Норма

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

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

Цикл продолжает перебирать оставшиеся элементы

Вложенные циклы
Норма

Прерваны все уровни, которые нужно прервать

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

Внешний цикл продолжает работу после Прервать во внутреннем

Код после цикла
Норма

Завершающие действия выполняются всегда

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

После Возврат часть логики недостижима

Цикл Пока
Норма

Условие гарантированно становится ложным или есть аварийный Прервать

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

Цикл не завершается, сеанс зависает

FAQ

Чем Прервать отличается от Продолжить?

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

Как выйти сразу из двух вложенных циклов?

Встроенного оператора «прервать два уровня» в 1С нет. Используйте переменную-флаг: внутренний цикл устанавливает её и прерывается, внешний проверяет флаг и тоже прерывается. Более чистый вариант — вынести перебор в функцию и выйти оператором Возврат, который завершит оба цикла.

Можно ли прервать цикл Для Каждого по выборке из запроса?

Да, оператор Прервать работает с любыми перебираемыми коллекциями, включая выборки результатов запроса, табличные части, таблицы значений и массивы. Ограничений по типу коллекции нет.

Что будет, если поставить Возврат внутри цикла в процедуре?

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

Как прервать цикл при обходе в обратном порядке?

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

Почему цикл Пока не завершается, хотя Прервать написан?

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

Итог

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

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