К статье
Практический материал

Разработка и Конфигурация · 15 мин

Модуль объекта в 1С 8: что доступно и как правильно использовать

Что доступно в модуле объекта 1С 8.3: контекст, реквизиты, ЭтотОбъект, события, экспортные процедуры. Примеры кода, ограничения и типичные ошибки разработчиков.

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

Главное отличие модуля объекта от модуля формы и общих модулей — неявный контекст. Внутри модуля объекта можно обращаться к реквизитам без указания имени объекта: просто Контрагент вместо ЭтотОбъект.Контрагент. Это удобно, но часто становится источником ошибок у начинающих разработчиков, которые пытаются использовать в модуле объекта элементы формы или, наоборот, обращаются к контексту объекта из общего модуля.

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

Что такое модуль объекта и где он находится

Модуль объекта существует у большинства прикладных объектов конфигурации: справочников, документов, планов видов характеристик, планов счетов, планов видов расчёта, бизнес-процессов, задач, обработок и отчётов. Открыть его можно в конфигураторе: правый клик по объекту в дереве конфигурации → «Открыть модуль объекта». У регистров (сведений, накопления, бухгалтерии, расчёта) вместо модуля объекта используется модуль набора записей.

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

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

Внутри модуля объекта все реквизиты объекта доступны напрямую по имени. Если у документа «РеализацияТоваровУслуг» есть реквизит «Контрагент», в коде модуля достаточно написать Контрагент — платформа сама разрешит обращение. То же касается табличных частей: Товары.Итог("Сумма") вернёт итог по колонке без дополнительных указаний.

Свойство ЭтотОбъект содержит ссылку на сам объект и используется, когда нужно передать текущий экземпляр в другую процедуру или явно указать контекст. Например: РегистрыНакопления.Продажи.ЗаписатьДвижения(ЭтотОбъект). Также доступны стандартные свойства: Ссылка, Дата, Номер (для документов), Код и Наименование (для справочников), ЭтоНовый(), Модифицированность(), ДополнительныеСвойства.

Отдельного внимания заслуживает свойство ДополнительныеСвойства — структура, через которую в объект передают произвольные данные между подписками на события, обработчиками и внешним кодом. Типовой сценарий: передать из формы флаг «не проверять заполнение» и прочитать его в ПередЗаписью. Это единственный безопасный способ «протащить» произвольные данные внутрь транзакции записи.

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

События модуля объекта: что и когда срабатывает

Основная часть кода модуля объекта — это обработчики предопределённых событий. Их набор зависит от типа объекта. Для документов ключевые события: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаУдаленияПроведения, ОбработкаЗаполнения, ОбработкаПроверкиЗаполнения, ПриКопировании. Для справочников набор похож, но без событий проведения.

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

Типичная ошибка — размещать в ПриЗаписи логику, которая должна выполняться только при проведении. Документ может записываться многократно без проведения, и побочные действия (например, отправка уведомлений) будут дублироваться. Проверяйте РежимЗаписи в ПередЗаписью или переносите логику в ОбработкаПроведения.

ОбработкаПроверкиЗаполненияДо записи

Проверка обязательных данных, установка Отказ

ПередЗаписьюДо сохранения в базу

Последние изменения реквизитов объекта

ПриЗаписиВ транзакции записи

Обновление связанных объектов и регистров

ОбработкаПроведенияПри проведении

Формирование движений по регистрам

Экспортные процедуры и функции модуля объекта

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

Важное ограничение: вызвать экспортный метод можно только у объекта, а не у ссылки. Если у вас есть ДокументСсылка, сначала нужно получить объект через Ссылка.ПолучитьОбъект() — а это полное чтение объекта из базы с блокировкой при записи. Поэтому методы, которые должны работать «по ссылке» без чтения объекта целиком, выносят в модуль менеджера объекта (например, типовые функции печати работают именно там).

Где размещать методы

Модуль объекта

Логика, требующая данных конкретного экземпляра: расчёты по табличным частям, проверки, заполнение. Требует ПолучитьОбъект() при вызове по ссылке.

Модуль менеджера

Операции над множеством объектов или по ссылке без чтения объекта: печатные формы, подбор данных, создание новых экземпляров.

Общий модуль

Универсальные алгоритмы, не привязанные к конкретному типу объекта: работа со строками, датами, обмен данными.

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

Список ограничений модуля объекта напрямую следует из его серверной природы. Недоступны: элементы формы и её реквизиты, клиентские методы (Предупреждение, ПоказатьВопрос, ОткрытьФорму), работа с файловой системой клиентского компьютера, директивы &НаКлиенте / &НаСервере (они в модулях объектов просто не применяются — весь код серверный).

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

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

Типичные сценарии использования на практике

Автозаполнение при создании документа

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

Проверка данных перед записью

В ОбработкаПроверкиЗаполнения принято реализовывать комплексные проверки, которые невозможно выразить свойством «Проверка заполнения» в конфигураторе: согласованность реквизитов между собой, контроль дублей строк в табличной части, проверка остатков. Для отказа установите Отказ = Истина и выведите сообщение через СообщениеПользователю с привязкой к реквизиту — тогда сообщение подсветит проблемное поле в форме.

Формирование движений при проведении

ОбработкаПроведения — центральное событие документа. Здесь обращаются к коллекции Движения, заполняют наборы записей регистров и устанавливают Движения.Продажи.Записывать = Истина. Типовая структура: запрос по табличным частям документа → выборка → цикл заполнения движений. При отказе (Отказ = Истина) вся транзакция проведения откатывается, включая запись самого документа.

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

Типичные ошибки и как их избежать

Первая ошибка — попытка обратиться к форме из модуля объекта. Конструкции вида ЭтаФорма.Элементы.Товары в модуле объекта не работают: форма и объект — разные сущности. Данные из формы передаются через реквизиты объекта или ДополнительныеСвойства.

Вторая ошибка — модификация реквизитов в событии ПриЗаписи. На этом этапе объект уже записан в базу; изменения реквизитов в памяти не сохранятся без повторной записи, которая вызовет рекурсию. Все изменения данных объекта выполняйте в ПередЗаписью.

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

Типичные ошибки в модуле объекта
01
Обращение к элементам формы — код падает с ошибкой, так как форма недоступна в серверном контексте объекта
02
Изменение реквизитов в ПриЗаписи — изменения теряются или вызывают рекурсивную запись
03
Отсутствие проверки ОбменДанными.Загрузка — обработчики срабатывают при обмене и портят данные
04
Вызов ПолучитьОбъект() ради одного метода — лишнее чтение и блокировка объекта; метод лучше перенести в модуль менеджера
05
Интерактивные вызовы (ПоказатьВопрос) — не работают на сервере и приводят к ошибке выполнения

Как проверить, что код модуля работает правильно

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

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

Контрольные точки

Как проверить результат

Запись корректного объекта
Норма

Объект записывается и проводится без сообщений об ошибках

Тревожный признак

Отказ в записи при корректных данных — проверяйте условия в ОбработкаПроверкиЗаполнения

Запись объекта с ошибкой
Норма

Отказ, сообщение с привязкой к проблемному полю

Тревожный признак

Объект записывается несмотря на нарушение — Отказ не установлен

Загрузка через обмен данными
Норма

Обработчики пропускаются, данные загружаются как есть

Тревожный признак

Срабатывают проверки и побочная логика — добавьте проверку ОбменДанными.Загрузка

Отмена проведения
Норма

Движения очищаются, побочных действий нет

Тревожный признак

Дублируются уведомления или изменения связанных объектов

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

Чем модуль объекта отличается от модуля менеджера?

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

Можно ли из модуля объекта показать сообщение пользователю?

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

Почему обработчик ПередЗаписью не срабатывает при записи из формы?

Срабатывает всегда, если объект действительно записывается. Частые причины «несрабатывания»: код размещён не в модуле объекта, а в модуле формы; конфигурация базы данных не обновлена после изменений; запись выполняется через механизм обмена данными, а в начале обработчика стоит выход по ОбменДанными.Загрузка. Проверьте отладчиком, доходит ли выполнение до обработчика.

Как передать данные из формы в модуль объекта?

Через свойство ДополнительныеСвойства объекта. В форме перед записью получите объект из реквизита формы (например, Объект.ДополнительныеСвойства.Вставить("Ключ", Значение)) — при серверном вызове записи эти данные будут доступны в обработчиках модуля объекта. Прямого обращения из модуля объекта к форме не существует.

Где размещать код проведения: в модуле объекта или в общем модуле?

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

Доступен ли модуль объекта в тонком и веб-клиенте?

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

Итог

Что важно запомнить

Модуль объекта — серверный модуль с прямым доступом к реквизитам и табличным частям текущего экземпляра. Основные события: ОбработкаПроверкиЗаполнения, ПередЗаписью, ПриЗаписи, ОбработкаПроведения. Элементы формы и клиентские вызовы недоступны; данные из формы передают через ДополнительныеСвойства. Всегда проверяйте ОбменДанными.Загрузка и изменяйте реквизиты только в ПередЗаписью.