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