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

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

Как пропустить строку в цикле 1С

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

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

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

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

Оператор Продолжить: синтаксис и принцип работы

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

Оператор почти всегда размещается внутри условия, иначе код после него окажется недостижимым. Типовой шаблон выглядит так:

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

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

Продолжить; // строка пропускается

КонецЕсли;

// обработка строки

КонецЦикла;

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

Пропуск строки в цикле Для Каждого

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

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

Если Не ЗначениеЗаполнено(СтрокаТЧ.Номенклатура) Тогда

Продолжить;

КонецЕсли;

Если СтрокаТЧ.Сумма = 0 Тогда

Продолжить;

КонецЕсли;

ОбщаяСумма = ОбщаяСумма + СтрокаТЧ.Сумма;

КонецЦикла;

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

Пропуск итерации в циклах Для и Пока

Цикл со счётчиком Для

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

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

Строка = ТаблицаЗначений[Инд];

Если Строка.ПометкаУдаления Тогда

Продолжить;

КонецЕсли;

// обработка

КонецЦикла;

Цикл Пока

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

Альтернативы: когда Продолжить не нужен

Не каждая задача «пропустить строку» требует оператора Продолжить. В ряде случаев код получается чище и быстрее без него.

Первый вариант — отбор на уровне запроса. Если данные читаются запросом, условие ГДЕ Количество > 0 отсечёт ненужные строки ещё на сервере СУБД, и цикл будет обходить только нужные записи. Это особенно важно при больших объёмах: передача и обход лишних строк стоят заметного времени.

Второй вариант — вложенное условие вместо пропуска. Если «полезного» кода в цикле немного, конструкция Если Условие Тогда ... КонецЕсли читается проще, чем несколько Продолжить подряд. Оператор пропуска оправдан, когда проверок много и основной код длинный: он позволяет не наращивать вложенность.

Третий вариант — методы коллекций. Для таблицы значений можно сначала получить подмножество через НайтиСтроки(Отбор) или скопировать нужные строки через Выгрузить() с отбором, а затем обходить уже отфильтрованный результат без каких-либо условий в цикле.

Способы пропустить строки

Оператор Продолжить

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

Отбор в запросе (ГДЕ)

Самый быстрый при больших объёмах, фильтрация на стороне СУБД. Ограничение: применимо только к данным, получаемым запросом.

НайтиСтроки / Выгрузить с отбором

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

Условие внутри тела цикла

Прозрачно при одной-двух проверках и коротком коде. Ограничение: при множестве условий растёт вложенность и код хуже читается.

Пропуск итерации внешнего цикла из вложенного

Типичная задача: во вложенном цикле обнаружено условие, по которому нужно пропустить не внутреннюю, а внешнюю итерацию. Прямого средства для этого в 1С нет, поэтому применяется флаговая переменная.

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

ПропуститьЗаказ = Ложь;

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

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

ПропуститьЗаказ = Истина;

Прервать; // выходим из внутреннего цикла

КонецЕсли;

КонецЦикла;

Если ПропуститьЗаказ Тогда

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

КонецЕсли;

// обработка заказа

КонецЦикла;

Альтернативный приём — вынести внутреннюю проверку в отдельную функцию, возвращающую булево. Тогда внешний цикл остаётся плоским: Если Не ЗаказДоступен(СтрокаЗаказа) Тогда Продолжить; КонецЕсли;. Такой код проще тестировать и сопровождать.

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

Типичные ошибки при пропуске строк

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

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

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

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

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

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

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

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

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

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

Количество обработанных строк
Норма

Равно общему числу строк минус строки, попадающие под условие пропуска

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

Обработано меньше или больше — условие сформулировано неверно

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

Цикл завершается за конечное число итераций

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

Сеанс зависает — сдвиг указателя стоит после Продолжить

Итоговые суммы и остатки
Норма

Сходятся с расчётом по отфильтрованным вручную данным

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

Расхождения — пропускаются или обрабатываются лишние строки

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

Итог

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

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

Частые вопросы

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

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

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

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

Как пропустить итерацию внешнего цикла из вложенного?

Специального оператора нет. Заведите флаговую переменную: во внутреннем цикле установите её и выполните Прервать, а во внешнем цикле после внутреннего проверьте флаг и выполните Продолжить. Альтернатива — вынести внутреннюю проверку в функцию, возвращающую Истина или Ложь.

Почему цикл Пока зависает после добавления Продолжить?

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

Что быстрее: пропуск строк в цикле или отбор в запросе?

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

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

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