Как правильно очистить реквизиты документа при копировании в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 часто возникает задача: при создании нового документа путем копирования существующего необходимо обнулить определенные данные. Это могут быть статусы, суммы, специфические признаки или табличные части, которые не должны переноситься в новый документ. В этой статье мы подробно разберем, как реализовать этот механизм, проанализируем типичные ошибки и рассмотрим продвинутые способы автоматизации процесса.

Использование обработчика ПриКопировании в модуле объекта

Самый правильный и стандартный способ решения задачи — использование предопределенной процедуры ПриКопировании, которая располагается в модуле объекта документа. Рассмотрим ситуацию: пользователь нажимает кнопку "Скопировать" (или клавишу F9) в списке документов. В этот момент платформа создает новый объект и вызывает данную процедуру.

Важный нюанс: процедура ПриКопировании принимает один параметр — ОбъектКопирования. Это ссылка на тот документ, из которого создается копия. Новый же документ — это и есть ЭтотОбъект, в контексте которого выполняется код.

Разберем конкретный пример кода, который нужно разместить в модуле объекта:


Процедура ПриКопировании(ОбъектКопирования)
    
    // Очищаем реквизиты шапки
    Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
    ТСБрутто     = 0;
    ТСНетто      = 0;
    ТСТара       = 0;
    
    // Устанавливаем статус по умолчанию для нового документа
    СостояниеЗаказа = Перечисления.ВидыСостоянияЗаказа.ЗаказОформлен;
    
    // Если есть комментарий, который не должен копироваться
    Комментарий = "";
    
КонецПроцедуры

Обратите внимание, что мы обращаемся к реквизитам Номенклатура, ТСБрутто и другим напрямую. Это эквивалентно записи ЭтотОбъект.Номенклатура. Ошибка многих начинающих разработчиков заключается в попытке изменить ОбъектКопирования — делать этого не нужно, так как это источник данных, а не результат.

Универсальный способ очистки всех реквизитов через метаданные

Иногда документ содержит десятки реквизитов, и прописывать очистку каждого вручную трудозатратно. В таком случае мы можем применить универсальный алгоритм, который обходит все реквизиты объекта через коллекцию метаданных. При этом важно оставить нетронутыми ключевые поля, такие как "Организация" или "Склад".

Проанализируем следующий подход:


Процедура ПриКопировании(ОбъектКопирования)
    
    // Получаем коллекцию реквизитов данного типа документа из метаданных
    РеквизитыОбъекта = Метаданные().Реквизиты;
    
    Для Каждого Реквизит Из РеквизитыОбъекта Цикл
        
        // Определяем список исключений, которые НЕ нужно очищать
        Если Реквизит.Имя = "Организация" Или Реквизит.Имя = "Подразделение" Тогда
            Продолжить;
        КонецЕсли;
        
        // Присваиваем пустое значение в зависимости от типа данных
        // Платформа 1С автоматически подберет пустое значение нужного типа
        ЭтотОбъект[Реквизит.Имя] = Реквизит.Тип.ПривестиЗначение("");
        
    КонецЦикла;
    
КонецПроцедуры

Использование метода ПривестиЗначение("") позволяет корректно установить пустую ссылку для справочников, 0 для чисел и пустую строку для текстовых полей.

Очистка табличных частей при копировании

Если в документе есть табличные части (например, "Товары" или "Услуги"), они по умолчанию копируются полностью. Чтобы создать абсолютно "чистый" документ без строк в таблицах, используем метод Очистить(). Если же нужно оставить строки, но обнулить в них только цены или количество, воспользуемся циклом Для Каждого.

Рассмотрим пример комплексной очистки:


Процедура ПриКопировании(ОбъектКопирования)
    
    // 1. Полная очистка табличной части "СпецУсловия"
    ЭтотОбъект.СпецУсловия.Очистить();
    
    // 2. Частичная очистка в табличной части "Товары"
    Для Каждого СтрокаТовар Из ЭтотОбъект.Товары Цикл
        СтрокаТовар.Цена = 0;
        СтрокаТовар.Сумма = 0;
        СтрокаТовар.Скидка = 0;
    КонецЦикла;
    
КонецПроцедуры

Такой подход позволяет сохранить структуру документа (перечень товаров), но заставить пользователя заново ввести актуальные цены.

Использование подписки на событие

Если в вашей конфигурации много однотипных документов и для всех них действуют одинаковые правила (например, всегда очищать реквизит "Ответственный" или "Комментарий"), целесообразно использовать Подписку на событие. Это позволит не вносить изменения в модуль каждого конкретного документа, что особенно полезно при поддержке типовых конфигураций.

  1. Создайте новый объект метаданных Подписка на событие.
  2. В поле Источник выберите типы документов, для которых должна работать логика (или укажите ДокументОбъект для всех).
  3. В поле Событие выберите ПриКопировании.
  4. Создайте процедуру в общем модуле (модуль должен иметь флаг "Сервер").

Пример кода в общем модуле для подписки:


Процедура ОчиститьДанныеПриКопировании(Источник, ОбъектКопирования) Экспорт
    
    // Источник — это и есть наш новый создаваемый документ
    Источник.Комментарий = "";
    Источник.Ответственный = Пользователи.ТекущийПользователь();
    
    // Можно проверить наличие реквизита программно перед записью
    Если Источник.Метаданные().Реквизиты.Найти("Статус") <> Неопределено Тогда
        Источник.Статус = Справочники.СтатусыДокументов.Новый;
    КонецЕсли;
    
КонецПроцедуры

Различие между ПриКопировании и ОбработкойЗаполнения

Выясним важный методический момент. В управляемых формах 1С существует также обработчик ОбработкаЗаполнения. Когда происходит копирование, платформа вызывает сначала ПриКопировании (в модуле объекта), а затем ОбработкаЗаполнения. В ОбработкаЗаполнения параметр ДанныеЗаполнения будет содержать ссылку на копируемый объект. Для наглядного отслеживания последовательности их вызова можно использовать обработку для изучения событий 1С.

Рекомендация: Логику, специфичную именно для интерактивного копирования пользователем, лучше оставлять в ПриКопировании. Если же логика заполнения должна работать и при создании на основании других документов, используйте ОбработкаЗаполнения.

Работа с хранилищем значения

Если ваш документ содержит присоединенные файлы или изображения, хранящиеся в реквизите с типом ХранилищеЗначения, помните, что они также копируются "как есть". Чтобы очистить такие данные, нужно присвоить реквизиту новый объект хранилища с неопределенным значением:

ЭтотОбъект.ДанныеКартинки = Новый ХранилищеЗначения(Неопределено);

Проанализировав все вышеописанные методы, мы видим, что платформа 1С предоставляет гибкие инструменты для управления данными при копировании. Выбор конкретного метода зависит от объема реквизитов и необходимости тиражирования этой логики на разные виды документов.

← На главную