Встроенный язык 1С:Предприятие — с чего начать разработчику

· 9 мин

Содержание

Код в 1С пишут во встроенном языке — внутри Конфигуратора (или 1С:EDT), в модулях объектов, форм и общих модулях. Язык двуязычный: ключевые слова работают и по-русски (Процедура, Если, Цикл), и по-английски (Procedure, If, For). Синтаксис ближе всего к Паскалю: строгие конструкции, явное завершение блоков, точка с запятой в конце оператора.

Типичная ситуация: бухгалтеру нужна печатная форма с нестандартным расчётом, а в типовой конфигурации её нет. Чтобы сделать такую доработку, открывают Конфигуратор, находят нужный объект и пишут несколько процедур. Ниже — как устроен этот язык и где именно размещается код.

Разработка ведётся на платформе 8.3 с интерфейсом «Такси». Инструмент для написания кода — Конфигуратор (входит в состав платформы) или отдельная среда 1С:EDT на базе Eclipse.

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

Код всегда находится внутри процедуры или функции. Процедура выполняет действия, функция возвращает значение через Возврат.

Процедура ПоказатьПриветствие()
    Сообщить("Привет из 1С!");
КонецПроцедуры

Функция СуммаСНДС(СуммаБезНДС, Ставка)
    Возврат СуммаБезНДС + СуммаБезНДС * Ставка / 100;
КонецФункции

Переменные не требуют объявления типа — тип определяется присвоенным значением. Явно объявить переменную можно словом Перем, но чаще её просто присваивают:

Количество = 10;
Цена = 150.50;
Наименование = "Бумага А4";
ИтогоСтрокой = СтрШаблон("%1 шт. по %2 руб.", Количество, Цена);

Для склейки числа со строкой не используйте просто + — число сначала приведётся непредсказуемо. Берите СтрШаблон(...) или Формат(Число, "ЧГ=0").

Основные конструкции управления:

  • Условие — Если ... Тогда ... ИначеЕсли ... Иначе ... КонецЕсли;
  • Цикл со счётчиком — Для Сч = 1 По 10 Цикл ... КонецЦикла;
  • Обход коллекции — Для Каждого Строка Из Таблица Цикл ... КонецЦикла;
  • Цикл по условию — Пока Условие Цикл ... КонецЦикла;
Если Количество > 0 Тогда
    Скидка = 5;
ИначеЕсли Количество > 100 Тогда
    Скидка = 10;
Иначе
    Скидка = 0;
КонецЕсли;

Комментарий начинается с двух слэшей //. Регистр ключевых слов и имён переменных платформа не различает, но принято писать в «КаждоеСловоСБольшой» — так называемый PascalCase.

Все встроенные типы, методы и свойства собраны в Синтакс-помощнике (вызывается в Конфигураторе из меню Справка или по контекстной подсказке при наборе точки после объекта). Это первый инструмент, к которому стоит привыкнуть: там же есть примеры вызова каждого метода.

Где размещается код: модули и директивы

Код в 1С лежит не в одном файле, а в разных модулях — каждый отвечает за свою область.

МодульЧто в нём пишут
Модуль формыРеакции на действия пользователя: нажатия кнопок, изменение полей
Модуль объекта (документа, справочника)Логику записи, проведения, заполнения
Модуль менеджераМетоды, не привязанные к конкретному экземпляру объекта
Общий модульПереиспользуемые процедуры и функции для всей конфигурации
Модуль приложенияДействия при запуске и завершении программы

В управляемом приложении код выполняется либо на компьютере пользователя (клиент), либо на сервере 1С. Где именно — задают директивы компиляции перед процедурой:

  • &НаКлиенте — работает у пользователя, может обращаться к элементам формы, но не к базе данных напрямую;
  • &НаСервере — работает на сервере, имеет доступ к базе, но «видит» форму целиком (это дороже по ресурсам);
  • &НаСервереБезКонтекста — работает на сервере и не тащит с собой данные формы, самый экономный вариант для чтения из базы.
&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
    ПересчитатьСумму();
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьКурс(Валюта, Дата)
    Возврат РегистрыСведений.КурсыВалют.ПолучитьПоследнее(
        Дата, Новый Структура("Валюта", Валюта)).Курс;
КонецФункции

С клиента нельзя напрямую обратиться к базе данных. Если нужно прочитать или записать данные, вызывайте серверную процедуру. Частая ошибка новичка — пытаться выполнить запрос в &НаКлиенте-процедуре; платформа выдаст ошибку компиляции.

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

Запросы: как достать данные из базы

Перебирать весь справочник циклом — долго и неправильно. Данные из базы получают запросом на языке запросов 1С (он похож на SQL, но с русскими словами).

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

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Артикул);
КонецЦикла;

Значения в запрос передают через параметры — так безопаснее и быстрее, чем склеивать условие в текст:

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

Вертикальная черта | в начале строк — это разделитель строк текста запроса, его ставят автоматически в конструкторе запроса. Чтобы не писать запрос руками, в модуле есть конструктор запроса: щёлкните правой кнопкой по тексту и выберите конструктор — он соберёт ВЫБРАТЬ ... ИЗ ... ГДЕ по таблицам базы в визуальном окне.

Основные операции языка запросов:

  1. ВЫБРАТЬ — перечисление полей;
  2. ИЗ — источник (таблица объекта, регистра, виртуальная таблица остатков);
  3. ГДЕ — отбор строк;
  4. СГРУППИРОВАТЬ ПО — группировка с итогами СУММА, КОЛИЧЕСТВО;
  5. УПОРЯДОЧИТЬ ПО — сортировка;
  6. СОЕДИНЕНИЕ — связывание нескольких таблиц.

Для отчётов чаще берут не запрос напрямую, а Систему компоновки данных (СКД) — она сама строит группировки, отборы и оформление поверх текста запроса.

Как создать и записать объект программно

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

Новый элемент справочника создают через менеджер, заполняют реквизиты и записывают:

НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
НовыйТовар.Наименование = "Бумага А4";
НовыйТовар.Артикул = "BM-0001";
НовыйТовар.ЕдиницаИзмерения = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("шт");
НовыйТовар.Записать();

Существующий объект сначала получают по ссылке, затем вызывают ПолучитьОбъект() — ссылка сама по себе только читается, менять можно именно объект:

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

Табличную часть (строки документа, спецификации) обходят циклом Для Каждого, а новую строку добавляют методом Добавить():

Для Каждого Строка Из Документ.Товары Цикл
    Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;

НоваяСтрока = Документ.Товары.Добавить();
НоваяСтрока.Номенклатура = НовыйТовар;
НоваяСтрока.Количество = 5;

Массовую запись или проведение документов делайте в транзакции (НачатьТранзакцию() / ЗафиксироватьТранзакцию()) и обязательно в клиент-серверной базе — на рабочей базе такие операции запускают в нерабочее время, чтобы не мешать пользователям.

Документ проводят, передавая в Записать() режим проведения — тогда сформируются движения по регистрам (остатки, взаиморасчёты). Без режима проведения документ просто сохранится как черновик.

Отладка и обработка ошибок

Код редко работает правильно с первого раза. Два разных инструмента помогают с этим: отладчик (найти, где именно ломается) и обработка исключений (не дать программе рухнуть на пользователе).

Отладка в Конфигураторе. Поставьте точку останова на нужной строке клавишей F9 — слева появится красный кружок. Запустите отладку из меню Отладка → Начать отладку (F5). Когда выполнение дойдёт до точки, оно остановится, и вы сможете:

  • F11 — выполнить следующую строку, заходя внутрь вызываемых процедур;
  • F10 — выполнить строку, не заходя внутрь;
  • F5 — продолжить до следующей точки останова;
  • навести курсор на переменную или открыть окно «Табло», чтобы увидеть её значение.

Если отладка не подключается в клиент-серверной базе, проверьте, что отладка разрешена в свойствах рабочего сервера и в параметрах подключения Конфигуратора.

Обработка исключений. Операции, которые могут не выполниться (запись документа, обращение к внешнему ресурсу, деление), оборачивают в Попытка ... Исключение ... КонецПопытки:

Попытка
    Документ.Записать(РежимЗаписиДокумента.Проведение);
Исключение
    ЗаписьЖурналаРегистрации("Проведение",
        УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
КонецПопытки;

Функция ОписаниеОшибки() возвращает текст ошибки. Собственную ошибку поднимают оператором ВызватьИсключение "Текст ошибки"; — например, если проверка данных не прошла и продолжать нельзя.

Частая ловушка новичка — «проглотить» ошибку пустым блоком Исключение. Так программа молча продолжит работу с неверными данными. Минимум — запишите ошибку в журнал регистрации, как в примере выше.

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

Платформа прощает неаккуратность на десятке строк справочника и жёстко наказывает на базе в миллион документов. Несколько правил, которые экономят часы работы пользователей.

Не делайте запрос внутри цикла. Это главная ошибка по производительности. Вместо того чтобы на каждой строке документа лезть в базу, соберите все нужные данные одним запросом до цикла.

// Плохо: 1000 строк → 1000 обращений к базе
Для Каждого Строка Из Товары Цикл
    Цена = ПолучитьЦенуЗапросом(Строка.Номенклатура); // запрос в цикле!
КонецЦикла;

Правильно — один запрос со всеми номенклатурами и соединением с таблицей цен, а в цикле только чтение готового результата.

Ещё несколько приёмов:

  • 📊 Считайте в запросе, а не в коде — суммы, остатки, группировки пусть делает СУБД.
  • 🔁 Минимизируйте вызовы сервера с клиента — каждый переход клиент→сервер стоит времени; соберите данные за один вызов.
  • 🧠 Кэшируйте повторно используемые значения через общий модуль с флагом «Повторное использование возвращаемых значений».
  • 🗂 Отбирайте по индексированным полям — отбор по неиндексированному реквизиту заставляет СУБД читать всю таблицу.

Удаление элементов из коллекции в цикле делайте с конца — иначе индексы «съедут»:

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

Найти узкие места помогает инструмент Отладка → Замер производительности в Конфигураторе: он покажет, сколько раз выполнялась каждая строка и сколько времени заняла.

Чистый код: стандарты и читаемость

Код пишут один раз, а читают и правят десятки раз — часто другой человек. Поэтому читаемость важнее краткости.

Что держит код в порядке:

  • Говорящие имена. СуммаДокументаСНДС понятнее, чем С1 или тмп.
  • Отступы. Тело процедуры, цикла, условия сдвигают на один уровень (обычно табуляцией). Конфигуратор умеет выравнивать выделенный блок автоматически.
  • Короткие процедуры. Одна процедура — одна задача. Если она разрослась на три экрана, её пора разбить.
  • Комментарии по делу. Поясняйте «почему так», а не «что делает строка» — это и так видно из кода.
  • Экспортные процедуры (со словом Экспорт) — только те, что реально вызываются извне модуля. Остальное держите внутренним.
// Пересчёт суммы строки с учётом скидки.
// Вызывается при изменении количества или цены.
Процедура ПересчитатьСуммуСтроки(СтрокаТовара) Экспорт
    СуммаБезСкидки = СтрокаТовара.Количество * СтрокаТовара.Цена;
    СтрокаТовара.Сумма = СуммаБезСкидки - СуммаБезСкидки * СтрокаТовара.Скидка / 100;
КонецПроцедуры

У фирмы 1С есть опубликованный свод правил оформления кода — «Стандарты разработки». Там описаны именование, структура модулей, работа с транзакциями и типовые паттерны. Начинающему стоит привыкать к ним сразу: типовые конфигурации написаны по этим правилам, и ваш код должен в них вписываться.

Если дорабатываете типовую конфигурацию, по возможности не меняйте её напрямую, а используйте расширение конфигурации (появились в платформе 8.3.6). Так доработки не слетят при очередном обновлении от 1С и останутся отдельным, легко отключаемым слоем.

Проверьте себя
Какое ключевое слово завершает процедуру в 1С?
Где выполняется код с директивой &НаСервере?
Чем правильнее достать данные из базы?
Что завершает блок перехвата ошибки?

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

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