При работе в современных конфигурациях 1С, таких как Управление торговлей 11, ERP 2.5 или Комплексная автоматизация, пользователи часто сталкиваются с необходимостью очистки данных при создании нового элемента путем копирования. Одной из специфических задач является удаление значений дополнительных реквизитов, которые по умолчанию копируются из исходного объекта. Если этого не сделать, в новом товаре могут остаться уникальные характеристики, артикулы поставщиков или весогабаритные данные, принадлежащие старому объекту.
В этой статье мы подробно разберем, почему стандартные попытки очистки в форме могут не срабатывать, и как правильно реализовать эту задачу с помощью механизмов расширений и событий модуля объекта.
Рассмотрим типичную ситуацию: разработчик пытается очистить реквизиты в процедуре ПриСозданииНаСервере модуля формы. Однако, как показывает практика, это часто не приносит желаемого результата. Проанализируем причину: подсистема "Свойства" из состава Библиотеки стандартных подсистем (БСП) инициализирует дополнительные реквизиты динамически. Если очистить табличную часть ДополнительныеРеквизиты слишком рано или в неподходящем месте программного кода, механизмы БСП могут повторно заполнить их из параметров копирования или объект просто не успеет обновить свои данные до вывода на экран.
Наиболее надежным и архитектурно правильным способом является перехват события непосредственно в момент зарождения нового объекта — в процедуре ПриКопировании.
Событие ПриКопировании вызывается в модуле объекта сразу после того, как данные из оригинала были перенесены в новый (еще не записанный) объект. Это идеальный момент, чтобы "вмешаться" и очистить ненужные коллекции.
Выполним следующие шаги для реализации через расширение:
Номенклатура.Номенклатура.&После.Разберем пример кода, который решает поставленную задачу:
&После("ПриКопировании")
Процедура РАСШ_ПриКопировании(ОбъектКопирования)
// Очищаем табличную часть, в которой хранятся дополнительные реквизиты
ЭтотОбъект.ДополнительныеРеквизиты.Очистить();
// Если требуется очистить и дополнительные сведения (внешние свойства),
// это делается иначе, так как они не хранятся внутри объекта.
// Но для доп. реквизитов достаточно метода Очистить().
КонецПроцедуры
Почему это работает: Метод Очистить() полностью удаляет все строки из табличной части ДополнительныеРеквизиты нового объекта. Поскольку это происходит на уровне ядра платформы в модуле объекта, форма при открытии получит уже "пустой" в плане доп. реквизитов объект и отобразит их незаполненными.
Если вы не хотите использовать механизм расширений для модулей (например, чтобы избежать проблем при обновлении), можно воспользоваться Подпиской на событие. Это еще более универсальный метод, который позволяет применить логику сразу к нескольким справочникам.
Рассмотрим алгоритм настройки подписки:
СправочникОбъект.Номенклатура, СправочникОбъект.Контрагенты).ПриКопировании.Проанализируем код обработчика в общем модуле:
Процедура ОчиститьДопРеквизитыПриКопировании(Источник, Отказ, ОбъектКопирования) Экспорт
// Источник — это наш новый создаваемый объект
// Проверяем наличие табличной части, чтобы избежать ошибок
МетаданныеОбъекта = Источник.Метаданные();
Если МетаданныеОбъекта.ТабличныеЧасти.Найти("ДополнительныеРеквизиты") <> Неопределено Тогда
Источник.ДополнительныеРеквизиты.Очистить();
КонецЕсли;
КонецПроцедуры
Выясним причину, по которой иногда после очистки реквизиты могут выглядеть странно или требовать заполнения. В конфигурациях на базе БСП (УТ 11, ERP) дополнительные реквизиты могут быть помечены как обязательные для заполнения.
Проанализируем последствия очистки таких реквизитов:
Частичная очистка: Иногда нужно очистить не все реквизиты, а только определенные. В этом случае вместо метода Очистить() следует использовать обход коллекции. Рассмотрим пример:
&После("ПриКопировании")
Процедура РАСШ_ПриКопировании(ОбъектКопирования)
СписокИсключений = Новый СписокЗначений;
СписокИсключений.Добавить("Производитель"); // Этот реквизит оставим
Индекс = ЭтотОбъект.ДополнительныеРеквизиты.Количество() - 1;
Пока Индекс >= 0 Цикл
СтрокаРеквизита = ЭтотОбъект.ДополнительныеРеквизиты[Индекс];
// Проверяем имя свойства (нужно получить имя из Плана Видов Характеристик)
Если СписокИсключений.НайтиПоЗначению(СтрокаРеквизита.Свойство.Наименование) = Неопределено Тогда
ЭтотОбъект.ДополнительныеРеквизиты.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
КонецПроцедуры
Важно помнить, что в 1С существует два похожих механизма:
ДополнительныеСведения. При обычном копировании элемента номенклатуры они не копируются платформой автоматически, так как привязаны к ссылке объекта, которой у нового элемента еще нет (до момента записи). Поэтому для дополнительных сведений писать код очистки обычно не требуется — они и так будут пустыми для новой копии.Таким образом, использование события ПриКопировании в модуле объекта является наиболее эффективным решением. Мы обеспечиваем чистоту данных еще до того, как пользователь увидит форму нового элемента, что исключает ошибки ввода и дублирование неактуальной информации.