Встроенный язык 1С 8.3 на практике: от первой строки до рабочего кода
Содержание
Команды в 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;
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Режимы записи: Запись — просто сохранить, Проведение — сохранить и провести, ОтменаПроведения — отменить проведение. Имена документа, табличной части и реквизитов здесь условные — в типовых конфигурациях они свои.
Движения в модуле проведения
Движения формируются в процедуре ОбработкаПроведения модуля объекта документа. Пример для регистра накопления с видом «Остатки»:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого Стр Из Товары Цикл
Движение = Движения.ОстаткиТоваров.ДобавитьПриход();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = Стр.Номенклатура;
Движение.Количество = Стр.Количество;
КонецЦикла;
КонецПроцедуры
Чтобы отказаться от проведения, установите Отказ = Истина и выведите пользователю причину.
Чтение регистров
Остатки и обороты берут из виртуальных таблиц, а не из физической таблицы регистра:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Остатки(&Дата, Склад = &Склад) КАК Остатки");
Запрос.УстановитьПараметр("Дата", ТекущаяДатаСеанса());
Запрос.УстановитьПараметр("Склад", Склад);
Условие пишите в параметрах виртуальной таблицы, как выше, а не в ГДЕ. Так платформа отбирает данные до расчёта остатков. Для периодических регистров сведений есть таблица СрезПоследних — актуальное значение на дату, например последняя цена.
Отладка и обработка ошибок: команды для диагностики
Отладчик
- Поставьте точку останова на нужной строке клавишей
F9. - Запустите отладку из Конфигуратора клавишей
F5или через менюОтладка. - Когда выполнение остановится, смотрите значения переменных в табло и окне вычисления выражений.
- Шагайте по коду:
F10— без захода в методы,F11— с заходом.
Для серверного кода в клиент-серверной базе нужно запустить агент сервера (ragent) с ключом -debug. Без этого точки останова в серверных методах не срабатывают.
Если код «тормозит», включите замер производительности в меню Отладка. Он покажет, сколько времени заняла каждая строка и сколько раз она выполнилась.
Перехват исключений
Попытка
Объект.Записать();
Исключение
Текст = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Загрузка.Контрагенты",
УровеньЖурналаРегистрации.Ошибка, , , Текст);
ВызватьИсключение;
КонецПопытки;
Пустой блок Исключение … КонецПопытки прячет ошибку: данные не записались, а пользователь об этом не знает. Минимум — запишите текст в журнал регистрации. ВызватьИсключение без параметров пробрасывает исходную ошибку дальше.
Быстрый вывод в окно сообщений даёт Сообщить(). В конфигурациях на БСП принято вызывать ОбщегоНазначения.СообщитьПользователю — он умеет подсветить поле формы с ошибкой.
Как писать команды 1С, чтобы код работал быстро
Медленный код в 1С почти всегда выглядит одинаково. Три приёма закрывают основную часть проблем.
Не выполняйте запрос в цикле
Плохо — запрос на каждую строку:
Для Каждого Стр Из Товары Цикл
Цена = ПолучитьЦенуЗапросом(Стр.Номенклатура); // 1000 строк = 1000 запросов
КонецЦикла;
Хорошо — один запрос на весь список, результат в соответствии:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Цены.Номенклатура,
| Цены.Цена
|ИЗ
| РегистрСведений.ЦеныТоваров.СрезПоследних(, Номенклатура В (&Список)) КАК Цены");
Запрос.УстановитьПараметр("Список", Товары.ВыгрузитьКолонку("Номенклатура"));
Цены = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Цены.Вставить(Выборка.Номенклатура, Выборка.Цена);
КонецЦикла;
Для Каждого Стр Из Товары Цикл
Стр.Цена = Цены.Получить(Стр.Номенклатура);
КонецЦикла;
Следите за точками
Запись Документ.Контрагент.ИНН в коде выглядит невинно. На деле каждая точка после ссылки — это чтение объекта из базы целиком. В цикле на тысячу строк это тысячи лишних обращений. Нужные поля получайте сразу в запросе.
Выбирайте только нужное
- 📌 Не пишите
ВЫБРАТЬ *— перечисляйте поля. - 📌 Сложные запросы разбивайте на пакет с временными таблицами (
ПОМЕСТИТЬ). - 📌 Не держите транзакцию открытой во время диалога с пользователем или долгих расчётов.
- 📌 Не вызывайте сервер из клиентского цикла: соберите данные и сделайте один серверный вызов.
Типичные ошибки при написании команд: тексты и причины
Эти сообщения платформа выдаёт чаще всего. Выберите своё — увидите причину и решение.
Ещё три ошибки не дают сообщения, но портят результат:
- 🐞 Сравнение дат без учёта времени.
ТекущаяДатаСеанса()содержит часы и минуты. Для сравнения по дню используйтеНачалоДня()иКонецДня(). - 🐞 Склейка числа со строкой.
"Счёт № " + 12345даст12 345с неразрывным пробелом. ПишитеФормат(Номер, "ЧГ=0")илиСтрШаблон("Счёт № %1", Формат(Номер, "ЧГ=0")). - 🐞 Деление на ноль в расчётах. Перед делением проверяйте знаменатель:
Если Количество <> 0 Тогда.
Команды формы и автоматизация рутинных задач
В 1С слово «команда» имеет и второй смысл — это кнопка на форме или в командном интерфейсе. Добавляется она так:
- Откройте форму в редакторе и перейдите на вкладку Команды.
- Добавьте новую команду, задайте имя и заголовок.
- В свойстве Действие нажмите на лупу — платформа создаст пустой обработчик в модуле формы.
- Перетащите команду из списка в дерево элементов формы — появится кнопка.
Обработчик создаётся на клиенте. Работу с базой выносите в серверный метод:
&НаКлиенте
Процедура ЗаполнитьЦены(Команда)
ЗаполнитьЦеныНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьЦеныНаСервере()
// запрос к регистру цен и заполнение табличной части
КонецПроцедуры
Где писать код, не трогая типовую конфигурацию
| Инструмент | Для чего | Обновление типовой |
|---|---|---|
Внешняя обработка (.epf) | разовые и периодические операции | не мешает |
Расширение конфигурации (.cfe) | доработка форм, модулей, новых команд | обычно переживает, но проверяйте после обновления |
| Правка самой конфигурации | глубокие изменения | усложняет каждое обновление |
Расширения появились в платформе 8.3.6. Для автоматической работы по расписанию служат регламентные задания: создаёте объект в ветке Общие дерева метаданных и указываете экспортный метод серверного общего модуля. Так обычно автоматизируют загрузку курсов, выгрузку на сайт, ночные проверки.
Для отладки запросов без программирования формы используйте консоль запросов — внешнюю обработку, которая выполняет текст запроса и показывает результат таблицей.