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