Модули 1С 8.3 на практике: общий, объекта, формы и менеджера

· 10 мин

Содержание

Чтобы создать модуль в 1С 8.3, откройте Конфигуратор, затем Конфигурация → Открыть конфигурацию. Общий модуль добавляют в ветке Общие → Общие модули через контекстное меню Добавить. Модуль объекта, менеджера или формы отдельно не создают: он уже есть у каждого справочника, документа и формы, его нужно только открыть и написать код. После правок нажмите F7 — Обновить конфигурацию базы данных.

Дальше всё решают детали: где выполняется код (клиент или сервер), какие флаги стоят у общего модуля и можно ли вообще править типовую конфигурацию . Ниже — пошаговая инструкция с примерами для управляемого приложения (интерфейс «Такси»). Отличия обычного приложения отмечены отдельно.

Что такое модуль в 1С и где он живёт

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

У модуля три части, и порядок у них строгий:

  1. 📌 Раздел объявления переменных — Перем ИмяПеременной;. Есть в модулях объектов, форм, приложения. В общих модулях переменных уровня модуля нет.
  2. 🧩 Процедуры и функции — основной код.
  3. ▶️ Основная программа — операторы вне процедур. Выполняются при создании экземпляра модуля. В общих модулях этого раздела нет.

Код внутри принято делить областями: #Область ПрограммныйИнтерфейс, #Область ОбработчикиСобытий, #Область СлужебныеПроцедурыИФункции. Платформе они не нужны, но по ним легко найти нужное место в модуле на 3000 строк. Типовые конфигурации написаны именно так.

Процедура видна снаружи модуля только с ключевым словом Экспорт. Без него её можно вызвать лишь внутри того же модуля.

Виды модулей 1С и за что отвечает каждый

МодульГде находитсяЧто в нём пишут
Модуль управляемого приложенияКорень конфигурации, контекстное менюДействия при запуске и завершении работы клиента
Модуль обычного приложенияТам жеТо же, для обычного (толстого) клиента
Модуль сеансаКорень конфигурацииУстановка параметров сеанса, выполняется на сервере
Модуль внешнего соединенияКорень конфигурацииКод для подключения через COM-соединение
Общий модульОбщие → Общие модулиПроцедуры, которые вызывают из разных мест
Модуль объектаСправочник, документ, обработка и т. п.Обработчики записи, проведения, проверки заполнения
Модуль менеджераТот же объект метаданныхФункции, которым не нужен конкретный экземпляр: печать, выборки
Модуль формыКаждая формаОбработчики элементов и команд формы
Модуль набора записейРегистрыПроверки и действия при записи набора
Модуль командыКоманды объектов и общие командыОбработчик ОбработкаКоманды

💡 Простое правило выбора. Код про конкретный документ при его записи — в модуль объекта. Код «для всех документов этого вида» без ссылки на экземпляр — в модуль менеджера. Код, нужный в пяти местах конфигурации, — в общий модуль.

Как создать модуль объекта: пошагово

Модуль объекта нужен, когда документ или справочник должен что-то делать сам при записи, проведении или заполнении.

Шаг 1. Откройте модуль

  1. В дереве конфигурации раскройте Документы (или Справочники).
  2. Щёлкните объект правой кнопкой мыши.
  3. Выберите Открыть модуль объекта.

Второй путь — открыть окно редактирования объекта и на вкладке Прочее нажать Модуль объекта. Там же рядом кнопка модуля менеджера.

Шаг 2. Добавьте обработчик события

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

Пример: документ сам пересчитывает сумму перед записью.

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ОбработчикиСобытий

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

	Если ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;

	СуммаДокумента = Товары.Итог("Сумма");

КонецПроцедуры

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

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

КонецПроцедуры

#КонецОбласти

#Область ПрограммныйИнтерфейс

Процедура ЗаполнитьЦены() Экспорт

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

КонецПроцедуры

#КонецОбласти

#КонецЕсли

Два приёма, которые знает каждый разработчик:

  • 🔁 Проверка ОбменДанными.Загрузка в начале ПередЗаписью. При загрузке данных через обмен объект пишется «как есть», и ваша логика не должна его менять.
  • 🛡 Обёртка #Если Сервер ... #КонецЕсли. Модуль объекта выполняется на сервере, и инструкция препроцессора не даёт коду попасть туда, где он работать не может.

Шаг 3. Проверьте синтаксис и сохраните

Нажмите Ctrl+F7 — платформа проверит синтаксис текущего модуля и покажет ошибки в окне сообщений. Затем F7, чтобы обновить конфигурацию базы данных. Структура метаданных при правке только кода не меняется, поэтому монопольный доступ к базе для такого обновления обычно не нужен.

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

Модуль формы открывается в редакторе формы: внизу окна есть вкладка Модуль. Главное отличие от модуля объекта — код формы работает и на клиенте, и на сервере. Где именно, задаёт директива перед каждой процедурой.

ДирективаГде выполняетсяЕсть ли доступ к данным формы
&НаКлиентеНа клиентеДа, но без обращения к базе
&НаСервереНа сервереДа, форма передаётся на сервер целиком
&НаСервереБезКонтекстаНа сервереНет, только параметры процедуры
&НаКлиентеНаСервереБезКонтекстаИ там, и тамНет

Как добавить обработчик кнопки

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

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

Связка клиент — сервер на примере, который вызывает экспортную процедуру из модуля объекта выше:

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

&НаСервере
Процедура ЗаполнитьЦеныНаСервере()
	Документ = РеквизитФормыВЗначение("Объект");
	Документ.ЗаполнитьЦены();
	ЗначениеВРеквизитФормы(Документ, "Объект");
КонецПроцедуры

Каждый вызов &НаСервере из клиента — это обращение к серверу с передачей данных формы. Если серверу нужна только ссылка, пишите &НаСервереБезКонтекста и передавайте ссылку параметром. На медленном канале разница заметна сразу.

Типовые обработчики модуля формы: ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) — настройка формы до открытия, ПриОткрытии(Отказ) — клиентские действия, ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи) — правка объекта перед записью из формы.

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

Создание

  1. В дереве конфигурации раскройте Общие → Общие модули.
  2. Правой кнопкой — Добавить.
  3. В палитре свойств задайте имя, например РаботаСТоварамиСервер.
  4. Расставьте флаги выполнения (о них ниже).
  5. Напишите процедуры с ключевым словом Экспорт.

Вызов из другого кода — через имя модуля: РаботаСТоварамиСервер.ОстатокТовара(Номенклатура, Склад).

#Область ПрограммныйИнтерфейс

// Возвращает количество товара на складе по регистру остатков.
Функция ОстатокТовара(Номенклатура, Склад) Экспорт

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

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

КонецФункции

#КонецОбласти

Имя регистра в примере условное: подставьте регистр своей конфигурации. Агрегатная СУММА без группировки всегда возвращает одну строку, поэтому Выборка.Следующий() здесь безопасен.

Флаги общего модуля

Флаги определяют, где модуль существует и кто может его вызвать. Ошибка во флагах — самая частая причина, почему «процедура есть, а вызвать её нельзя».

ФлагЧто даётСуффикс имени по стандартам
СерверМодуль компилируется на сервере...Сервер
Сервер + Вызов сервераЭкспортные методы можно вызывать с клиента...ВызовСервера
Клиент (управляемое приложение)Код работает в тонком и веб-клиенте...Клиент
Клиент + СерверКод без обращений к базе, доступен везде...КлиентСервер
ГлобальныйМетоды вызываются без имени модуля...Глобальный
ПривилегированныйКод выполняется без проверки прав...ПолныеПрава
Повторное использование возвращаемых значенийКэширование результатов функций...ПовтИсп

Что учитывать:

  • ⚡ Глобальные модули компилируются при старте клиента. Десяток тяжёлых глобальных модулей — это медленный запуск. Ставьте флаг только там, где без него никак.
  • 🔐 Привилегированный режим снимает проверку прав. Не кладите в такой модуль методы с флагом вызова с клиента, которые принимают произвольные параметры: пользователь получит доступ к данным в обход своей роли.
  • 🗃 Повторное использование бывает «на время вызова» и «на время сеанса». Кэшируются только функции, и результат должен быть неизменяемым: возвращайте ФиксированныйМассив или ФиксированнаяСтруктура, а не обычную коллекцию, которую код потом поменяет.
Диагностика: выберите симптом

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

В типовой БП 3.0, ЗУП 3.1 или УТ 11, которая стоит на поддержке, редактировать модули нельзя, пока не включена возможность изменений. Снятие с поддержки усложняет каждое следующее обновление: ваши правки придётся сравнивать и объединять вручную.

Поэтому новые модули в типовые конфигурации добавляют через расширение. Расширения появились в платформе 8.3.6, а перехват методов существующих модулей стал нормальной практикой в более поздних версиях.

  1. Конфигурация → Расширения конфигурации, кнопка добавления нового расширения.
  2. Откройте конфигурацию расширения и добавьте общий модуль в его дереве так же, как в основной конфигурации.
  3. Чтобы изменить поведение типового документа, щёлкните его в основной конфигурации правой кнопкой и выберите Добавить в расширение.
  4. В модуле объекта внутри расширения создайте процедуру с аннотацией &Перед, &После или &Вместо и именем перехватываемого метода.
&После("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	Если Не Отказ И Не ЗначениеЗаполнено(Комментарий) Тогда
		Комментарий = "Создан " + Формат(ТекущаяДатаСеанса(), "ДЛФ=D");
	КонецЕсли;
КонецПроцедуры

💡 Префикс Расш1_ в имени процедуры — не формальность. Он не даёт конфликтовать с именами из основной конфигурации и сразу показывает, чей это код.

Если в типовой конфигурации всё же включаете возможность изменений, сначала выгрузите базу в .dt. Вернуть конфигурацию на полную поддержку без резервной копии нельзя.

Отладка и проверка кода модулей

Точки останова и пошаговое выполнение

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

Для клиент-серверной базы серверный код отлаживается, только если на сервере 1С разрешена отладка. Это настройка службы агента сервера, её меняет администратор. Перезапуск службы обрывает сеансы всех пользователей, поэтому делают это вне рабочего времени.

Проверка конфигурации целиком

Ctrl+F7 проверяет только открытый модуль. Перед выпуском доработки запустите Конфигурация → Проверка конфигурации. Отметьте режимы тонкого клиента, веб-клиента и сервера: проверка найдёт вызовы серверных методов из клиентского кода, которые синтаксический контроль одного модуля пропускает.

Быстрый тест без правки конфигурации

Кусок кода удобно проверить во внешней обработке: Файл → Новый → Внешняя обработка. Добавьте форму, кнопку, вставьте код в модуль формы и откройте обработку в пользовательском режиме через Файл → Открыть. Рабочая конфигурация при этом не меняется.

Ошибки при написании модулей, которых стоит избегать

  • 🚫 Запрос в цикле. Обращение к базе в каждой итерации по 500 строкам товаров — это 500 запросов. Соберите данные одним запросом до цикла.
  • 🚫 Обращение к базе из клиентского кода через точку. Объект.Контрагент.ИНН в процедуре &НаКлиенте в управляемой форме не сработает: ссылочные данные доступны только на сервере. Получите ИНН серверной функцией без контекста.
  • 🚫 Склейка числа со строкой. "Строк: " + Количество даст Строк: 1 500 с неразрывным пробелом. Пишите Формат(Количество, "ЧГ=0") или СтрШаблон("Строк: %1", Количество).
  • 🚫 Удаление из коллекции в прямом цикле. Удаляйте строки обратным проходом: Для Сч = 1 По Товары.Количество() Цикл Строка = Товары[Товары.Количество() - Сч]; .... Здесь граница цикла вычисляется один раз, а индекс считается от текущего размера.
  • 🚫 Логика записи в модуле формы. Проверка, которая живёт только в форме, не сработает при записи объекта из обработки или обмена. Правила данных — в модуль объекта.
  • 🚫 Всё в одном общем модуле. Модуль-свалка с флагами «Клиент» и «Сервер» сразу тянет в клиентский контекст лишний код. Делите по контексту выполнения.

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

Можно ли создать модуль в режиме 1С:Предприятие?
Нет. Модули создают и редактируют в Конфигураторе или 1С:EDT. В пользовательском режиме можно только подключить готовую внешнюю обработку или расширение, код которых написан заранее.
Чем модуль менеджера отличается от общего модуля?
Модуль менеджера принадлежит одному объекту и вызывается через него: Документы.ИмяДокумента.ИмяФункции(). Общий модуль не привязан к объекту. Код про один вид документа логичнее держать в модуле менеджера.
Можно ли объявить переменную в общем модуле?
Нет, в общих модулях нет раздела объявления переменных. Для значений на весь сеанс используют параметры сеанса или функции в модуле с повторным использованием.
Как найти, в каком модуле находится процедура?
В Конфигураторе есть глобальный поиск по всем текстам конфигурации: Правка → Глобальный поиск. Для перехода к определению вызываемой процедуры поставьте на неё курсор и нажмите F12.
Нужно ли обновлять конфигурацию базы после правки кода?
Да. Пока не нажата F7, пользователи работают со старой версией модуля. Изменения увидят сеансы, запущенные после обновления; уже открытым сеансам платформа предложит перезапуск.