Что умеет каждый оператор встроенного языка 1С:Предприятия 8.3
Содержание
Операторы в языке 1С делятся на две группы. Первая — знаки операций внутри выражений: + - * / %, сравнения = <> < > <= >= и логические И, ИЛИ, НЕ. Вторая — управляющие конструкции: Если, Для, Пока, Попытка, Возврат, Прервать, Продолжить и другие. Функции и примеры использования каждого — ниже, с кодом, который можно вставить в обработку и проверить.
Частое заблуждение новичков — искать в 1С привычные по другим языкам +=, ++ или switch. Их нет. Присваивание в 1С всегда полное (Сумма = Сумма + 1), а выбор из нескольких вариантов пишется через ИначеЕсли. Всё, что описано здесь, общее для платформы 8.3 и не зависит от конфигурации: код одинаково работает в Бухгалтерии, ЗУП, УТ и в самописной базе.
Арифметические, логические операторы и операции сравнения в 1С
Арифметика
| Оператор | Что делает | Пример | Результат |
|---|---|---|---|
+ | сложение, склейка строк, сдвиг даты | 10 + 5 | 15 |
- | вычитание, разница дат | 10 - 5 | 5 |
* | умножение | 4 * 2.5 | 10 |
/ | деление | 7 / 2 | 3.5 |
% | остаток от деления | 7 % 2 | 1 |
унарный - | смена знака | -Сумма | — |
Деление в 1С всегда дробное: 7 / 2 даёт 3.5, а не 3. Целую часть берут функцией Цел(7 / 2), округление — Окр(Число, 2).
Оператор + ведёт себя по-разному в зависимости от типа левого операнда:
- 🔢
5 + "3"→ 8: строка приводится к числу; - 🔤
"5" + 3→"53": число приводится к строке; - 📅
Дата + 86400→ та же дата через сутки: к дате прибавляются секунды; - ⏱
Дата2 - Дата1→ число секунд между датами.
ДатаНачала = '20260101';
ДатаКонца = '20260115';
Дней = (ДатаКонца - ДатаНачала) / 86400; // 14
СрокОплаты = ТекущаяДатаСеанса() + 10 * 86400; // через 10 дней
При склейке строки с числом платформа форматирует число с разделителем групп: "Сумма: " + 1500 выдаст Сумма: 1 500 с неразрывным пробелом. Для имён файлов, кодов и обменов используйте Формат(Сумма, "ЧГ=0") или СтрШаблон("Сумма: %1", Формат(Сумма, "ЧГ=0")).
Сравнение
= — равно, <> — не равно, <, >, <=, >= — больше и меньше. Результат всегда Истина или Ложь.
Значения разных типов на равенство сравнивать можно: 1 = "1" вернёт Ложь, ошибки не будет. А вот < и > между числом и строкой вызовут ошибку выполнения. Ссылки на объекты сравнивают только на = и <>.
Логические операторы
- ✅
И— истина, если истинны оба операнда; - 🔀
ИЛИ— истина, если истинен хотя бы один; - 🚫
НЕ— отрицание.
Логические выражения в 1С вычисляются по сокращённой схеме. Если левая часть И ложна, правая не вычисляется. На этом построена привычная защита от ошибки:
Если ЗначениеЗаполнено(Договор) И Договор.ВидДоговора = Перечисления.ВидыДоговоровКонтрагентов.СПоставщиком Тогда
// обращения к реквизиту пустой ссылки не будет
КонецЕсли;
Если поменять условия местами, при пустом договоре код всё равно отработает, но лишний раз прочитает данные. На объектах вроде Неопределено перестановка ведёт уже к ошибке «Поле объекта не обнаружено».
Приоритет операций: в каком порядке считает платформа
Платформа выполняет операции по старшинству, а внутри одного уровня — слева направо.
| Уровень | Операции |
|---|---|
| 1 (выше всех) | скобки ( ) |
| 2 | унарный минус |
| 3 | *, /, % |
| 4 | +, - |
| 5 | сравнения =, <>, <, >, <=, >= |
| 6 | НЕ |
| 7 | И |
| 8 (ниже всех) | ИЛИ |
Пример, на котором ошибаются чаще всего:
// Хотели: (оптовый ИЛИ VIP) И сумма больше 10 000
Если ЭтоОпт ИЛИ ЭтоVIP И Сумма > 10000 Тогда
Здесь И сильнее ИЛИ, поэтому условие читается как ЭтоОпт ИЛИ (ЭтоVIP И Сумма > 10000). Оптовый клиент получит скидку даже на заказ в 500 рублей.
Ставьте скобки всегда, когда в одном условии смешаны И и ИЛИ. Код станет длиннее на два символа, а читать его будет проще любому, кто откроет модуль после вас.
Операторы присваивания и работа с переменными
Знак = в 1С означает и присваивание, и сравнение. Смысл определяет место: в начале оператора — присваивание, внутри выражения — сравнение.
Итого = Цена * Количество; // присваивание
Флаг = (Итого = 0); // справа сравнение, результат Булево
Объявление переменных
- 📌 Внутри процедуры переменная появляется при первом присваивании, объявлять её не обязательно.
- 📌
Перем Имя;объявляет переменную явно. До присваивания её значение —Неопределено. - 📌 Переменные модуля объявляют
Перемв начале модуля. С ключевым словомЭкспортпеременная модуля объекта или формы доступна снаружи.
Перем КэшНастроек Экспорт; // в модуле объекта
Процедура ПересчитатьСумму()
Перем Результат;
Результат = 0;
Для Каждого Строка Из Товары Цикл
Результат = Результат + Строка.Сумма;
КонецЦикла;
СуммаДокумента = Результат;
КонецПроцедуры
Другие операторы, связанные со значениями
- 🆕
Новый— создаёт объект:Новый ТаблицаЗначений,Новый Структура("Код, Имя"),Новый Массив. - ↩️
Возврат— выход из процедуры или возврат значения из функции:Возврат Итого;. - 🏷
Перейти ~Метка;— безусловный переход. В языке он есть, но в рабочем коде почти не нужен: его заменяютПрервать,ПродолжитьиВозврат.
Константы-литералы: строки в двойных кавычках ("Текст", кавычка внутри удваивается: "Ответ ""ок"""), даты в одинарных ('20261007'), булево — Истина и Ложь, пустые значения — Неопределено и Null.
Условные операторы 1С: Если и ?()
Полная конструкция
Если Остаток < 0 Тогда
Сообщить("Отрицательный остаток");
ИначеЕсли Остаток = 0 Тогда
Сообщить("Товар закончился");
Иначе
Сообщить("В наличии: " + Формат(Остаток, "ЧГ=0"));
КонецЕсли;
- Веток
ИначеЕслиможет быть сколько угодно, веткаИначенеобязательна. - Платформа проверяет условия сверху вниз и выполняет первую подходящую ветку. Остальные пропускает.
- После
КонецЕслиставится точка с запятой.
Аналога switch/case нет. Цепочка ИначеЕсли и есть способ выбрать один вариант из многих. Если вариантов десятки, удобнее заполнить Соответствие и брать значение по ключу.
Тернарный оператор
Короткая форма для выражений: ?(Условие, ЕслиИстина, ЕслиЛожь).
Ставка = ?(ЭтоНерезидент, 30, 13);
Представление = ?(ПустаяСтрока(Комментарий), "без комментария", Комментарий);
Тернарный оператор возвращает значение, его нельзя использовать как отдельный оператор. Вложенные ?(…, ?(…)) формально допустимы, но после второго уровня их проще переписать на Если.
Лишние сравнения с Истиной
Если Проведен = Истина Тогда работает, но избыточно. Пишут Если Проведен Тогда и Если НЕ Проведен Тогда.
Операторы циклов в 1С и управление итерациями
В языке три вида циклов.
| Цикл | Когда применять | Синтаксис |
|---|---|---|
Для … По | известно число повторов | Для Сч = 1 По 10 Цикл … КонецЦикла; |
Для Каждого … Из | обход коллекции | Для Каждого Стр Из Товары Цикл … КонецЦикла; |
Пока | повторять, пока верно условие | Пока Выборка.Следующий() Цикл … КонецЦикла; |
Цикл со счётчиком
Шаг у Для … По всегда равен 1, ключевого слова для шага нет. Нужен шаг 2 или обратный порядок — используйте Пока или пересчитывайте индекс.
Обход коллекции
Для Каждого обходит массивы, таблицы и деревья значений, табличные части, структуры и соответствия. Выборку из результата запроса так не обойти: для неё нужен Пока Выборка.Следующий() Цикл.
Прервать и Продолжить
- ⛔
Прервать— немедленный выход из цикла. - ⏭
Продолжить— переход к следующей итерации.
Для Каждого Строка Из Товары Цикл
Если Строка.Количество = 0 Тогда
Продолжить; // пустые строки пропускаем
КонецЕсли;
Если Строка.Номенклатура = НайденнаяПозиция Тогда
НомерСтроки = Строка.НомерСтроки;
Прервать; // нашли — дальше искать незачем
КонецЕсли;
КонецЦикла;
Удаление элементов в цикле
Удалять строки внутри Для Каждого нельзя: после удаления сдвигаются индексы и часть строк пропускается. Обходите коллекцию с конца:
Всего = Товары.Количество();
Для Сч = 1 По Всего Цикл
Строка = Товары[Всего - Сч];
Если Строка.Количество = 0 Тогда
Товары.Удалить(Строка);
КонецЕсли;
КонецЦикла;
Граница Всего посчитана до цикла, поэтому удаление на неё не влияет. Индексы идут от Всего - 1 до 0, то есть строки обходятся от последней к первой.
Цикл Пока без изменения условия внутри тела — бесконечный. В тонком клиенте это выглядит как зависшая форма. Прервать выполнение можно сочетанием Ctrl+Break, но несохранённые данные формы при этом могут потеряться.
Обработка исключений: Попытка, Исключение, ВызватьИсключение
Конструкция ловит ошибки выполнения: деление на ноль, обращение к несуществующему полю, сбой записи, недоступный файл.
Попытка
Файл = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);
Текст = Файл.Прочитать();
Файл.Закрыть();
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Загрузка прайса",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(Инфо));
Сообщить("Не удалось прочитать файл: " + КраткоеПредставлениеОшибки(Инфо));
КонецПопытки;
Что здесь происходит:
- Код между
ПопыткаиИсключениевыполняется как обычно. - При первой же ошибке управление переходит в блок
Исключение, остаток блокаПопыткапропускается. ИнформацияОбОшибке()возвращает объект с описанием ошибки, модулем и номером строки.ПодробноеПредставлениеОшибки()даёт полный текст со стеком — его пишут в журнал регистрации.КраткоеПредставлениеОшибки()— короткий текст для пользователя.
Свои ошибки и повторный выброс
ВызватьИсключение "Не заполнен склад";— прерывает выполнение с вашим текстом. Если выше по стеку нетПопытки, пользователь увидит окно с этим сообщением.ВызватьИсключение;без параметров допустим только внутри блокаИсключение. Он пробрасывает исходную ошибку дальше, сохраняя её текст.
Пустой блок Исключение … КонецПопытки — худшее, что можно сделать с ошибкой. Сбой исчезает без следа, а через месяц бухгалтер находит недопроведённые документы и никто не понимает почему. Минимум — запись в журнал регистрации.
Не оборачивайте в Попытку то, что можно проверить заранее. Вместо ловли деления на ноль проверьте делитель: Если Количество <> 0 Тогда. Попытка нужна для внешних операций: файлы, COM, HTTP, запись объектов.
Операторы работы с транзакциями и блокировками
Строго говоря, транзакции в 1С управляются не операторами, а методами глобального контекста. Но пишутся они рядом с Попыткой и в коде воспринимаются как одна конструкция.
| Метод | Назначение |
|---|---|
НачатьТранзакцию() | открывает транзакцию |
ЗафиксироватьТранзакцию() | записывает все изменения разом |
ОтменитьТранзакцию() | откатывает все изменения |
ТранзакцияАктивна() | возвращает Истина, если транзакция открыта |
Шаблон, принятый в типовых конфигурациях:
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
Блокировка.Заблокировать();
// чтение остатков и запись документов
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Перемещение товаров",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
Правила, которые стоит держать в голове:
- 🔒
НачатьТранзакцию()ставится доПопытки. Если транзакция не открылась, откатывать нечего. - 🔁 Вложенных транзакций в полном смысле нет. Внутренний
НачатьТранзакцию()лишь увеличивает счётчик, аОтменитьТранзакцию()на любом уровне откатывает всё. - 🧱 После ошибки внутри транзакции её уже нельзя продолжать. Попытка записать что-то ещё даст ошибку «В данной транзакции уже происходили ошибки». Поэтому
Попыткавнутри транзакции, которая «гасит» ошибку и идёт дальше, не спасает. - 📦
Записать()у объекта сам открывает транзакцию, если её нет. Явная транзакция нужна, когда несколько записей должны пройти вместе или не пройти вовсе. - 🔐 Управляемая блокировка
БлокировкаДанныхдействует только внутри транзакции и снимается при её завершении.
Не держите транзакцию открытой во время диалога с пользователем или долгого HTTP-запроса. Пока она активна, заблокированные данные недоступны другим сеансам, и коллеги получат ошибки блокировки при проведении.
Частые ошибки при работе с операторами
- ❌ Проверка
Если Сумма = НеопределеновместоЗначениеЗаполнено(Сумма). Пустое число — это 0, а неНеопределено, и условие не сработает. - ❌ Арифметика с
Null. Результат запроса с левым соединением даётNullв пустых полях, иNull + 100падает с ошибкой. Обрабатывайте в самом запросе черезЕСТЬNULL(Поле, 0). - ❌ Сравнение дробей на точное равенство. После деления
Сумма / 3 * 3может не совпасть с исходной суммой в последнем знаке. Сравнивайте округлённые значения:Окр(А, 2) = Окр(Б, 2). - ❌ Изменение переменной цикла внутри
Для. Присвоение счётчику внутри тела ломает логику и читается как ошибка. Если нужно управлять шагом — пишитеПока. - ❌ Перепутанные
ПрерватьиВозврат.Прерватьвыходит только из ближайшего цикла, код послеКонецЦиклавыполнится. Чтобы выйти из процедуры целиком, нуженВозврат.
Частые вопросы об операторах 1С
Есть ли в 1С английские названия операторов?
If … Then … ElsIf … Else … EndIf, For Each … In … Do … EndDo, While, Try … Except … EndTry, Raise, AND, OR, NOT. В одном модуле их можно смешивать, но в типовых конфигурациях пишут по-русски.Чем операторы языка запросов отличаются от встроенного языка?
ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ вместо Если, ЕСТЬ NULL, В, ПОДОБНО, МЕЖДУ. Циклов, Если и Попытки в запросах нет.Можно ли выполнить код, собранный в строку?
Выполнить(Строка) выполняет фрагмент кода, а функция Вычислить(Строка) возвращает значение выражения. Пользуйтесь ими осторожно: ошибка в строке видна только во время выполнения, а код из внешних данных — дыра в безопасности.Что такое Асинх и Ждать?
Асинх помечает процедуру или функцию, а Ждать приостанавливает её до получения результата, например ответа на вопрос пользователю. Они заменяют цепочки ОписаниеОповещения в клиентском коде.Нужна ли точка с запятой после каждого оператора?
КонецЕсли, КонецЦикла и КонецПопытки её у последнего оператора можно опустить, но лучше ставить всегда, чтобы при добавлении строки не получить синтаксическую ошибку.