Встроенный язык 1С:Предприятие — с чего начать разработчику
Содержание
Код в 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, но с русскими словами).
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ПометкаУдаления = ЛОЖЬ";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Артикул);
КонецЦикла;
Значения в запрос передают через параметры — так безопаснее и быстрее, чем склеивать условие в текст:
Запрос.Текст =
"ВЫБРАТЬ Товары.Номенклатура, Товары.Количество
|ИЗ Документ.ПоступлениеТоваровУслуг.Товары КАК Товары
|ГДЕ Товары.Ссылка = &Документ";
Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент);
Вертикальная черта | в начале строк — это разделитель строк текста запроса, его ставят автоматически в конструкторе запроса. Чтобы не писать запрос руками, в модуле есть конструктор запроса: щёлкните правой кнопкой по тексту и выберите конструктор — он соберёт ВЫБРАТЬ ... ИЗ ... ГДЕ по таблицам базы в визуальном окне.
Основные операции языка запросов:
ВЫБРАТЬ— перечисление полей;ИЗ— источник (таблица объекта, регистра, виртуальная таблица остатков);ГДЕ— отбор строк;СГРУППИРОВАТЬ ПО— группировка с итогамиСУММА,КОЛИЧЕСТВО;УПОРЯДОЧИТЬ ПО— сортировка;СОЕДИНЕНИЕ— связывание нескольких таблиц.
Для отчётов чаще берут не запрос напрямую, а Систему компоновки данных (СКД) — она сама строит группировки, отборы и оформление поверх текста запроса.
Как создать и записать объект программно
Запрос только читает данные. Чтобы что-то изменить — создать элемент справочника, провести документ , заполнить реквизиты — работают с самим объектом.
Новый элемент справочника создают через менеджер, заполняют реквизиты и записывают:
НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
НовыйТовар.Наименование = "Бумага А4";
НовыйТовар.Артикул = "BM-0001";
НовыйТовар.ЕдиницаИзмерения = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("шт");
НовыйТовар.Записать();
Существующий объект сначала получают по ссылке, затем вызывают ПолучитьОбъект() — ссылка сама по себе только читается, менять можно именно объект:
ОбъектТовара = СсылкаНаТовар.ПолучитьОбъект();
ОбъектТовара.Комментарий = "Проверено";
ОбъектТовара.Записать();
Табличную часть (строки документа, спецификации) обходят циклом Для Каждого, а новую строку добавляют методом Добавить():
Для Каждого Строка Из Документ.Товары Цикл
Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;
НоваяСтрока = Документ.Товары.Добавить();
НоваяСтрока.Номенклатура = НовыйТовар;
НоваяСтрока.Количество = 5;
Массовую запись или проведение документов делайте в транзакции (НачатьТранзакцию() / ЗафиксироватьТранзакцию()) и обязательно в клиент-серверной базе — на рабочей базе такие операции запускают в нерабочее время, чтобы не мешать пользователям.
Документ проводят, передавая в Записать() режим проведения — тогда сформируются движения по регистрам (остатки, взаиморасчёты). Без режима проведения документ просто сохранится как черновик.
Отладка и обработка ошибок
Код редко работает правильно с первого раза. Два разных инструмента помогают с этим: отладчик (найти, где именно ломается) и обработка исключений (не дать программе рухнуть на пользователе).
Отладка в Конфигураторе. Поставьте точку останова на нужной строке клавишей F9 — слева появится красный кружок. Запустите отладку из меню Отладка → Начать отладку (F5). Когда выполнение дойдёт до точки, оно остановится, и вы сможете:
F11— выполнить следующую строку, заходя внутрь вызываемых процедур;F10— выполнить строку, не заходя внутрь;F5— продолжить до следующей точки останова;- навести курсор на переменную или открыть окно «Табло», чтобы увидеть её значение.
Если отладка не подключается в клиент-серверной базе, проверьте, что отладка разрешена в свойствах рабочего сервера и в параметрах подключения Конфигуратора.
Обработка исключений. Операции, которые могут не выполниться (запись документа, обращение к внешнему ресурсу, деление), оборачивают в Попытка ... Исключение ... КонецПопытки:
Попытка
Документ.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписьЖурналаРегистрации("Проведение",
УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
КонецПопытки;
Функция ОписаниеОшибки() возвращает текст ошибки. Собственную ошибку поднимают оператором ВызватьИсключение "Текст ошибки"; — например, если проверка данных не прошла и продолжать нельзя.
Частая ловушка новичка — «проглотить» ошибку пустым блоком Исключение. Так программа молча продолжит работу с неверными данными. Минимум — запишите ошибку в журнал регистрации, как в примере выше.
Как писать быстрый код
Платформа прощает неаккуратность на десятке строк справочника и жёстко наказывает на базе в миллион документов. Несколько правил, которые экономят часы работы пользователей.
Не делайте запрос внутри цикла. Это главная ошибка по производительности. Вместо того чтобы на каждой строке документа лезть в базу, соберите все нужные данные одним запросом до цикла.
// Плохо: 1000 строк → 1000 обращений к базе
Для Каждого Строка Из Товары Цикл
Цена = ПолучитьЦенуЗапросом(Строка.Номенклатура); // запрос в цикле!
КонецЦикла;
Правильно — один запрос со всеми номенклатурами и соединением с таблицей цен, а в цикле только чтение готового результата.
Ещё несколько приёмов:
- 📊 Считайте в запросе, а не в коде — суммы, остатки, группировки пусть делает СУБД.
- 🔁 Минимизируйте вызовы сервера с клиента — каждый переход клиент→сервер стоит времени; соберите данные за один вызов.
- 🧠 Кэшируйте повторно используемые значения через общий модуль с флагом «Повторное использование возвращаемых значений».
- 🗂 Отбирайте по индексированным полям — отбор по неиндексированному реквизиту заставляет СУБД читать всю таблицу.
Удаление элементов из коллекции в цикле делайте с конца — иначе индексы «съедут»:
Для Сч = 1 По Массив.Количество() Цикл
Элемент = Массив[Массив.Количество() - Сч];
Если НужноУдалить(Элемент) Тогда
Массив.Удалить(Массив.Количество() - Сч);
КонецЕсли;
КонецЦикла;
Найти узкие места помогает инструмент Отладка → Замер производительности в Конфигураторе: он покажет, сколько раз выполнялась каждая строка и сколько времени заняла.
Чистый код: стандарты и читаемость
Код пишут один раз, а читают и правят десятки раз — часто другой человек. Поэтому читаемость важнее краткости.
Что держит код в порядке:
- Говорящие имена.
СуммаДокументаСНДСпонятнее, чемС1илитмп. - Отступы. Тело процедуры, цикла, условия сдвигают на один уровень (обычно табуляцией). Конфигуратор умеет выравнивать выделенный блок автоматически.
- Короткие процедуры. Одна процедура — одна задача. Если она разрослась на три экрана, её пора разбить.
- Комментарии по делу. Поясняйте «почему так», а не «что делает строка» — это и так видно из кода.
- Экспортные процедуры (со словом
Экспорт) — только те, что реально вызываются извне модуля. Остальное держите внутренним.
// Пересчёт суммы строки с учётом скидки.
// Вызывается при изменении количества или цены.
Процедура ПересчитатьСуммуСтроки(СтрокаТовара) Экспорт
СуммаБезСкидки = СтрокаТовара.Количество * СтрокаТовара.Цена;
СтрокаТовара.Сумма = СуммаБезСкидки - СуммаБезСкидки * СтрокаТовара.Скидка / 100;
КонецПроцедуры
У фирмы 1С есть опубликованный свод правил оформления кода — «Стандарты разработки». Там описаны именование, структура модулей, работа с транзакциями и типовые паттерны. Начинающему стоит привыкать к ним сразу: типовые конфигурации написаны по этим правилам, и ваш код должен в них вписываться.
Если дорабатываете типовую конфигурацию, по возможности не меняйте её напрямую, а используйте расширение конфигурации (появились в платформе 8.3.6). Так доработки не слетят при очередном обновлении от 1С и останутся отдельным, легко отключаемым слоем.
Частые вопросы
На каком языке писать — русском или английском?
Процедура, и Procedure. На практике в России пишут по-русски — так написаны типовые конфигурации и вся документация. Смешивать языки в одном коде не стоит.