Разработка и Конфигурация · 15 мин
Модуль объекта в 1С 8: что доступно и как правильно использовать
Что доступно в модуле объекта 1С 8.3: контекст, реквизиты, ЭтотОбъект, события, экспортные процедуры. Примеры кода, ограничения и типичные ошибки разработчиков.
Модуль объекта в 1С 8 — это программный модуль, в котором описывается поведение конкретного объекта конфигурации: документа, справочника, плана счетов, обработки, отчёта и других прикладных объектов. Код этого модуля выполняется только в контексте конкретного экземпляра объекта — записываемого документа, выбранного элемента справочника или открытой обработки. Поэтому внутри модуля объекта напрямую доступны реквизиты, табличные части и стандартные свойства именно этого экземпляра.
Главное отличие модуля объекта от модуля формы и общих модулей — неявный контекст. Внутри модуля объекта можно обращаться к реквизитам без указания имени объекта: просто Контрагент вместо ЭтотОбъект.Контрагент. Это удобно, но часто становится источником ошибок у начинающих разработчиков, которые пытаются использовать в модуле объекта элементы формы или, наоборот, обращаются к контексту объекта из общего модуля.
Понимание того, что именно доступно в модуле объекта, критично для правильной архитектуры решения: бизнес-логику проведения и проверки данных принято размещать здесь, а интерфейсные операции — в модуле формы. Смешение этих слоёв приводит к ошибкам при работе в тонком и веб-клиенте, где серверный контекст объекта недоступен в клиентских вызовах.
Что такое модуль объекта и где он находится
Модуль объекта существует у большинства прикладных объектов конфигурации: справочников, документов, планов видов характеристик, планов счетов, планов видов расчёта, бизнес-процессов, задач, обработок и отчётов. Открыть его можно в конфигураторе: правый клик по объекту в дереве конфигурации → «Открыть модуль объекта». У регистров (сведений, накопления, бухгалтерии, расчёта) вместо модуля объекта используется модуль набора записей.
Код модуля объекта выполняется на сервере. Даже когда пользователь записывает документ в форме на клиенте, обработчики модуля объекта срабатывают в серверном контексте. Это принципиально: из модуля объекта нельзя обратиться к элементам управляемой формы, показать пользователю вопрос через Вопрос() в асинхронном режиме или выполнить интерактивные действия. Для сообщений используется Сообщить() или объект СообщениеПользователю.
Контекст модуля: реквизиты, табличные части и ЭтотОбъект
Внутри модуля объекта все реквизиты объекта доступны напрямую по имени. Если у документа «РеализацияТоваровУслуг» есть реквизит «Контрагент», в коде модуля достаточно написать Контрагент — платформа сама разрешит обращение. То же касается табличных частей: Товары.Итог("Сумма") вернёт итог по колонке без дополнительных указаний.
Свойство ЭтотОбъект содержит ссылку на сам объект и используется, когда нужно передать текущий экземпляр в другую процедуру или явно указать контекст. Например: РегистрыНакопления.Продажи.ЗаписатьДвижения(ЭтотОбъект). Также доступны стандартные свойства: Ссылка, Дата, Номер (для документов), Код и Наименование (для справочников), ЭтоНовый(), Модифицированность(), ДополнительныеСвойства.
Отдельного внимания заслуживает свойство ДополнительныеСвойства — структура, через которую в объект передают произвольные данные между подписками на события, обработчиками и внешним кодом. Типовой сценарий: передать из формы флаг «не проверять заполнение» и прочитать его в ПередЗаписью. Это единственный безопасный способ «протащить» произвольные данные внутрь транзакции записи.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() Тогда
Ответственный = ПользователиИнформационнойБазы.ТекущийПользователь().Имя;
КонецЕсли;
Если Не ДополнительныеСвойства.Свойство("ПропуститьПроверку") Тогда
Если Товары.Итог("Сумма") = 0 Тогда
Отказ = Истина;
Сообщить("Сумма документа равна нулю");
КонецЕсли;
КонецЕсли;
КонецПроцедурыСобытия модуля объекта: что и когда срабатывает
Основная часть кода модуля объекта — это обработчики предопределённых событий. Их набор зависит от типа объекта. Для документов ключевые события: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаУдаленияПроведения, ОбработкаЗаполнения, ОбработкаПроверкиЗаполнения, ПриКопировании. Для справочников набор похож, но без событий проведения.
Порядок вызова важен для корректной логики. Сначала срабатывает ОбработкаПроверкиЗаполнения — здесь принято проверять обязательные реквизиты и отказывать в записи через параметр Отказ. Затем ПередЗаписью — последняя точка, где можно изменить данные объекта до фиксации в базе. ПриЗаписи выполняется уже внутри транзакции записи, когда объект физически сохранён, — здесь обновляют связанные данные, регистры сведений, статусы. ОбработкаПроведения вызывается при проведении и отвечает за формирование движений по регистрам.
Типичная ошибка — размещать в ПриЗаписи логику, которая должна выполняться только при проведении. Документ может записываться многократно без проведения, и побочные действия (например, отправка уведомлений) будут дублироваться. Проверяйте РежимЗаписи в ПередЗаписью или переносите логику в ОбработкаПроведения.
Проверка обязательных данных, установка Отказ
Последние изменения реквизитов объекта
Обновление связанных объектов и регистров
Формирование движений по регистрам
Экспортные процедуры и функции модуля объекта
Кроме обработчиков событий, в модуле объекта можно объявлять собственные процедуры и функции с ключевым словом Экспорт. Они становятся методами объекта и доступны извне: из формы, из других модулей, из внешних обработок. Например, функция ПолучитьСуммуДокумента() Экспорт позволит любому коду получить рассчитанное значение, не дублируя логику.
Важное ограничение: вызвать экспортный метод можно только у объекта, а не у ссылки. Если у вас есть ДокументСсылка, сначала нужно получить объект через Ссылка.ПолучитьОбъект() — а это полное чтение объекта из базы с блокировкой при записи. Поэтому методы, которые должны работать «по ссылке» без чтения объекта целиком, выносят в модуль менеджера объекта (например, типовые функции печати работают именно там).
Где размещать методы
Логика, требующая данных конкретного экземпляра: расчёты по табличным частям, проверки, заполнение. Требует ПолучитьОбъект() при вызове по ссылке.
Операции над множеством объектов или по ссылке без чтения объекта: печатные формы, подбор данных, создание новых экземпляров.
Универсальные алгоритмы, не привязанные к конкретному типу объекта: работа со строками, датами, обмен данными.
Что недоступно в модуле объекта: ограничения и риски
Список ограничений модуля объекта напрямую следует из его серверной природы. Недоступны: элементы формы и её реквизиты, клиентские методы (Предупреждение, ПоказатьВопрос, ОткрытьФорму), работа с файловой системой клиентского компьютера, директивы &НаКлиенте / &НаСервере (они в модулях объектов просто не применяются — весь код серверный).
Ещё одна граница — обращение к другим объектам. Из модуля объекта можно читать и изменять любые другие объекты базы, но делать это в транзакции записи нужно осторожно: изменение связанных объектов в ПриЗаписи может привести к взаимным блокировкам при параллельной работе пользователей. Правило: читайте сколько угодно, изменяйте только то, без чего транзакция не имеет смысла, и никогда не вызывайте из модуля объекта длительные операции (обмены, запросы к внешним сервисам) синхронно.
Также нельзя обратиться к контексту объекта до его инициализации: в обработчике ОбработкаЗаполнения реквизиты ещё могут быть пустыми, а Ссылка у нового объекта — пустой. Проверка ЭтоНовый() и аккуратная работа с незаполненными значениями обязательны.
Типичные сценарии использования на практике
Автозаполнение при создании документа
Событие ОбработкаЗаполнения срабатывает при создании объекта и при вводе на основании. Здесь заполняют значения по умолчанию: организацию, склад, валюту, ответственного. Параметр ДанныеЗаполнения содержит объект-основание — проверяйте его тип через ТипЗнч() перед обращением к реквизитам, иначе при ручном создании документа получите ошибку.
Проверка данных перед записью
В ОбработкаПроверкиЗаполнения принято реализовывать комплексные проверки, которые невозможно выразить свойством «Проверка заполнения» в конфигураторе: согласованность реквизитов между собой, контроль дублей строк в табличной части, проверка остатков. Для отказа установите Отказ = Истина и выведите сообщение через СообщениеПользователю с привязкой к реквизиту — тогда сообщение подсветит проблемное поле в форме.
Формирование движений при проведении
ОбработкаПроведения — центральное событие документа. Здесь обращаются к коллекции Движения, заполняют наборы записей регистров и устанавливают Движения.Продажи.Записывать = Истина. Типовая структура: запрос по табличным частям документа → выборка → цикл заполнения движений. При отказе (Отказ = Истина) вся транзакция проведения откатывается, включая запись самого документа.
- 1Откройте конфигуратор, найдите документ и откройте его модуль объекта
- 2Создайте обработчик ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
- 3Добавьте условие проверки и при нарушении установите Отказ = Истина
- 4Выведите сообщение через СообщениеПользователю с указанием реквизита
- 5Обновите конфигурацию базы данных и проверьте: документ с ошибкой не записывается, корректный — записывается и проводится
Типичные ошибки и как их избежать
Первая ошибка — попытка обратиться к форме из модуля объекта. Конструкции вида ЭтаФорма.Элементы.Товары в модуле объекта не работают: форма и объект — разные сущности. Данные из формы передаются через реквизиты объекта или ДополнительныеСвойства.
Вторая ошибка — модификация реквизитов в событии ПриЗаписи. На этом этапе объект уже записан в базу; изменения реквизитов в памяти не сохранятся без повторной записи, которая вызовет рекурсию. Все изменения данных объекта выполняйте в ПередЗаписью.
Третья ошибка — игнорирование режима обмена данными. При загрузке через планы обмена обработчики записи выполняются, и ваша логика (например, отправка уведомлений или проверка остатков) может сработать некорректно. В начале обработчиков добавляйте проверку Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; — это стандарт де-факто для любых событий записи.
Как проверить, что код модуля работает правильно
Базовая проверка — ручной сценарий в пользовательском режиме: создать объект, заполнить, записать, провести, отменить проведение, скопировать. Каждое действие должно вызывать ожидаемые обработчики без ошибок. Для отладки установите точку останова в модуле объекта и запустите отладку конфигуратора — серверные обработчики останавливаются в ней штатно.
Дополнительно проверьте поведение при загрузке через обмен, при групповой обработке (например, перепроведении) и при работе нескольких пользователей с одним типом документов. Ошибки блокировок и логики проявляются именно в этих сценариях, а не при одиночном тестировании.
Как проверить результат
Объект записывается и проводится без сообщений об ошибках
Отказ в записи при корректных данных — проверяйте условия в ОбработкаПроверкиЗаполнения
Отказ, сообщение с привязкой к проблемному полю
Объект записывается несмотря на нарушение — Отказ не установлен
Обработчики пропускаются, данные загружаются как есть
Срабатывают проверки и побочная логика — добавьте проверку ОбменДанными.Загрузка
Движения очищаются, побочных действий нет
Дублируются уведомления или изменения связанных объектов
Частые вопросы
Чем модуль объекта отличается от модуля менеджера?
Модуль объекта работает в контексте конкретного экземпляра и имеет прямой доступ к его реквизитам. Модуль менеджера не привязан к экземпляру: в нём размещают функции работы с объектами «снаружи» — создание, печать, получение данных по ссылке без чтения объекта целиком. Вызвать метод модуля объекта можно только через ПолучитьОбъект(), метод модуля менеджера — напрямую через Документы.ИмяДокумента.ИмяМетода().
Можно ли из модуля объекта показать сообщение пользователю?
Да, но только через Сообщить() или объект СообщениеПользователю. Интерактивные диалоги (вопросы, предупреждения с ожиданием ответа) на сервере недоступны. Если нужна реакция пользователя, логику разделяют: проверку выполняют на клиенте в модуле формы до записи, а в модуле объекта оставляют только жёсткий контроль с отказом.
Почему обработчик ПередЗаписью не срабатывает при записи из формы?
Срабатывает всегда, если объект действительно записывается. Частые причины «несрабатывания»: код размещён не в модуле объекта, а в модуле формы; конфигурация базы данных не обновлена после изменений; запись выполняется через механизм обмена данными, а в начале обработчика стоит выход по ОбменДанными.Загрузка. Проверьте отладчиком, доходит ли выполнение до обработчика.
Как передать данные из формы в модуль объекта?
Через свойство ДополнительныеСвойства объекта. В форме перед записью получите объект из реквизита формы (например, Объект.ДополнительныеСвойства.Вставить("Ключ", Значение)) — при серверном вызове записи эти данные будут доступны в обработчиках модуля объекта. Прямого обращения из модуля объекта к форме не существует.
Где размещать код проведения: в модуле объекта или в общем модуле?
Обработчик ОбработкаПроведения существует только в модуле объекта — это точка входа. Однако объёмную логику формирования движений допустимо выносить в общие модули, передавая туда ЭтотОбъект или подготовленные данные. Так делают в типовых конфигурациях: обработчик остаётся компактным, а алгоритмы переиспользуются и тестируются отдельно.
Доступен ли модуль объекта в тонком и веб-клиенте?
Да, но только на сервере. При записи объекта из тонкого или веб-клиента платформа передаёт объект на сервер, где и выполняются все обработчики модуля объекта. Для разработчика это прозрачно, но важно помнить: никаких клиентских вызовов внутри модуля быть не должно, иначе код завершится ошибкой.
Что важно запомнить
Модуль объекта — серверный модуль с прямым доступом к реквизитам и табличным частям текущего экземпляра. Основные события: ОбработкаПроверкиЗаполнения, ПередЗаписью, ПриЗаписи, ОбработкаПроведения. Элементы формы и клиентские вызовы недоступны; данные из формы передают через ДополнительныеСвойства. Всегда проверяйте ОбменДанными.Загрузка и изменяйте реквизиты только в ПередЗаписью.