Урок 7 из 8 · 25 мин · обновлено

Встроенный язык и запросы

Основы встроенного языка 1С: переменные, условия, циклы, процедуры и функции, виды модулей, клиент и сервер. Язык запросов — родственник SQL: ВЫБРАТЬ, ИЗ, ГДЕ, параметры и виртуальные таблицы. Запрещаем продавать товар, которого нет на складе.

Язык на русском

Встроенный язык 1С похож на другие языки программирования, только ключевые слова русские. Есть и английские синонимы — If, Then, EndIf, — но в российских компаниях почти везде пишут по-русски.

1С
// Переменные создаются присваиванием
Цена = 1500;
Количество = 3;
Сумма = Цена * Количество;

// Условие
Если Сумма > 10000 Тогда
	Скидка = 5;
ИначеЕсли Сумма > 3000 Тогда
	Скидка = 3;
Иначе
	Скидка = 0;
КонецЕсли;

// Цикл со счётчиком
Для Номер = 1 По 3 Цикл
	Сообщить("Строка " + Номер);
КонецЦикла;

Сообщить("Сумма со скидкой: " + Сумма * (100 - Скидка) / 100);

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

Код собирают в процедуры и функции. Функция возвращает значение:

1С
Функция СуммаСоСкидкой(Сумма, Скидка)
	Возврат Сумма * (100 - Скидка) / 100;
КонецФункции

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

Где живёт код

Код в 1С не лежит в отдельных файлах, а привязан к объектам — в модулях:

  • модуль объекта — поведение конкретного документа или элемента справочника: проведение, проверки при записи;
  • модуль формы — реакция на действия пользователя в окне: нажал кнопку, выбрал товар;
  • модуль менеджера — действия с объектами одного вида в целом: например, печать;
  • общие модули — процедуры, которые нужны в разных местах конфигурации.

Клиент и сервер

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

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

&НаСервере
Процедура ПересчитатьНаСервере()
	// здесь можно читать данные из базы
КонецПроцедуры

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

Язык запросов

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

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

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

Что здесь происходит:

  • ВЫБРАТЬ … ИЗ … УПОРЯДОЧИТЬ ПО — как SELECT … FROM … ORDER BY в SQL;
  • ОстаткиТоваров.Остатки — виртуальная таблица остатков из прошлого урока; в скобках её параметры: дата не указана — значит, текущие остатки, и отбор по складу;
  • &Склад — параметр: значение передаётся отдельно методом УстановитьПараметр;
  • текст запроса многострочный: каждая новая строка начинается с |;
  • Пока Выборка.Следующий() Цикл перебирает строки результата.

Ещё одна особенность — обращение через точку: Остатки.Товар.Артикул достанет артикул товара без явного соединения таблиц. Удобно, но в больших запросах этим не злоупотребляют: каждая точка — скрытое соединение.

Писать запросы вручную с нуля не нужно: в Конфигураторе есть конструктор запроса, где таблицы и поля выбирают мышкой. Но читать и править текст запроса разработчик должен уверенно. Если вы проходили курс «SQL с нуля», половина языка запросов вам уже знакома.

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

Решение

В модуле объекта документа РасходТовара после цикла с движениями добавьте:

1С
	// записываем движения сейчас, чтобы проверить остатки с их учётом
	Движения.ОстаткиТоваров.Записать();

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

	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Сообщить("Не хватает товара «" + Выборка.Товар + "»: " + (-Выборка.Остаток) + " шт.");
		Отказ = Истина;
	КонецЦикла;

Проверьте: проведите расход больше остатка — документ не проведётся, а внизу окна появится сообщение. При отказе платформа отменит и уже записанные движения.

Это упрощённая проверка: она смотрит на текущие остатки, а не на остатки в момент документа. В настоящих конфигурациях учитывают и дату документа, и одновременную работу нескольких пользователей — этому учат в полноценных курсах.

Мини-тест: проверьте себя

Закрепите урок: несколько вопросов, разбор ответов — в конце.

  1. Что выведет код: Сумма = 0; Для Н = 1 По 3 Цикл Сумма = Сумма + Н; КонецЦикла; Сообщить(Сумма);

  2. Зачем в запросе писать ГДЕ Остатки.Склад = &Склад, а не вставлять название склада в текст?

  3. Чем язык запросов 1С отличается от SQL?

  4. В каком модуле лучше писать код, который нужен в нескольких документах сразу?