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

Три кита: виды циклов в 1С
В платформе 1С:Предприятие существует три конструкции для организации циклов. Каждая заточена под свой сценарий.
Цикл «Для» — когда знаем количество итераций
Классический счётный цикл. Используется, когда заранее известно, сколько раз нужно выполнить действие.
Для Счетчик = 1 По 10 Цикл
Сообщить("Итерация №" + Счетчик);
КонецЦикла;Важный нюанс: переменная-счётчик увеличивается автоматически на 1 после каждой итерации. В 1С нельзя задать произвольный шаг, как в некоторых других языках. Если нужен шаг, отличный от единицы, придётся хитрить:
Для Индекс = 0 По 9 Цикл
РеальныйШаг = Индекс * 3;
Сообщить("Значение: " + РеальныйШаг);
КонецЦикла;Типичный сценарий — обход массива по индексу:
МассивТоваров = Новый Массив;
МассивТоваров.Добавить("Ноутбук");
МассивТоваров.Добавить("Монитор");
МассивТоваров.Добавить("Клавиатура");
Для Инд = 0 По МассивТоваров.ВГраница() Цикл
Сообщить(МассивТоваров[Инд]);
КонецЦикла;Цикл «Для Каждого» — универсальный солдат
Самый популярный цикл в 1С. Работает с любой коллекцией: массивами, списками значений, табличными частями, результатами запросов, структурами и соответствиями.
Для Каждого Элемент Из МассивТоваров Цикл
Сообщить(Элемент);
КонецЦикла;Главное преимущество — вам не нужно думать об индексах, границах и количестве элементов. Вы просто работаете с каждым элементом коллекции.
Цикл «Пока» — когда условие выхода неизвестно заранее
Выполняется до тех пор, пока условие истинно. Идеален для ситуаций, когда количество итераций заранее неизвестно.
Остаток = 1000;
Месяц = 0;
Пока Остаток > 0 Цикл
Остаток = Остаток - 150;
Месяц = Месяц + 1;
КонецЦикла;
Сообщить("Средства закончатся через " + Месяц + " мес.");Будьте осторожны: если условие никогда не станет ложным, вы получите бесконечный цикл, и платформа зависнет. Всегда предусматривайте аварийный выход:
Счетчик = 0;
Пока НеВыполненоУсловие И Счетчик < 10000 Цикл
// логика обработки
Счетчик = Счетчик + 1;
КонецЦикла;
Обработка табличных частей документов
Табличные части — одна из самых частых структур данных, с которой работает разработчик 1С. Разберём несколько практических задач.
Подсчёт суммы по табличной части
ИтогоСумма = 0;
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
ИтогоСумма = ИтогоСумма + СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецЦикла;
Сообщить("Общая сумма: " + ИтогоСумма);Удаление строк из табличной части
Вот тут начинается самое интересное. Классическая ошибка новичка — удалять строки в прямом цикле:
// ❌ ТАК ДЕЛАТЬ НЕЛЬЗЯ — пропустите строки!
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Если СтрокаТЧ.Количество = 0 Тогда
Документ.Товары.Удалить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;При удалении строки коллекция сдвигается, и следующий элемент «проскакивает» мимо. Правильный подход — обходить табличную часть в обратном порядке. Но стандартный цикл «Для» в 1С не поддерживает обратный отсчёт, поэтому используем «Пока»:
// ✅ Корректный обратный обход
Инд = Документ.Товары.Количество() - 1;
Пока Инд >= 0 Цикл
СтрокаТЧ = Документ.Товары[Инд];
Если СтрокаТЧ.Количество = 0 Тогда
Документ.Товары.Удалить(Инд);
КонецЕсли;
Инд = Инд - 1;
КонецЦикла;Поиск дубликатов в табличной части
Задача, которая встречается постоянно: найти и объединить одинаковые товары.
Инд = 0;
Пока Инд < Документ.Товары.Количество() Цикл
ТекСтрока = Документ.Товары[Инд];
Инд2 = Инд + 1;
Пока Инд2 < Документ.Товары.Количество() Цикл
СравнСтрока = Документ.Товары[Инд2];
Если ТекСтрока.Номенклатура = СравнСтрока.Номенклатура Тогда
ТекСтрока.Количество = ТекСтрока.Количество + СравнСтрока.Количество;
Документ.Товары.Удалить(Инд2);
Иначе
Инд2 = Инд2 + 1;
КонецЕсли;
КонецЦикла;
Инд = Инд + 1;
КонецЦикла;Обратите внимание: при удалении дубликата мы не увеличиваем Инд2, потому что на его место сдвинется следующий элемент.

Работа с выборками из запросов
Результат запроса в 1С — это не массив, а специальный объект, который обходится особым образом.
Базовый обход выборки
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Цена КАК Цена
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Цена > 0";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + ": " + Выборка.Цена + " руб.");
КонецЦикла;Метод Следующий() перемещает указатель на следующую запись и возвращает Истина, если запись существует. Когда записи заканчиваются, возвращается Ложь и цикл завершается.
Обход иерархической выборки
Для справочников с иерархией удобно использовать выборку с группировками:
Результат = Запрос.Выполнить();
ВыборкаГруппы = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаГруппы.Следующий() Цикл
Сообщить("== Группа: " + ВыборкаГруппы.Категория + " ==");
ВыборкаДетали = ВыборкаГруппы.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
Сообщить(" " + ВыборкаДетали.Наименование);
КонецЦикла;
КонецЦикла;Пакетные запросы с несколькими результатами
Когда запрос возвращает несколько таблиц, обрабатываем каждую:
МассивРезультатов = Запрос.ВыполнитьПакет();
Для Каждого РезультатЗапроса Из МассивРезультатов Цикл
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// обработка строки
КонецЦикла;
КонецЦикла;Обход структур и соответствий
Структуры и соответствия — это пары «ключ-значение». Их обходят через Для Каждого:
Параметры = Новый Структура;
Параметры.Вставить("Организация", "ООО Ромашка");
Параметры.Вставить("Период", ТекущаяДата());
Параметры.Вставить("Склад", "Основной");
Для Каждого КлючЗначение Из Параметры Цикл
Сообщить(КлючЗначение.Ключ + " = " + КлючЗначение.Значение);
КонецЦикла;Для соответствий синтаксис аналогичен, но соответствие допускает ключи любого типа — не только строки.
Управление циклом: Прервать и Продолжить
Два оператора позволяют гибко управлять ходом цикла.
Прервать — немедленно выходит из цикла:
Для Каждого Товар Из Каталог Цикл
Если Товар.Наименование = "Искомый товар" Тогда
НайденныйТовар = Товар;
Прервать;
КонецЕсли;
КонецЦикла;Продолжить — пропускает оставшийся код итерации и переходит к следующей:
Для Каждого Контрагент Из СписокКонтрагентов Цикл
Если Контрагент.ЭтоГруппа Тогда
Продолжить; // группы пропускаем
КонецЕсли;
// обработка только элементов
ОбработатьКонтрагента(Контрагент);
КонецЦикла;Практические советы по производительности
Есть несколько правил, которые помогут писать быстрые и надёжные циклы в 1С.
Не обращайтесь к базе внутри цикла. Каждый вызов к базе данных — это сетевой запрос. Если у вас 10 000 строк, вы сделаете 10 000 обращений к серверу. Вместо этого получите все нужные данные одним запросом до цикла:
// ❌ Медленно: запрос внутри цикла
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
Остаток = РегистрыНакопления.ОстаткиТоваров
.ПолучитьПоследнийСрез(, "Номенклатура = &Ном");
КонецЦикла;
// ✅ Быстро: один запрос, потом цикл
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура, Остаток ИЗ ...";
ТаблицаОстатков = Запрос.Выполнить().Выгрузить();
Для Каждого СтрокаТЧ Из Документ.Товары Цикл
НайденнаяСтрока = ТаблицаОстатков.Найти(
СтрокаТЧ.Номенклатура, "Номенклатура");
Если НайденнаяСтрока <> Неопределено Тогда
Остаток = НайденнаяСтрока.Остаток;
КонецЕсли;
КонецЦикла;Используйте ТаблицаЗначений.НайтиСтроки() вместо вложенных циклов. Вместо перебора вложенным циклом используйте встроенные методы поиска — они работают значительно быстрее:
// ❌ Вложенный цикл O(n²)
Для Каждого Строка1 Из Таблица1 Цикл
Для Каждого Строка2 Из Таблица2 Цикл
Если Строка1.Ключ = Строка2.Ключ Тогда
// ...
КонецЕсли;
КонецЦикла;
КонецЦикла;
// ✅ Поиск через НайтиСтроки O(n)
Для Каждого Строка1 Из Таблица1 Цикл
Отбор = Новый Структура("Ключ", Строка1.Ключ);
НайденныеСтроки = Таблица2.НайтиСтроки(Отбор);
Для Каждого НайдСтрока Из НайденныеСтроки Цикл
// ...
КонецЦикла;
КонецЦикла;Для больших объёмов данных используйте индексирование через Соответствие:
Индекс = Новый Соответствие;
Для Каждого Строка Из Таблица2 Цикл
Индекс.Вставить(Строка.Ключ, Строка);
КонецЦикла;
Для Каждого Строка1 Из Таблица1 Цикл
НайденнаяСтрока = Индекс.Получить(Строка1.Ключ);
Если НайденнаяСтрока <> Неопределено Тогда
// работаем с найденной строкой
КонецЕсли;
КонецЦикла;Этот приём превращает O(n²) во O(n) и критически важен при обработке тысяч строк.
Шпаргалка: какой цикл выбрать?
Задача | Цикл | Почему |
|---|---|---|
Обход массива с индексом | Для … По | Нужен доступ по индексу |
Обход табличной части | Для Каждого | Самый читаемый вариант |
Удаление строк из коллекции | Пока (обратный обход) | Избегаем пропуска элементов |
Выборка результата запроса | Пока Выборка.Следующий() | Единственный способ обхода |
Повторение до условия | Пока | Количество итераций неизвестно |
Обход структуры/соответствия | Для Каждого | Получаем пары ключ-значение |
Заключение
Циклы в 1С — инструмент, который вы будете использовать в каждой обработке, каждом отчёте и каждом модуле. Запомните три главных правила: не лезьте в базу внутри цикла, удаляйте элементы в обратном порядке и используйте Соответствие для быстрого поиска. Эти три приёма отличают начинающего разработчика 1С от опытного.
Если вы только начинаете путь в программировании или хотите освоить новые технологии — загляните в приложение Кодик. Там вы найдёте структурированные курсы по Python, JavaScript, HTML, CSS и другим языкам, которые помогут разобраться в основах и перейти к реальным задачам. А в нашем Telegram-канале всегда можно задать вопрос, получить поддержку от сообщества из более чем 2000 разработчиков и быть в курсе новых материалов. Программирование — это проще, чем кажется, когда рядом есть те, кто готов помочь.
