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