Условия и циклы

Условия и циклы — это то, что превращает набор переменных в программу, которая принимает решения и повторяет действия.

Управляющая конструкция — оператор, который меняет порядок выполнения кода: либо выбирает одну из веток (условие), либо повторяет блок много раз (цикл). Без них программа выполнялась бы строго сверху вниз, один раз.

Практически любая обработка в 1С — это «пройти по строкам документа и для каждой что-то проверить». Значит, вам нужны две вещи: Если для проверок и цикл для перебора. Разберём обе конструкции с примерами из учётной практики.

Ветвление: Если ... Тогда

Базовая форма читается почти как русская фраза: «если условие, тогда сделать это, конец если».

Остаток = 5;
Если Остаток > 0 Тогда
    Сообщить("Товар в наличии");
КонецЕсли;

Ключевое слово КонецЕсли обязательно — оно закрывает конструкцию. Полная форма добавляет альтернативы через ИначеЕсли (сколько угодно раз) и финальную ветку Иначе.

Сумма = 15000;
Если Сумма >= 100000 Тогда
    Скидка = 10;
ИначеЕсли Сумма >= 50000 Тогда
    Скидка = 5;
ИначеЕсли Сумма >= 10000 Тогда
    Скидка = 2;
Иначе
    Скидка = 0;
КонецЕсли;
Сообщить("Скидка: " + Скидка + "%");

Результат:

Скидка: 2%

Проверки идут сверху вниз, выполняется первая подошедшая ветка, остальные пропускаются. Наш пример 15000 не дотянул до 50000, но прошёл порог 10000 — отсюда 2%.

Логические операторы И, ИЛИ, НЕ

Условия соединяются словами (не символами): И — оба должны быть истинны, ИЛИ — хотя бы одно, НЕ — отрицание. Никаких && или ||, как в других языках, здесь нет.

Оплачено = Истина;
Отгружено = Ложь;

Если Оплачено И НЕ Отгружено Тогда
    Сообщить("Заказ оплачен, но ещё не отгружен — пора собирать");
КонецЕсли;

Статус = "Новый";
Если Статус = "Новый" ИЛИ Статус = "ВРаботе" Тогда
    Сообщить("Заказ ещё активен");
КонецЕсли;

Операторы И / ИЛИ вычисляются «лениво»: в А И Б, если А оказалось Ложь, Б уже не проверяется (результат всё равно Ложь). Это удобно для защиты: сначала проверить, что объект существует, а потом обращаться к его свойствам.

Цикл Для ... Цикл (счётный)

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

Для Счётчик = 1 По 5 Цикл
    Сообщить("Итерация " + Счётчик);
КонецЦикла;

Результат:

Итерация 1
Итерация 2
Итерация 3
Итерация 4
Итерация 5

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

Цикл Для Каждого ... Из (перебор коллекции)

Самый частый цикл в 1С. Он перебирает элементы коллекции — строки таблицы, элементы массива, строки документа — без возни с индексами.

Товары = Новый Массив;
Товары.Добавить("Мышь");
Товары.Добавить("Клавиатура");
Товары.Добавить("Монитор");

Для Каждого Товар Из Товары Цикл
    Сообщить("Позиция: " + Товар);
КонецЦикла;

Результат:

Позиция: Мышь
Позиция: Клавиатура
Позиция: Монитор

Именно так обходят табличную часть документа: Для Каждого СтрокаТовары Из Документ.Товары Цикл — и внутри доступны СтрокаТовары.Количество, СтрокаТовары.Цена и так далее. Этот приём вы будете использовать чаще любого другого.

Цикл Пока ... Цикл (по условию)

Когда заранее неизвестно число повторений, а важно условие — берут Пока. Он крутится, пока условие истинно.

Остаток = 10;
Пока Остаток > 0 Цикл
    Сообщить("Осталось: " + Остаток);
    Остаток = Остаток - 3;
КонецЦикла;
Сообщить("Склад пуст");

Результат:

Осталось: 10
Осталось: 7
Осталось: 4
Осталось: 1
Склад пуст

Прервать и Продолжить

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

Числа = Новый Массив;
Числа.Добавить(4);
Числа.Добавить(-2);
Числа.Добавить(7);
Числа.Добавить(-9);

СуммаПоложительных = 0;
Для Каждого Значение Из Числа Цикл
    Если Значение < 0 Тогда
        Продолжить; // отрицательные пропускаем
    КонецЕсли;
    СуммаПоложительных = СуммаПоложительных + Значение;
КонецЦикла;
Сообщить("Сумма положительных: " + СуммаПоложительных);

Результат:

Сумма положительных: 11

Как это работает

Платформа выполняет модуль построчно. Дойдя до Если, она вычисляет логическое выражение в Булево и, если там Истина, входит в блок до КонецЕсли, иначе перескакивает к следующей ветке. Циклы устроены как «проверка + прыжок назад»: Пока перед каждой итерацией проверяет условие; счётный Для хранит скрытый счётчик и сам увеличивает его на 1; Для Каждого запрашивает у коллекции внутренний итератор и на каждом шаге берёт следующий элемент. Прервать — это прыжок за КонецЦикла, Продолжить — прыжок к проверке условия.

Частые ошибки

Забыли КонецЕсли или КонецЦикла. В отличие от языков с фигурными скобками, границы блоков в 1С — это ключевые слова. Пропустили закрывающее — получите синтаксическую ошибку компиляции. Пишите открывающее и закрывающее слово сразу, а тело набивайте между ними.

Бесконечный цикл Пока. Если внутри Пока забыть менять переменную условия (в примере выше — не уменьшать Остаток), цикл никогда не завершится и «подвесит» сеанс. Всегда убеждайтесь, что тело цикла приближает условие к Ложь.

Символы вместо слов в логике. Попытка написать Если а > 0 && б > 0 — ошибка: в 1С только И, ИЛИ, НЕ. Амперсанд в 1С — это префикс директив компиляции (&НаКлиенте), а не логический оператор.

Ждут, что «По N» остановится на N-1. В Для i = 1 По 5 верхняя граница включается: тело выполнится и для i = 5. Если нужно строго до 5, пишите По 4.

Итоги

  • Если ... Тогда ... ИначеЕсли ... Иначе ... КонецЕсли — ветвление; выполняется первая подошедшая ветка.
  • Логика — словами: И, ИЛИ, НЕ; вычисление ленивое.
  • Три цикла: Для ... По ... (счётный, граница включительна), Для Каждого ... Из ... (перебор коллекций — самый частый), Пока ... Цикл (по условию).
  • Прервать выходит из цикла, Продолжить переходит к следующей итерации.
  • Каждый блок закрывается своим словом: КонецЕсли, КонецЦикла.
Проверьте себя
1. Сколько раз выполнится тело цикла: Для i = 1 По 5 Цикл ... КонецЦикла; ?
A4 раза
B5 раз
C6 раз
DЗависит от значения i внутри
2. Какой оператор в 1С является логическим «И»?
A&&
BИ
CAND только по-английски
D&