Язык 1С: встроенный язык, язык запросов и всё, что вокруг них
Содержание
В 1С программируют на собственном встроенном языке платформы «1С:Предприятие». Он не является диалектом Basic, Pascal или SQL, хотя на первый взгляд похож на всё сразу. Для выборки данных к нему добавлен второй язык: язык запросов, который внешне напоминает SQL, но работает с объектами конфигурации, а не с таблицами СУБД.
Сама платформа, по общепринятым сведениям, написана на C++ и компилируется в нативный код. Но разработчик конфигурации этого кода не видит. Он пишет модули на встроенном языке, а платформа исполняет их на клиенте или на сервере.
Что за язык внутри платформы: природа и устройство
Встроенный язык проприетарный: его разработала фирма 1С, и вне платформы он не работает . Нельзя поставить «компилятор 1С» и запустить программу из командной строки как скрипт на Python. Код живёт только внутри конфигурации и выполняется платформой.
Что важно знать о его природе:
- 🧩 Предметно-ориентированный. Язык создан под учётные задачи: документы, справочники, регистры, отчёты. Типы «Справочник», «Документ», «ТаблицаЗначений» встроены в него как родные.
- 🌐 Два написания ключевых слов. Любую конструкцию можно писать по-русски или по-английски:
ЕслииIf,ПроцедураиProcedure. Оба варианта равноправны и смешиваются в одном модуле. - 🔤 Не зависит от регистра.
Сообщить,сообщитьиСООБЩИТЬдля компилятора одно и то же. - 🔄 Динамическая типизация. Тип переменной определяется значением, объявлять его не нужно. Тип можно узнать функцией
ТипЗнч(). - 📦 Модульная организация. Код лежит в модулях: общих, модулях форм, объектов, менеджеров, приложения и сеанса. Каждый модуль выполняется в своём контексте.
Исходный текст не хранится отдельными файлами в привычном смысле. Он входит в конфигурацию, которая лежит в базе данных. Выгрузить её в файлы можно, но это отдельная операция, а не основной режим работы.
Синтаксис: как выглядит код на 1С
Если вы видели Pascal или Visual Basic, синтаксис покажется знакомым. Блоки закрываются парными словами, фигурных скобок нет.
Процедура ПоказатьСумму(Цена, Количество)
Сумма = Цена * Количество;
Если Сумма > 10000 Тогда
Сообщить("Крупная покупка: " + Сумма);
ИначеЕсли Сумма = 0 Тогда
Сообщить("Нулевая сумма");
Иначе
Сообщить("Обычная покупка: " + Сумма);
КонецЕсли;
КонецПроцедуры
Основные конструкции:
| Что нужно | Как записывается |
|---|---|
| Условие | Если … Тогда … Иначе … КонецЕсли; |
| Цикл по счётчику | Для Индекс = 0 По 9 Цикл … КонецЦикла; |
| Цикл по коллекции | Для Каждого Элемент Из Коллекция Цикл … КонецЦикла; |
| Цикл с условием | Пока Условие Цикл … КонецЦикла; |
| Процедура и функция | Процедура … КонецПроцедуры, Функция … КонецФункции |
| Обработка ошибок | Попытка … Исключение … КонецПопытки; |
| Вызов из другого модуля | ключевое слово Экспорт у процедуры или функции |
Разница между процедурой и функцией такая же, как в большинстве языков: функция возвращает значение через Возврат, процедура нет.
Точка с запятой ставится после каждого оператора. Комментарии начинаются с двойной косой черты //. Многострочных комментариев в языке нет.
Строки в двойных кавычках. Внутри строки кавычку удваивают: "Он сказал ""да""". Для многострочного текста, например запроса, каждую следующую строку начинают с вертикальной черты |.
Чего в языке нет
Классического объектно-ориентированного программирования здесь не будет. Нельзя объявить свой класс с наследованием и полиморфизмом. Зато можно работать с объектами платформы: создавать их через Новый, вызывать методы, читать свойства. Поведение расширяется не наследованием, а механизмом расширений конфигурации (о нём ниже).
Нет и привычной многопоточности на уровне языка. Параллельность решается фоновыми заданиями, которые платформа запускает на сервере.
Обращение к базе данных и язык запросов
Данные в 1С хранятся в СУБД: PostgreSQL, Microsoft SQL Server или файловой базе. Но разработчик редко пишет SQL напрямую. Он работает с объектами метаданных, а платформа сама переводит обращения в SQL-запросы.
Для массовой выборки есть язык запросов. Он похож на SQL ключевыми словами ВЫБРАТЬ, ИЗ, ГДЕ, СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, ОБЪЕДИНИТЬ. Но в ИЗ вы пишете не имя таблицы СУБД, а имя объекта конфигурации: Справочник.Номенклатура, Документ.РеализацияТоваровУслуг, РегистрНакопления.ТоварыНаСкладах.Остатки.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Код КАК Код
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.Наименование ПОДОБНО &Маска";
Запрос.УстановитьПараметр("Маска", "Кабель%");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Код + " — " + Выборка.Наименование);
КонецЦикла;
Здесь видны три особенности:
- Параметры задаются через
&Имяи передаются методомУстановитьПараметр. Подставлять значения конкатенацией строк не нужно. - Результат читают выборкой в цикле
Пока Выборка.Следующий(). - Вместо
LIKEиспользуетсяПОДОБНО, вместоAS—КАК.
Виртуальные таблицы регистров
Главное, чего нет в обычном SQL, это виртуальные таблицы. Для регистра накопления можно запросить .Остатки(&Дата) или .Обороты(&Начало, &Конец). Платформа сама посчитает остатки на дату по итогам и движениям. Писать группировки по тысячам строк движений вручную не придётся.
Ещё одно отличие: запрос умеет обращаться через точку к реквизитам связанных объектов. Запись Реализация.Контрагент.ИНН заставит платформу сделать нужные соединения сама.
Обращение через несколько точек удобно, но на больших выборках бьёт по скорости: платформа строит неявные соединения, которые вы не контролируете. В тяжёлых запросах соединения пишут явно.
Запросы также умеют временные таблицы (ПОМЕСТИТЬ), пакетное выполнение нескольких запросов, итоги (ИТОГИ ПО) и вложенные запросы.
Клиент и сервер: где выполняется код
Здесь у разработчиков с опытом на других языках чаще всего возникают вопросы. Один и тот же модуль формы содержит код, который работает в разных местах. Место выполнения задаётся директивой компиляции перед процедурой:
| Директива | Где выполняется | Доступ к данным формы |
|---|---|---|
&НаКлиенте | на стороне пользователя | да |
&НаСервере | на сервере 1С | да, форма передаётся целиком |
&НаСервереБезКонтекста | на сервере | нет, передаются только параметры |
&НаКлиентеНаСервереБезКонтекста | и там и там | нет |
Пример: кнопка на форме вызывает клиентскую процедуру, а та обращается к серверной.
&НаКлиенте
Процедура ПересчитатьНажатие(Команда)
Результат = ПолучитьИтогНаСервере(Объект.Контрагент);
Сообщить("Итого: " + Результат);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьИтогНаСервере(Контрагент)
// здесь допустим запрос к базе
Возврат 0;
КонецФункции
Клиентский код не может выполнять запросы к базе напрямую. Всё, что требует данных, уходит на сервер. Каждый такой вызов стоит времени: между клиентом и сервером идёт передача параметров по сети. Поэтому опытные разработчики стараются делать меньше серверных вызовов с большим объёмом работы, а не много мелких.
Это правило работает одинаково для тонкого клиента , веб-клиента и мобильного приложения. Единый код платформа исполняет в разных оболочках, а JavaScript для веб-клиента писать не нужно: его готовит сама платформа.
Что доступно только на сервере
- 🗄 работа с запросами и объектами базы (запись документа, проведение);
- 📁 доступ к файлам на диске сервера;
- 🔐 управление блокировками данных и транзакциями;
- ⏱ фоновые и регламентные задания.
На клиенте доступны интерактивные действия: диалоги выбора файлов, открытие форм, показ сообщений. Какие именно методы доступны в каком контексте, подсказывает синтаксис-помощник в Конфигураторе: у каждого метода указано, где его можно вызывать. Если вызвать серверный метод в клиентской процедуре, компилятор сообщит об ошибке при проверке модуля.
Сравнение с SQL, Python, C# и другими языками
Частый вопрос: чем 1С отличается от привычных языков и можно ли «перейти» с одного на другой. Короткая таблица.
| Критерий | 1С | SQL | Python | C# / Java |
|---|---|---|---|---|
| Назначение | учётные приложения на платформе | выборка и изменение данных | универсальный | универсальный |
| Запуск вне платформы | нет | в любой СУБД | да | да |
| Типизация | динамическая | схема таблиц | динамическая | статическая |
| ООП со своими классами | нет | нет | да | да |
| Язык запросов | встроенный, свой | это и есть язык запросов | через библиотеки | через ORM или SQL |
| Интерфейс | форма собирается в конструкторе | нет | через библиотеки | через фреймворки |
Главное отличие от SQL: язык запросов 1С только читает данные. Изменять их нужно объектами: создать документ
, заполнить реквизиты, записать. Операторов INSERT, UPDATE и DELETE в нём нет.
Главное отличие от универсальных языков: в 1С вы не пишете с нуля слой хранения, слой интерфейса и права доступа . Всё это даёт платформа. Поэтому код короче, но и свободы меньше: вы работаете в рамках, которые задала платформа.
Если вы пришли из Python или C#, привыкать придётся к двум вещам: к контекстам клиента и сервера и к тому, что почти всё делается через объекты метаданных, а не через собственные структуры данных.
Расширения и связь с внешними системами
Типовые конфигурации (Бухгалтерия, ЗУП, УТ) не принято править напрямую: каждая правка осложняет обновление. Для доработок есть расширения конфигурации. Расширение подключается к базе как отдельный объект, может добавлять новые справочники и документы, менять поведение форм и перехватывать вызовы процедур. При обновлении основной конфигурации расширение остаётся нетронутым.
Перехват делают директивами &Перед, &После, &Вместо и &ИзменениеИКонтроль. Можно добавить свой код до вызова типового метода, после него или заменить его целиком.
Для обмена с другими системами в языке есть несколько путей:
- HTTP-сервисы и веб-сервисы. Конфигурация сама публикует интерфейс: другие программы отправляют запросы по HTTP, а 1С отвечает. Подходит для REST-подобных схем и SOAP.
- HTTP-соединение. В обратную сторону: 1С вызывает чужой API через объекты
HTTPСоединениеиHTTPЗапрос. - Обмен файлами. XML и JSON читаются и пишутся встроенными объектами (
ЧтениеJSON,ЗаписьJSON,ЧтениеXML). Это основа обмена между базами и с внешними системами. - COM-соединение. Внешняя программа под Windows может управлять 1С как COM-объектом, и наоборот.
- Внешние компоненты. Для работы с оборудованием и нестандартными задачами подключают компоненты, написанные на других языках, например на C++.
- Прямая работа с СУБД. Возможна, но только для чтения и аналитики. Писать в таблицы базы мимо платформы нельзя: можно сломать целостность данных.
Любая интеграция пишется всё тем же встроенным языком. Другой язык нужен только для внешних компонент.
Версия 8.3 и куда движется язык
Современная ветка платформы — 8.3. Язык в ней не переписывали, но он постепенно получает новые возможности: работа с JSON, HTTP, строки и форматирование, асинхронные вызовы на клиенте, новые объекты для работы с интерфейсом. Старый код продолжает работать, потому что фирма 1С сохраняет обратную совместимость.
Для разработки сегодня есть два инструмента:
- 🛠 Конфигуратор — привычная среда с отладчиком, синтаксис-помощником и конструктором запросов. Исторически основной инструмент.
- 💻 1C:Enterprise Development Tools (EDT) — среда на основе Eclipse. Она работает с конфигурацией как с набором файлов, поддерживает систему контроля версий и подсказки по коду.
Если вы собираетесь изучать язык, начать можно с учебной версии платформы и типовой конфигурации. Прежде чем писать код, откройте любой модуль в Конфигураторе и прочитайте его: типовые модули хороший учебник по тому, как принято писать.
А вот чему стоит научиться в первую очередь, чтобы не набить шишек:
- ✅ разделять клиентский и серверный код;
- ✅ писать запросы с параметрами, а не со склейкой строк;
- ✅ пользоваться отладчиком вместо вывода сообщений;
- ✅ не править типовую конфигурацию без необходимости.