В практике разработчика 1С часто возникают ситуации, когда необходимо записать объект "тихо" — то есть так, чтобы не сработали стандартные проверки, алгоритмы заполнения или проведения. Это актуально при выполнении обменов данными, групповой обработке справочников или исправлении ошибок в документах прошлых периодов. В этой статье мы подробно разберем все доступные механизмы, которые позволяют обойти обработчики событий, и выясним, какие нюансы скрывает платформа 1С:Предприятие 8.3.
Самым правильным и системным способом отключения логики при записи является использование свойства ОбменДанными.Загрузка. Рассмотрим, как это работает на практике. Когда мы устанавливаем это свойство в значение Истина, мы сообщаем платформе, что объект записывается в режиме импорта данных, и лишние действия выполнять не нужно.
Проанализируем пример кода:
Объект = СсылкаНаДокумент.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Важно понимать, что происходит "под капотом" платформы при такой установке. В этом режиме платформа автоматически отключает:
ОбработкаПроведения в модуле документа просто не будет вызван.Многие разработчики сталкиваются с ситуацией: флаг ОбменДанными.Загрузка установлен, но код в процедурах ПередЗаписью или ПриЗаписи все равно выполняется и выдает ошибки. Разберем причину этой ситуации. Платформа все равно вызывает эти процедуры, даже если включен режим загрузки. Она лишь предоставляет программисту инструмент, чтобы он сам решил, выполнять ли прикладную логику.
Поэтому правилом "хорошего тона" и стандартом разработки фирмы 1С является добавление проверки в самом начале обработчиков событий в модуле объекта:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Далее идет основной код логики
КонецПроцедуры
Если в вашей конфигурации (особенно если она самописная) в объектах нет такой проверки, то установка флага ОбменДанными.Загрузка = Истина в коде вызова не принесет желаемого результата для прикладной логики. В таких случаях нам на помощь приходят альтернативные методы.
Если мы работаем с типовой конфигурацией, где разработчики забыли вставить проверку ОбменДанными.Загрузка, или нам нужно временно отключить события в закрытом для редактирования объекте, мы можем воспользоваться механизмом расширений. Рассмотрим, как это сделать.
Мы создаем расширение и добавляем в него нужный объект. Затем создаем метод-обертку для процедуры ПередЗаписью с типом вызова &Вместо. Напишем пример кода для расширения:
&Вместо("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтотОбъект.ОбменДанными.Загрузка Тогда
// Просто выходим, не вызывая основную процедуру
Возврат;
КонецЕсли;
// Если это не загрузка, вызываем стандартную логику
ПродолжитьВызов(Отказ, РежимЗаписи, РежимПроведения);
КонецПроцедуры
Такой подход позволяет нам программно "заткнуть" события в любом объекте системы, не меняя основную конфигурацию и не снимая её с поддержки.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), то вы можете использовать специализированные флаги в коллекции ДополнительныеСвойства. Эти флаги обрабатываются общими модулями БСП и подписками на события. Выясним, какие свойства наиболее полезны.
Рассмотрим пример комплексного отключения механизмов контроля:
Объект = Ссылка.ПолучитьОбъект();
// Отключаем регистрацию на узлах планов обмена
Объект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов", Истина);
// Отключаем версионирование (создание новых версий в истории)
Объект.ДополнительныеСвойства.Вставить("ЗаписьНовойВерсииОбъекта", Ложь);
// Пропускаем проверку запрета изменения данных
Объект.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения", Истина);
// Устанавливаем режим загрузки
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Использование таких свойств позволяет обойти не только код в самом модуле объекта, но и многочисленные Подписки на события, которые в современных конфигурациях выполняют львиную долю проверок (проверка прав, заполнение реквизитов, бизнес-логика).
Если перед вами стоит задача отключить логику записи сразу для большого количества типов объектов (например, для всех документов), можно создать собственную общую подписку на событие ПередЗаписью. В качестве источника выберите ДокументОбъект (или список нужных документов).
В обработчике подписки можно реализовать проверку глобальной переменной или параметра сеанса, который будет служить "рубильником":
Процедура ОбщаяПодпискаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если ПараметрыСеанса.ОтключитьБизнесЛогикуПриЗаписи Тогда
Источник.ОбменДанными.Загрузка = Истина;
КонецЕсли;
КонецПроцедуры
Важно помнить: подписки на события выполняются в определенном порядке. Событие ПередЗаписью в модуле объекта срабатывает до подписок на это же событие. Поэтому, если код в модуле объекта уже выдал ошибку и установил Отказ = Истина, подписка уже не сможет это исправить. Однако она отлично подходит для управления регистрацией изменений и дополнительными сервисами.
Проанализируем ситуацию с регистрами сведений и накопления. Если вам нужно записать данные в регистр, минуя события документа-регистратора, используйте НаборЗаписей. При записи набора записей напрямую, обработчики событий документа (ПередЗаписью, ПриЗаписи) вообще не вызываются. У набора записей также есть свойство ОбменДанными.Загрузка, которое позволяет записывать данные без контроля уникальности и других проверок платформы.
Резюмируя, можно сказать, что ОбменДанными.Загрузка = Истина — это фундамент, на котором строится отключение событий. Но для полноценного "тихого" режима записи всегда проверяйте наличие соответствующего условия в коде обработчиков и при необходимости используйте расширения или ДополнительныеСвойства.