Программирование на встроенном языке 1С 8.3: синтаксис, модули, запросы и отладка

· 9 мин

Содержание

Скрипты для 1С пишут на встроенном языке платформы 1С:Предприятие 8.3. Самый быстрый способ начать — создать внешнюю обработку в Конфигураторе (Файл → Новый → Внешняя обработка), добавить форму с кнопкой, написать код в модуле формы и открыть файл .epf в рабочей базе через Файл → Открыть. Конфигурацию при этом менять не нужно.

Язык похож на Паскаль и Бейсик, но с русскими ключевыми словами: Если, Цикл, Процедура. У каждого слова есть английский вариант (If, Do, Procedure), регистр букв значения не имеет. Главное отличие от «обычного» программирования — код всегда выполняется в конкретном месте: на клиенте или на сервере, и это определяет, что в нём можно делать.

С чего начать: где писать и как запустить первый код

Отдельного «окна для скриптов» в 1С нет. Код живёт в модулях объектов конфигурации или внешних обработок. Для учёбы и разовых задач есть три варианта.

ВариантКогда подходитЧто нужно
📄 Внешняя обработка .epfРазовые выборки, массовые правки, проверкиКонфигуратор и право открывать внешние обработки в базе
🧩 Расширение конфигурации .cfeПостоянные доработки типовой без снятия с поддержкиКонфигуратор, платформа 8.3.6 и новее
🛠 Правка основной конфигурацииСобственные разработки, нетиповые базыКонфигуратор, понимание последствий для обновлений

Пошагово первый скрипт во внешней обработке:

  1. Откройте базу в режиме Конфигуратора. Подойдёт и пустая учебная база.
  2. Выполните Файл → Новый → Внешняя обработка.
  3. В окне обработки на вкладке «Формы» добавьте форму. Конструктор предложит тип — оставьте форму обработки.
  4. В редакторе формы на вкладке «Команды» создайте команду Найти и перетащите её в дерево элементов: появится кнопка.
  5. В свойствах команды нажмите на лупу у поля «Действие» — платформа создаст обработчик в модуле формы.
  6. Сохраните обработку в файл, откройте рабочую базу в режиме 1С:Предприятие и выполните Файл → Открыть.

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

Для коллективной разработки и работы с Git фирма 1С выпускает среду 1C:Enterprise Development Tools (EDT). Для первых шагов она избыточна: Конфигуратора хватает.

Синтаксис встроенного языка и типы данных

Каждый оператор заканчивается точкой с запятой. Комментарий начинается с // и идёт до конца строки. Многострочного комментария нет — выделите строки и закомментируйте их разом командой из меню Текст → Блок.

Переменную объявлять заранее не обязательно: она появляется при первом присваивании. Тип у переменной не фиксирован, он определяется значением.

Основные примитивные типы:

  • 🔢 Число — 150, 12.5. Десятичный разделитель в коде всегда точка.
  • 🔤 Строка — "ООО Ромашка". Кавычку внутри строки удваивают: "Счёт ""Основной""".
  • 📅 Дата — литерал в одинарных кавычках: '20260101' или '20260101120000' со временем.
  • ✅ Булево — Истина и Ложь.
  • ⭕ Неопределено и Null — «пустое значение». Null приходит из запросов, когда в соединении нет данных.

Универсальные коллекции встречаются почти в каждом скрипте:

Массив = Новый Массив;
Массив.Добавить("Москва");
Массив.Добавить("Казань");

Параметры = Новый Структура("Организация, Период");
Параметры.Период = ТекущаяДата();

Цены = Новое Соответствие;
Цены.Вставить("Товар-01", 1200);
Цена = Цены.Получить("Товар-01"); // 1200
КоллекцияЧем отличаетсяПример задачи
МассивУпорядоченный список, доступ по индексу с нуляСписок ссылок на документы
СтруктураКлючи — строки, имена как у переменныхНабор параметров для процедуры
СоответствиеКлючом может быть любое значение, в том числе ссылкаСумма по каждому контрагенту
ТаблицаЗначенийСтроки и колонки, сортировка, свёрткаПромежуточный отчёт в памяти

Строки склеивают плюсом. Число со строкой без форматирования лучше не склеивать: 1500 превратится в "1 500" с неразрывным пробелом. Используйте Формат(Сумма, "ЧГ=0") или шаблон:

Текст = СтрШаблон("Найдено документов: %1 на сумму %2 руб.",
    Формат(Количество, "ЧГ=0"), Формат(Сумма, "ЧДЦ=2"));

Модули и область видимости в коде 1С

Где написан код, там он и выполняется. Основные модули конфигурации:

  • 📦 Модуль объекта — код конкретного документа или элемента справочника: обработчики ПередЗаписью, ОбработкаПроведения.
  • 🗂 Модуль менеджера — функции «для всех объектов вида», например печать или подбор.
  • 🖼 Модуль формы — реакции на кнопки и поля конкретной формы.
  • 📚 Общий модуль — библиотека процедур. Флажки «Клиент», «Сервер», «Вызов сервера», «Привилегированный» определяют, где и с какими правами он работает.
  • 🚀 Модуль сеанса и модуль управляемого приложения — код, который выполняется при старте сеанса или программы.

Внутри модуля код делится на процедуры и функции. Функция возвращает значение через Возврат, процедура — нет. Слово Экспорт открывает процедуру для вызова из других модулей.

Функция СуммаСНДС(Сумма, Ставка = 20) Экспорт
    Возврат Сумма + Окр(Сумма * Ставка / 100, 2);
КонецФункции

Видимость переменных простая:

  1. Переменная внутри процедуры живёт до её окончания.
  2. Переменная, объявленная через Перем в начале модуля, видна всем процедурам этого модуля.
  3. С Перем ИмяПеременной Экспорт она видна снаружи — в модуле объекта через сам объект, в модуле приложения глобально.

Параметры передаются по ссылке: если процедура изменит параметр, изменится и переменная у вызывающего кода. Чтобы защитить значение, перед параметром пишут Знач.

Клиент и сервер: директивы компиляции

В модуле управляемой формы перед каждой процедурой ставят директиву:

ДирективаЧто доступноТипичное применение
&НаКлиентеЭлементы формы, диалоги, файлы на компьютере пользователяОбработка нажатия кнопки
&НаСервереБаза данных и реквизиты формыЗапросы, запись объектов
&НаСервереБезКонтекстаТолько база, без данных формыБыстрые вызовы без передачи формы на сервер
&НаКлиентеНаСервереБезКонтекстаКод, который можно вызвать и там, и тамРасчёты и форматирование

На клиенте нельзя выполнить запрос или вызвать ПолучитьОбъект(). Поэтому обработчик кнопки обычно пустой и лишь передаёт работу серверной процедуре.

Условия и циклы в скриптах 1С

Условие записывается так:

Если Сумма > 100000 Тогда
    Уровень = "Крупная";
ИначеЕсли Сумма > 10000 Тогда
    Уровень = "Средняя";
Иначе
    Уровень = "Мелкая";
КонецЕсли;

Для коротких случаев есть тернарный оператор: Статус = ?(Оплачено, "Закрыт", "Открыт");. Логические операции — И, ИЛИ, НЕ. Платформа вычисляет условие слева направо и останавливается, как только результат ясен. Поэтому Если Значение <> Неопределено И Значение.Сумма > 0 не упадёт на пустом значении.

Три вида циклов:

// Счётчик: от 1 до 10 включительно
Для Сч = 1 По 10 Цикл
    Итог = Итог + Сч;
КонецЦикла;

// Перебор коллекции
Для Каждого Город Из Массив Цикл
    Сообщить(Город);
КонецЦикла;

// Пока условие истинно
Пока Остаток > 0 Цикл
    Остаток = Остаток - Платёж;
КонецЦикла;

Прервать выходит из цикла, Продолжить переходит к следующей итерации.

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

Количество = Массив.Количество();
Для Сч = 1 По Количество Цикл
    Индекс = Количество - Сч;
    Если ПустаяСтрока(Массив[Индекс]) Тогда
        Массив.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Здесь Количество запомнено до цикла, а индекс считается от него. Удаление с конца не сдвигает элементы, которые ещё предстоит проверить.

Проверьте себя
Что вернёт выражение ?(5 > 3, "Да", "Нет")?
Можно ли выполнить запрос в процедуре с директивой &НаКлиенте?
С какого номера начинаются индексы массива?

Как писать запросы и работать с данными в 1С

Данные базы читают запросами. Язык запросов похож на SQL, но обращается к объектам метаданных: Справочник.Контрагенты, Документ.РеализацияТоваровУслуг, РегистрНакопления.ТоварыНаСкладах.

Полный рабочий пример для внешней обработки в Бухгалтерии предприятия 3.0: найти контрагентов без ИНН.

&НаКлиенте
Процедура Найти(Команда)
    НайтиНаСервере();
КонецПроцедуры

&НаСервере
Процедура НайтиНаСервере()

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Контрагент,
    |    Контрагенты.Наименование КАК Наименование
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |    НЕ Контрагенты.ЭтоГруппа
    |    И НЕ Контрагенты.ПометкаУдаления
    |    И Контрагенты.ИНН = &ПустойИНН";
    Запрос.УстановитьПараметр("ПустойИНН", "");

    Выборка = Запрос.Выполнить().Выбрать();
    Найдено = 0;
    Пока Выборка.Следующий() Цикл
        Сообщить(Выборка.Наименование);
        Найдено = Найдено + 1;
    КонецЦикла;

    Сообщить(СтрШаблон("Всего без ИНН: %1", Формат(Найдено, "ЧГ=0")));

КонецПроцедуры

Многострочный текст запроса записывают с вертикальной чертой в начале каждой строки. Составлять его руками необязательно: щёлкните правой кнопкой внутри строки и выберите «Конструктор запроса» — платформа соберёт текст сама.

💡 Значения в запрос передавайте только параметрами через УстановитьПараметр. Подставлять их в текст склейкой строк нельзя: ломаются даты, кавычки и кэш плана запроса.

Чтение и запись объектов

Запрос только читает. Чтобы изменить данные, получают объект:

Объект = Выборка.Контрагент.ПолучитьОбъект();
Объект.Комментарий = "Проверить ИНН";
Объект.Записать();

Новый элемент создают через менеджер: Справочники.Номенклатура.СоздатьЭлемент(), новый документ — Документы.<Имя>.СоздатьДокумент(). Для документа запись с проведением выглядит так: Документ.Записать(РежимЗаписиДокумента.Проведение).

Массовая запись в рабочей базе — только после резервной копии. Запущенный по ошибке цикл перезапишет тысячи объектов за минуту, а отменить это кнопкой нельзя.

Обработка ошибок и отладка скриптов

Ошибка выполнения прерывает код и показывает пользователю сообщение. Чтобы перехватить её, используют Попытка:

Попытка
    Объект.Записать();
Исключение
    Текст = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
    ЗаписьЖурналаРегистрации("Моя обработка",
        УровеньЖурналаРегистрации.Ошибка, , , Текст);
    Сообщить("Не записан: " + Объект.Наименование);
КонецПопытки;

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

Если несколько записей должны пройти вместе или не пройти вовсе, используйте транзакцию:

НачатьТранзакцию();
Попытка
    ДокументПриход.Записать(РежимЗаписиДокумента.Проведение);
    ДокументРасход.Записать(РежимЗаписиДокумента.Проведение);
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение;
КонецПопытки;

ВызватьИсключение без текста пробрасывает исходную ошибку дальше, чтобы вызывающий код о ней узнал.

Отладчик Конфигуратора

Отладка — самый короткий путь понять, что делает чужой или собственный код:

  1. Поставьте курсор на строку и нажмите F9 — появится точка останова.
  2. Запустите Отладка → Начать отладку (F5): откроется 1С:Предприятие, подключённое к отладчику.
  3. Когда выполнение дойдёт до точки, Конфигуратор остановится на ней.
  4. F10 — следующая строка, F11 — зайти внутрь вызываемой процедуры.
  5. Shift+F9 открывает окно вычисления выражения: посмотрите значение переменной или содержимое таблицы.

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

Для поиска медленных мест есть Отладка → Замер производительности. После прогона он показывает, сколько раз выполнилась каждая строка и какую долю времени она заняла.

Как писать быстрый и понятный код

Работающий код и хороший код в 1С различаются на порядки по скорости. Главные правила:

  • 🚫 Никаких запросов в цикле. Сто запросов по одному контрагенту медленнее одного запроса по ста. Соберите ссылки в массив и передайте параметром: ГДЕ Ссылка В (&Список).
  • 🔗 Осторожно с обращением через точку. Выборка.Контрагент.ИНН в цикле — это отдельное чтение из базы на каждой строке. Получите ИНН сразу в запросе.
  • 📥 Временные таблицы (ПОМЕСТИТЬ) вместо вложенных запросов в соединениях. План запроса становится предсказуемым.
  • 📡 Меньше серверных вызовов. Каждый переход с клиента на сервер — сетевой обмен. Соберите все действия в одну серверную процедуру.
  • ⚡ Виртуальные таблицы регистров (Остатки, Обороты) с условиями в параметрах, а не в ГДЕ. Так фильтр применяется до расчёта итогов.

Понятность важна не меньше скорости:

  • Одна процедура — одна задача. Если она длиннее экрана, её пора делить.
  • Имена по смыслу: СуммаКОплате, а не с1.
  • Комментарий объясняет, зачем, а не что: «исключаем возвраты, их учитывает отдельный отчёт».
  • Перед правкой типовой конфигурации подумайте о расширении: при обновлении правки в основной конфигурации придётся сравнивать и переносить вручную.

Частые ошибки новичка

ОшибкаЧем грозитКак правильно
Запрос в обработчике &НаКлиентеОшибка «Тип не определён» или метод недоступенВынести в &НаСервере
Сравнение ссылки со строкойУсловие никогда не выполнитсяСравнивать со ссылкой или с ПредопределенноеЗначение
Дата в запросе без параметраНеверный результат при другом формате датыУстановитьПараметр
Записать() без проверки заполненияПустые реквизиты в базеПроверять до записи или вызывать ПроверитьЗаполнение()

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

Где взять базу для тренировки?
Подойдёт учебная версия платформы 1С:Предприятие 8.3 или копия рабочей базы, развёрнутая отдельно. Писать первые скрипты в рабочей базе не стоит.
Нужно ли знать английский, чтобы программировать в 1С?
Нет. Весь язык и справка по нему на русском. Английский синтаксис есть, но в типовых конфигурациях код написан по-русски.
Где посмотреть все методы объекта?
В Конфигураторе откройте Справка → Синтаксис-помощник. Там описан каждый тип, его свойства и методы, а также где они доступны: на клиенте, на сервере или везде.
Чем внешняя обработка отличается от расширения?
Обработку запускают вручную, когда нужно. Расширение встраивается в конфигурацию и меняет её поведение постоянно: добавляет реквизиты, команды, перехватывает процедуры типового кода.
Можно ли запускать код по расписанию?
Да, через регламентное задание конфигурации. В клиент-серверном варианте их выполняет кластер серверов, в файловом — сеанс, в котором включён запуск регламентных заданий.