Разбираем код 1С 8.3: модули, объекты, запросы и отладка
Содержание
Чтобы понять код 1С, читайте его не сверху вниз, а от точки входа: найдите процедуру-обработчик, которую вызывает система (ПриПроведении, ПриСозданииНаСервере, команда формы), и двигайтесь по вызовам внутрь. Встроенный язык 1С похож на русский Паскаль: ключевые слова на русском, строки через // — комментарии, точка с запятой завершает оператор. Главная сложность не в синтаксисе, а в том, чтобы понять, где исполняется строка — на клиенте или на сервере — и откуда система дёргает этот код.
Распространённое заблуждение новичка: «весь код лежит в одном месте, как в обычной программе». На деле код 1С разбросан по десяткам модулей, привязанных к объектам конфигурации, и запускается событиями. Поэтому сначала учатся ориентироваться в структуре, а уже потом — в строках.
Где физически лежит код и когда он запускается
Код в 1С живёт не в файлах, а в модулях — текстовых контейнерах внутри конфигурации. Открываются они из дерева конфигурации в Конфигураторе или в 1С:EDT. Основные типы модулей:
- 🧩 Модуль объекта (справочника, документа) — логика конкретного объекта:
ПриЗаписи,ПриПроведении,ОбработкаПроверкиЗаполнения. - 📄 Модуль формы — поведение открытой формы: обработчики кнопок, событий полей,
ПриОткрытии. - 🗂 Модуль менеджера — методы, общие для всех объектов вида (например, генерация номеров, печатные формы).
- 🌍 Общие модули — переиспользуемый код без привязки к объекту. Именно сюда выносят библиотечные функции.
- 🚀 Модуль приложения (управляемого и обычного), модуль сеанса — запускаются при старте, управляют инициализацией.
Чтобы быстро найти, откуда взялась процедура, в Конфигураторе удобна команда перехода к определению: установите курсор на имя метода и нажмите F12 — редактор откроет тело процедуры, даже если она в другом модуле.
Если видите имя процедуры с припиской Экспорт — её можно вызывать снаружи, из других модулей. Без Экспорт метод доступен только внутри своего модуля.
Запускается код по событиям. Пользователь нажал «Провести» — платформа вызвала ПередЗаписью, затем ПриЗаписи, затем ПриПроведении. Открыл форму — отработали ПриСозданииНаСервере и ПриОткрытии. Понимание этой цепочки событий важнее, чем знание отдельных команд: читая код, вы всегда спрашиваете «какое событие сюда привело».
Клиент и сервер: директивы компиляции
Самая частая причина «не могу понять, почему код не работает так, как читается» — незнание, где он исполняется. Над каждой процедурой в модуле формы стоит директива компиляции:
| Директива | Где исполняется | Есть ли доступ к данным |
|---|---|---|
&НаКлиенте | на компьютере пользователя | нет прямого чтения из базы |
&НаСервере | на сервере, с контекстом формы | да, с реквизитами формы |
&НаСервереБезКонтекста | на сервере, без данных формы | да, быстрее и легче |
&НаКлиентеНаСервереБезКонтекста | и там, и там | нет |
Клиентский код не умеет напрямую обращаться к базе данных — ему нужно «сходить на сервер». Поэтому типичный шаблон выглядит так: кнопка на клиенте вызывает серверную процедуру, та читает данные и возвращает результат обратно.
&НаКлиенте
Процедура ОбновитьОстаток(Команда)
Остаток = ПолучитьОстатокНаСервере(Номенклатура);
Сообщить("Остаток: " + Остаток);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьОстатокНаСервере(Номенклатура)
// здесь можно работать с базой
Возврат 0;
КонецФункции
Если не понять границу клиент/сервер, весь остальной код будет читаться неправильно. Начинайте разбор формы именно с директив.
Синтаксис и типы данных: из чего собран код
Синтаксис встроенного языка компактный. Вот минимум, без которого текст не читается:
- Переменные объявлять заранее не обязательно — тип определяется при присваивании.
- Комментарий — всё после
//до конца строки. - Процедура ничего не возвращает, Функция возвращает значение через
Возврат. - Конструкции ветвления и циклов:
Если … Тогда … Иначе … КонецЕсли,Для … По … Цикл … КонецЦикла,Для Каждого … Из … Цикл,Пока … Цикл.
Типы данных делятся на три группы:
- Примитивные:
Число,Строка,Булево,Дата, а такжеНеопределено,NULLиТип. - Ссылочные: ссылки на объекты базы —
СправочникСсылка.Контрагенты,ДокументСсылка.РеализацияТоваровУслуг. Ссылка — это «адрес» записи, а не сама запись. - Универсальные коллекции:
Массив,Структура,Соответствие,СписокЗначений,ТаблицаЗначений,ДеревоЗначений.
Коллекции встречаются в коде постоянно, поэтому различайте их:
| Коллекция | Чем ищем элемент | Когда применяют |
|---|---|---|
Массив | по индексу (с нуля) | простой список значений |
Структура | по имени ключа (идентификатор) | набор именованных полей |
Соответствие | по любому ключу-значению | справочник «ключ → значение» |
ТаблицаЗначений | по строкам и колонкам | данные в виде таблицы |
// Структура: ключ — это имя, его видно в коде
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Организация", ТекущаяОрганизация);
ПараметрыОтбора.Вставить("Период", ТекущаяДата());
// Массив: доступ по индексу, первый элемент — нулевой
Список = Новый Массив;
Список.Добавить("Первый");
Сообщить(Список[0]); // выведет: Первый
В коллекциях 1С индексация начинается с нуля, а не с единицы. Массив[0] — первый элемент. Это частый источник ошибок при чтении чужого кода.
Объектная модель: как код достаёт и меняет данные
Чтобы читать прикладной код, держите в голове тройку «менеджер → ссылка → объект». Это ядро объектной модели 1С.
- Менеджер — точка входа к данным вида:
Справочники.Контрагенты,Документы.РеализацияТоваровУслуг. Через него ищут и создают записи. - Ссылка — указатель на конкретную запись. По ссылке можно читать реквизиты, но нельзя менять.
- Объект — «живая» запись, полученная через
.ПолучитьОбъект(). Только объект можно изменить и записать.
// Нашли ссылку через менеджер
Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("Ромашка");
Если Не Контрагент.Пустая() Тогда
// Чтобы менять — получаем объект
ОбъектКонтрагент = Контрагент.ПолучитьОбъект();
ОбъектКонтрагент.Комментарий = "Проверен";
ОбъектКонтрагент.Записать();
КонецЕсли;
Когда видите в коде .Пустая() — это проверка «ссылка ни на что не указывает» (запись не найдена). Метод НайтиПоНаименованию или НайтиПоКоду возвращает именно ссылку, поэтому проверка на пустоту обязательна.
Отдельно читаются табличные части документов — это строки спецификации (товары, услуги). Перебор строк табличной части — один из самых частых циклов в коде:
Для Каждого СтрокаТовара Из Документ.Товары Цикл
Сумма = Сумма + СтрокаТовара.Количество * СтрокаТовара.Цена;
КонецЦикла;
Запись объекта (.Записать()) в рабочей базе запускает всю его бизнес-логику: обработчики событий, проведение, движения по регистрам. Поэтому строка Записать() в чужом коде — не мелочь: за ней может стоять каскад действий.
Язык запросов внутри кода
Большие объёмы данных в 1С читают не циклами по базе, а языком запросов. Это отдельный язык внутри встроенного — похож на SQL, но с русскими словами и своими возможностями под учётные регистры.
Типовой блок с запросом состоит из трёх шагов: создать запрос, задать текст и параметры, выполнить и обойти результат.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Номенклатура);
КонецЦикла;
Что здесь важно для чтения:
- Символ
|в начале строк — это продолжение строкового литерала, а не часть запроса. Так в коде оформляют многострочный текст. &Ссылка— параметр запроса, его значение подставляют черезУстановитьПараметр. Параметры всегда начинаются с&.КАКзадаёт псевдоним колонки, по которому к ней обращаются в выборке.
Отдельная тема — виртуальные таблицы регистров: РегистрНакопления.ТоварыНаСкладах.Остатки(...), .Обороты(...), .ОстаткиИОбороты(...). Это не физические таблицы базы — платформа рассчитывает остатки и обороты на лету. Если в тексте запроса встретилось .Остатки, значит код достаёт текущие остатки регистра, а не перебирает все движения вручную.
Когда видите длинный запрос с ПОМЕСТИТЬ ВременнаяТаблица — это пакетный запрос: сначала собирают промежуточные данные во временную таблицу, потом используют её в следующем запросе пакета. Читается он сверху вниз по частям.
Отладка: как увидеть, что код делает на самом деле
Самый надёжный способ понять незнакомый код — не читать его, а выполнить по шагам в отладчике. Отладчик встроен в Конфигуратор и в 1С:EDT.
- Поставьте точку останова — щёлкните на левом поле нужной строки или нажмите
F9. Строка отметится кружком. - Запустите 1С:Предприятие в режиме отладки (из Конфигуратора — зелёная стрелка «Начать отладку»,
F5). - Выполните в программе действие, которое приводит к этому коду (проведите документ, нажмите кнопку). Выполнение остановится на точке.
- Дальше шагайте:
F11— зайти внутрь вызываемой процедуры,F10— выполнить строку не заходя внутрь,F5— продолжить до следующей точки.
Пока выполнение на паузе, значения переменных смотрят так:
- Наведите курсор на переменную — всплывёт её текущее значение.
- Табло — закрепите нужные переменные, чтобы видеть их постоянно.
- Вычислить выражение (
Shift+F9) — посчитайте любое выражение в текущем контексте, разверните структуры и таблицы значений.
Чтобы отладка на сервере работала, в параметрах информационной базы должна быть включена отладка (пункт «Отладка разрешена»). Для клиент-серверного варианта отладку сервера настраивают отдельно. Без этого точки останова в серверных процедурах не сработают.
Ещё один инструмент — замер производительности в Конфигураторе: он показывает, сколько раз выполнилась каждая строка и сколько заняла. Полезно, когда нужно понять не логику, а «где код тормозит».
Что сбивает с толку новичков
Несколько особенностей, из-за которых код 1С читается неправильно, даже когда синтаксис понятен:
- 🔀 Код не линейный. Исполнение прыгает между клиентом и сервером, между модулями формы и объекта. Читать «подряд» бесполезно — идите по событиям и вызовам.
- 0️⃣ Индексы с нуля. Первый элемент массива —
[0], последний —[Массив.ВГраница()]или[Массив.Количество() - 1]. - 🧷 Ссылка ≠ объект. По ссылке читают, объект (
.ПолучитьОбъект()) меняют. Путаница здесь ломает понимание всей логики записи. - 📦 Невидимая бизнес-логика. Одна строка
Записать()илиПровести()запускает обработчики, проверки и движения по регистрам, которых в этом модуле не видно. - 🧵 Процедуры-обёртки. Часто вызов из формы ведёт в общий модуль, а оттуда — в ещё один. Не пугайтесь глубины:
F12проведёт по цепочке.
Отдельно про запросы: символ | в начале строк и параметры с & новички принимают за ошибки или «мусор». Это штатное оформление многострочного текста запроса.
Где искать значение команды и документацию
Когда непонятна конкретная команда или метод, не угадывайте — смотрите справку. Основные источники:
- 📘 Синтакс-помощник — встроенный справочник по всем объектам и методам языка. Открывается в Конфигураторе и EDT из меню
Справка. Поставьте курсор на имя метода в коде и вызовите контекстную подсказку — откроется описание с параметрами и примером. - ⌨️ Контекстная подсказка редактора. Начните печатать имя объекта и поставьте точку — редактор предложит доступные свойства и методы. Это помогает понять, что за объект перед вами.
- 🔎 Глобальный поиск по конфигурации. Чтобы найти, откуда вызывается процедура или где используется реквизит, ищите по всей конфигурации (поиск ссылок на объект, поиск по тексту модулей).
- 🧭 Переход к определению (
F12) и список вызывающих процедур — чтобы пройти по цепочке вызовов, не теряя нить.
Для прикладных методов конкретной конфигурации (БСП — Библиотека стандартных подсистем) описание обычно лежит в комментарии над самой процедурой: разработчики библиотеки подробно документируют параметры прямо в коде. Поэтому, встретив вызов библиотечного метода, сначала перейдите к нему через F12 и прочитайте шапку.
Нужно ли знать программирование, чтобы читать код 1С?
Чем язык запросов отличается от встроенного языка?
Выполнить() и обходят результат циклом.Почему код в модуле формы «не видит» базу данных?
&НаКлиенте) исполняются на компьютере пользователя и не имеют прямого доступа к базе. Чтение данных выносят в серверные процедуры (&НаСервере, &НаСервереБезКонтекста).