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

· 9 мин

Содержание

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

Разберём по порядку: общий модуль, модуль объекта, модуль формы и модуль менеджера. У каждого своё назначение, свой набор событий и свои правила компиляции. Плюс покажу, как добавить код в типовую конфигурацию , не ломая обновления, и как потом всё отладить.

Перед работой откройте конфигурацию в режиме редактирования: меню Конфигурация → Открыть конфигурацию. Если это типовая конфигурация на поддержке — об этом ниже отдельный раздел.

Как устроены модули в дереве конфигурации

Модуль — это контейнер для процедур и функций. Разные модули компилируются в разном контексте, поэтому код из одного не всегда виден в другом. Основные виды:

  • 🗂 Общий модуль — переиспользуемые процедуры и функции, не привязанные к конкретному объекту.
  • 📄 Модуль объекта — логика конкретного справочника, документа, регистра: что делать при записи, проведении, удалении.
  • 🖥 Модуль формы — обработка действий пользователя: нажал кнопку, изменил поле, открыл форму.
  • ⚙️ Модуль менеджера — методы уровня объекта в целом (не отдельного элемента), печать, выбор данных.
  • 🌐 Модуль приложения (управляемого и обычного), модуль сеанса, модуль внешнего соединения — запуск системы, старт сеанса, работа через COM.

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

ЗадачаКуда писать код
Общий расчёт, вызываемый из многих местОбщий модуль
Проверка и движения при записи документаМодуль объекта
Реакция на действия пользователя в формеМодуль формы
Метод «на весь справочник», печатьМодуль менеджера
Код при старте программыМодуль приложения
Куда положить новый код?

Как создать общий модуль и настроить флаги

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

  1. В дереве конфигурации раскройте ветку Общие → Общие модули.
  2. Правой кнопкой → Добавить. Задайте имя латиницей без пробелов, например РаботаСКонтрагентами.
  3. Откройте палитру свойств (если не видна — Правка → Свойства или клавиша F4) и настройте флаги.

Ключевые свойства общего модуля:

  • Флаги контекста компиляции: Сервер, Клиент (управляемое приложение), Клиент (обычное приложение), Внешнее соединение. Отмечаете те контексты, где модуль должен быть доступен. Для серверной бизнес-логики обычно хватает одного флага Сервер.
  • Вызов сервера — разрешает вызывать экспортные процедуры серверного модуля прямо с клиента. Без этого флага обращение с клиента вызовет ошибку компиляции.
  • Привилегированный — код исполняется без контроля прав доступа. Включайте осознанно: привилегированный модуль видит все данные в обход ролей.
  • Повторное использование возвращаемых значений — На время вызова, На время сеанса или Не использовать. Кэширует результат функции, чтобы не считать одно и то же дважды. Подходит только для функций, которые для одинаковых параметров всегда возвращают один результат.
  • Глобальный — экспортные методы вызываются без указания имени модуля. Увеличивает время запуска, поэтому глобальных модулей держат минимум.

Простой пример экспортной функции в серверном общем модуле:

Функция ПолноеИмя(Фамилия, Имя, Отчество = "") Экспорт
    Результат = СокрЛП(Фамилия) + " " + СокрЛП(Имя);
    Если НЕ ПустаяСтрока(Отчество) Тогда
        Результат = Результат + " " + СокрЛП(Отчество);
    КонецЕсли;
    Возврат Результат;
КонецФункции

Ключевое слово Экспорт делает метод видимым снаружи. Вызов из другого модуля: РаботаСКонтрагентами.ПолноеИмя(Фам, Имя). Без Экспорт функция доступна только внутри своего модуля.

Не смешивайте в одном модуле клиентский и серверный код без необходимости. Если на модуле стоят оба флага, компилятор потребует указывать директивы у каждой процедуры.

Код в модуле объекта: события справочника и документа

Модуль объекта содержит логику конкретного прикладного объекта. Он компилируется на сервере и реагирует на предопределённые события жизненного цикла.

Чтобы открыть модуль : двойным кликом по объекту (например, документу) в дереве конфигурации, затем вкладка (или пункт контекстного меню) Открыть модуль объекта.

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

  • ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) — проверка перед записью.
  • ПередЗаписью(Отказ) — последняя возможность отменить запись или дозаполнить реквизиты.
  • ПриЗаписи(Отказ) — после записи объекта, но внутри той же транзакции.
  • ОбработкаПроведения(Отказ, РежимПроведения) — только у документов: формирование движений по регистрам.
  • ПередУдалением(Отказ) — контроль перед удалением.

Если установить Отказ = Истина, операция прерывается — удобно для контроля данных. Пример проверки заполнения с корректным сообщением, привязанным к реквизиту:

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

А так документ формирует движения по регистру накопления при проведении (имена регистра и табличной части — для примера, в вашей конфигурации они свои):

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

Внутри модуля объекта текущий объект доступен как ЭтотОбъект, а его реквизиты — напрямую по имени (Контрагент, Дата, Товары).

Модуль формы: директивы компиляции и клиентская логика

Форма — это то, что видит пользователь. Её модуль управляет поведением интерфейса и в отличие от модуля объекта работает в двух контекстах сразу — на клиенте и на сервере. Поэтому у каждой процедуры обязательна директива компиляции.

Основные директивы управляемой формы:

  • &НаКлиенте — исполняется на клиенте, имеет доступ к элементам формы и интерактивным методам.
  • &НаСервере — исполняется на сервере, имеет доступ к базе; получает реквизиты формы, но не её элементы.
  • &НаСервереБезКонтекста — то же, но без передачи данных формы на сервер и обратно. Самый быстрый серверный вызов, потому что не «таскает» контекст формы по сети.
  • &НаКлиентеНаСервереБезКонтекста — процедура доступна в обоих контекстах (например, общая проверка).

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

&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
    СтрокаТовары = Элементы.Товары.ТекущиеДанные;
    СтрокаТовары.Сумма = СтрокаТовары.Количество * СтрокаТовары.Цена;
КонецПроцедуры

Частые события формы: ПриСозданииНаСервере (начальная настройка, исполняется при открытии на сервере), ПриОткрытии (клиент), ПередЗаписью и ПослеЗаписи. Логику подготовки данных держите в серверных процедурах, реакцию на действия пользователя — в клиентских.

С клиента нельзя напрямую обратиться к базе данных. Если из &НаКлиенте-процедуры нужны данные из базы, вызывайте серверную процедуру (&НаСервере или &НаСервереБезКонтекста), а не пытайтесь выполнить запрос на клиенте.

Модуль менеджера и подписки на события

Модуль менеджера хранит методы, которые относятся к объекту в целом, а не к отдельному элементу. Открывается так же, как модуль объекта: контекстное меню объекта → Открыть модуль менеджера. Компилируется на сервере.

Сюда помещают методы, которые логично вызывать «от имени» справочника или документа:

// Модуль менеджера справочника "Контрагенты"
Функция НайтиПоИНН(ИНН) Экспорт
    Возврат Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИНН);
КонецФункции

Экспортный метод вызывается через менеджер объекта: Справочники.Контрагенты.НайтиПоИНН(СтрокаИНН). В модуле менеджера также размещают обработчик ОбработкаПолученияДанныхВыбора и команды печати.

Отдельный приём, которого нет в наивной инструкции, — подписки на события. Они позволяют вынести код из модуля объекта в общий модуль, не трогая сам объект. Это важно, когда нужно повесить обработку на типовой документ.

  1. Создайте экспортную процедуру в неглобальном серверном общем модуле. Её параметры должны совпадать с сигнатурой события.
  2. В дереве конфигурации: Общие → Подписки на события → Добавить.
  3. Укажите Источник (тип или набор типов), Событие (например, ПередЗаписью) и Обработчик (вашу процедуру).

Так один общий модуль обслуживает событие сразу у многих объектов, а логика собрана в одном месте.

Расширения конфигурации: код без снятия с поддержки

Если вы дорабатываете типовую конфигурацию (БП 3.0, ЗУП 3.1, УТ 11), просто так в её модули писать нельзя — она на поддержке поставщика. Есть два пути.

Снятие с поддержки (Конфигурация → Поддержка → Настройка поддержки) снимает замок редактирования, но тогда автоматическое обновление усложняется: типовые релизы придётся сверять вручную. Для небольших доработок это неоправданно.

Расширение конфигурации — правильный современный способ (доступен с платформы 8.3.6). Расширение хранит ваши изменения отдельным файлом и накладывается на типовую конфигурацию, не изменяя её. Обновления типовой при этом продолжают ставиться штатно.

  1. Меню Конфигурация → Расширения конфигурации, добавьте новое расширение, задайте имя и префикс.
  2. Переключитесь на дерево расширения и добавляйте свои общие модули, формы, а к заимствованным объектам — обработчики через аннотации &Перед, &После, &Вместо.
  3. Загрузите расширение (.cfe) и обновите конфигурацию базы данных — это два отдельных шага.

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

Как отладить и проверить написанный код

Написать код мало — его нужно проверить. В Конфигураторе для этого есть встроенный отладчик.

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

Пошаговая отладка:

  1. Поставьте точку останова на нужной строке — клавиша F9 или клик на серой полосе слева от кода.
  2. Запустите 1С:Предприятие в режиме отладки — клавиша F5. Когда исполнение дойдёт до точки, оно остановится.
  3. Двигайтесь по коду: F11 — шагнуть внутрь процедуры, F10 — выполнить строку не заходя внутрь, Shift+F11 — выйти из текущей процедуры.
  4. Смотрите значения переменных в окне Табло, а разовые выражения вычисляйте через Отладка → Вычислить выражение (Shift+F9).

Для файловой базы отладка подключается автоматически. Для клиент-серверной базы отладку по протоколу нужно разрешить в параметрах информационной базы (флаг разрешения отладки), а в Конфигураторе выбрать предмет отладки через меню Отладка → Подключение.

Полезно и измерение производительности: Отладка → Замер производительности покажет, какие строки кода выполняются дольше всего, — удобно искать медленные запросы в цикле.

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

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

Чем модуль объекта отличается от модуля менеджера?
Модуль объекта работает с конкретным элементом (эта запись справочника, этот документ) и реагирует на события его жизненного цикла. Модуль менеджера содержит методы уровня объекта в целом — например, «найти элемент по реквизиту» или «сформировать печатную форму».
Почему процедура из общего модуля не вызывается с клиента?
Скорее всего, у модуля не установлен флаг «Вызов сервера» либо у него нет клиентского контекста. Проверьте флаги компиляции в свойствах модуля и наличие ключевого слова Экспорт у процедуры.
Что означает директива &НаСервереБезКонтекста?
Процедура исполняется на сервере, но данные формы на сервер не передаются. Это самый лёгкий серверный вызов: нет накладных расходов на пересылку контекста формы. Подходит, когда внутри не нужны реквизиты и элементы формы.
Как добавить обработчик события, не меняя типовой объект?
Через подписку на событие: пишете экспортную процедуру в серверном общем модуле и регистрируете её в ветке Общие → Подписки на событие. Либо используете расширение конфигурации с аннотациями &Перед, &После, &Вместо.
Зачем нужен флаг «Повторное использование возвращаемых значений»?
Он кэширует результат функции, чтобы при повторном вызове с теми же параметрами не выполнять расчёт заново. Включайте только для функций, которые для одинаковых аргументов всегда дают один результат, иначе получите устаревшие данные.