Встроенный язык 1С 8.3 на практике: от первой строки до рабочего кода

· 10 мин

Содержание

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

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

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

Встроенный язык 1С похож на Pascal и Basic, но со своими привычками. Запомните базовый набор правил:

  • ✏️ Точка с запятой разделяет операторы. Перед КонецЕсли, КонецЦикла её можно не ставить, но лучше ставить всегда — так меньше путаницы.
  • 🔤 Регистр не важен: Сообщить, сообщить и СООБЩИТЬ — одно и то же. Принято писать с заглавной буквы каждое слово.
  • 💬 Комментарий начинается с // и идёт до конца строки. Многострочных комментариев нет.
  • 🌐 Два языка: у каждого слова есть английский вариант (Если = If, Цикл = Do). Смешивать можно, но в одной конфигурации лучше держаться одного.
  • 📝 Строки — в двойных кавычках. Многострочная строка продолжается символом | в начале следующей строки.
  • 📅 Даты — в одинарных кавычках: '20260101' или '20260101120000'.

Основные конструкции:

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

// Цикл со счётчиком
Для Сч = 1 По 10 Цикл
	Итог = Итог + Сч;
КонецЦикла;

// Обход коллекции
Для Каждого Элемент Из МассивСумм Цикл
	Итог = Итог + Элемент;
КонецЦикла;

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

Процедура ничего не возвращает, функция возвращает значение через Возврат:

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

Слово Экспорт открывает метод для вызова из других модулей. Параметр со значением по умолчанию (Ставка = 20) можно не передавать.

Директивы компиляции

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

ДирективаГде выполняетсяДоступ к базе
&НаКлиентена компьютере пользователянет
&НаСерверена сервере, с передачей данных формыда
&НаСервереБезКонтекстана сервере, без данных формыда

Если метод на сервере не использует реквизиты формы, ставьте &НаСервереБезКонтекста. На сервер не уходит вся форма, вызов заметно легче.

Как писать команды для чтения, создания и изменения данных

Данные в 1С читают запросом, а меняют через объект. Это разные механизмы, и путать их не стоит.

Выборка данных запросом

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

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

Значения в запрос передавайте только через УстановитьПараметр. Склеивать текст запроса со строкой из поля ввода нельзя: сломается на кавычке и откроет дорогу ошибкам.

Текст запроса удобно собирать не вручную, а в Конструкторе запроса: щёлкните правой кнопкой внутри строки запроса в модуле и выберите конструктор.

Создание, изменение и удаление

// Новый элемент справочника
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Бумага А4";
НовыйЭлемент.Записать();

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

// Пометка на удаление вместо удаления
Объект.УстановитьПометкуУдаления(Истина);

Метод Удалить() у объекта удаляет запись сразу, без контроля ссылок. В рабочей базе используйте пометку на удаление, а сами объекты убирайте штатной обработкой удаления помеченных.

Имена реквизитов (Комментарий и т.п.) зависят от конфигурации. Точный список смотрите в дереве метаданных Конфигуратора.

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

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

КоллекцияКогда братьКлючевые методы
Массивпростой список значенийДобавить, Найти, Количество, Удалить
Структуранесколько именованных полейВставить, Свойство
Соответствиебыстрый поиск по ключуВставить, Получить
ТаблицаЗначенийстроки и колонки, итогиДобавить, Свернуть, НайтиСтроки, Сортировать
// Массив
Склады = Новый Массив;
Склады.Добавить(СкладОсновной);
Склады.Добавить(СкладРозница);

// Структура
Параметры = Новый Структура("Организация, Период", Организация, ТекущаяДатаСеанса());
Если Параметры.Свойство("Период") Тогда
	Сообщить(Формат(Параметры.Период, "ДЛФ=D"));
КонецЕсли;

// Соответствие: ИНН -> контрагент
ПоИНН = Новый Соответствие;
ПоИНН.Вставить("7701234567", Контрагент);
Найденный = ПоИНН.Получить("7701234567");

Таблица значений — главный рабочий инструмент. Например, сложить количество по товарам:

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Товар");
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

Стр = Таблица.Добавить();
Стр.Товар = "Бумага";
Стр.Количество = 3;

Стр = Таблица.Добавить();
Стр.Товар = "Бумага";
Стр.Количество = 2;

Таблица.Свернуть("Товар", "Количество");
// Осталась одна строка: Бумага — 5

Удаление элементов при обходе

Нельзя удалять элементы коллекции внутри цикла Для Каждого — часть элементов будет пропущена. Обходите коллекцию с конца по индексу:

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

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

Команды для работы с документами и регистрами

Создание и проведение документа

ДокОбъект = Документы.ПриходТовара.СоздатьДокумент();
ДокОбъект.Дата = ТекущаяДатаСеанса();
ДокОбъект.Склад = Склад;

СтрокаТЧ = ДокОбъект.Товары.Добавить();
СтрокаТЧ.Номенклатура = Товар;
СтрокаТЧ.Количество = 10;

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Режимы записи: Запись — просто сохранить, Проведение — сохранить и провести, ОтменаПроведения — отменить проведение. Имена документа, табличной части и реквизитов здесь условные — в типовых конфигурациях они свои.

Движения в модуле проведения

Движения формируются в процедуре ОбработкаПроведения модуля объекта документа. Пример для регистра накопления с видом «Остатки»:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	Движения.ОстаткиТоваров.Записывать = Истина;
	Для Каждого Стр Из Товары Цикл
		Движение = Движения.ОстаткиТоваров.ДобавитьПриход();
		Движение.Период = Дата;
		Движение.Склад = Склад;
		Движение.Номенклатура = Стр.Номенклатура;
		Движение.Количество = Стр.Количество;
	КонецЦикла;
КонецПроцедуры

Чтобы отказаться от проведения, установите Отказ = Истина и выведите пользователю причину.

Чтение регистров

Остатки и обороты берут из виртуальных таблиц, а не из физической таблицы регистра:

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

Условие пишите в параметрах виртуальной таблицы, как выше, а не в ГДЕ. Так платформа отбирает данные до расчёта остатков. Для периодических регистров сведений есть таблица СрезПоследних — актуальное значение на дату, например последняя цена.

Отладка и обработка ошибок: команды для диагностики

Отладчик

  1. Поставьте точку останова на нужной строке клавишей F9.
  2. Запустите отладку из Конфигуратора клавишей F5 или через меню Отладка.
  3. Когда выполнение остановится, смотрите значения переменных в табло и окне вычисления выражений.
  4. Шагайте по коду: F10 — без захода в методы, F11 — с заходом.

Для серверного кода в клиент-серверной базе нужно запустить агент сервера (ragent) с ключом -debug. Без этого точки останова в серверных методах не срабатывают.

Если код «тормозит», включите замер производительности в меню Отладка. Он покажет, сколько времени заняла каждая строка и сколько раз она выполнилась.

Перехват исключений

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

Пустой блок Исключение … КонецПопытки прячет ошибку: данные не записались, а пользователь об этом не знает. Минимум — запишите текст в журнал регистрации. ВызватьИсключение без параметров пробрасывает исходную ошибку дальше.

Быстрый вывод в окно сообщений даёт Сообщить(). В конфигурациях на БСП принято вызывать ОбщегоНазначения.СообщитьПользователю — он умеет подсветить поле формы с ошибкой.

Как писать команды 1С, чтобы код работал быстро

Медленный код в 1С почти всегда выглядит одинаково. Три приёма закрывают основную часть проблем.

Не выполняйте запрос в цикле

Плохо — запрос на каждую строку:

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

Хорошо — один запрос на весь список, результат в соответствии:

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

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

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

Следите за точками

Запись Документ.Контрагент.ИНН в коде выглядит невинно. На деле каждая точка после ссылки — это чтение объекта из базы целиком. В цикле на тысячу строк это тысячи лишних обращений. Нужные поля получайте сразу в запросе.

Выбирайте только нужное

  • 📌 Не пишите ВЫБРАТЬ * — перечисляйте поля.
  • 📌 Сложные запросы разбивайте на пакет с временными таблицами (ПОМЕСТИТЬ).
  • 📌 Не держите транзакцию открытой во время диалога с пользователем или долгих расчётов.
  • 📌 Не вызывайте сервер из клиентского цикла: соберите данные и сделайте один серверный вызов.

Типичные ошибки при написании команд: тексты и причины

Эти сообщения платформа выдаёт чаще всего. Выберите своё — увидите причину и решение.

Диагностика: выберите симптом

Ещё три ошибки не дают сообщения, но портят результат:

  • 🐞 Сравнение дат без учёта времени. ТекущаяДатаСеанса() содержит часы и минуты. Для сравнения по дню используйте НачалоДня() и КонецДня().
  • 🐞 Склейка числа со строкой. "Счёт № " + 12345 даст 12 345 с неразрывным пробелом. Пишите Формат(Номер, "ЧГ=0") или СтрШаблон("Счёт № %1", Формат(Номер, "ЧГ=0")).
  • 🐞 Деление на ноль в расчётах. Перед делением проверяйте знаменатель: Если Количество <> 0 Тогда.

Команды формы и автоматизация рутинных задач

В 1С слово «команда» имеет и второй смысл — это кнопка на форме или в командном интерфейсе. Добавляется она так:

  1. Откройте форму в редакторе и перейдите на вкладку Команды.
  2. Добавьте новую команду, задайте имя и заголовок.
  3. В свойстве Действие нажмите на лупу — платформа создаст пустой обработчик в модуле формы.
  4. Перетащите команду из списка в дерево элементов формы — появится кнопка.

Обработчик создаётся на клиенте. Работу с базой выносите в серверный метод:

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

&НаСервере
Процедура ЗаполнитьЦеныНаСервере()
	// запрос к регистру цен и заполнение табличной части
КонецПроцедуры

Где писать код, не трогая типовую конфигурацию

ИнструментДля чегоОбновление типовой
Внешняя обработка (.epf)разовые и периодические операциине мешает
Расширение конфигурации (.cfe)доработка форм, модулей, новых командобычно переживает, но проверяйте после обновления
Правка самой конфигурацииглубокие измененияусложняет каждое обновление

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

Для отладки запросов без программирования формы используйте консоль запросов — внешнюю обработку, которая выполняет текст запроса и показывает результат таблицей.

Перед тем как отдать код в рабочую базу
Выполнено: 0 / 6

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

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