К статье
Практический материал

Разработка и Конфигурация · 13 мин

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

Как очистить реквизит при копировании документа в 1С: обработчик ПриКопировании, очистка табличных частей, отличия от ПриЗаполнении, примеры кода и типичные ошибки.

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

Обработчик ПриКопировании вызывается на сервере в момент, когда пользователь нажимает «Скопировать» (F9) в форме документа или списка. К этому моменту данные источника уже перенесены в новый объект, но документ ещё не записан — поэтому любые изменения реквизитов внутри обработчика безопасны и не требуют дополнительной записи.

Ниже разобраны типовые приёмы: очистка одиночных реквизитов, табличных частей, условная очистка по виду операции, а также отличия от события ПриЗаполнении и способы проверить результат без риска для рабочих данных.

Где находится событие ПриКопировании и как оно работает

Событие ПриКопировании располагается в модуле объекта документа. Чтобы открыть модуль, в конфигураторе найдите нужный документ в дереве конфигурации, вызовите контекстное меню и выберите «Открыть модуль объекта». Если конфигурация типовая и находится на поддержке, изменения лучше вносить через расширение конфигурации — так вы сохраните возможность обновления.

Порядок вызова событий при копировании выглядит так: платформа создаёт новый объект, копирует в него данные источника, затем вызывает ПриКопировании с параметром ОбъектКопирования — ссылкой на документ-источник. После этого открывается форма нового документа. Всё, что вы измените в обработчике, попадёт в форму и в итоговый документ после его записи пользователем.

Очистка одиночных реквизитов шапки

Самая частая задача — обнулить реквизит шапки: комментарий, ссылку на основание, служебный признак. В зависимости от типа реквизита используется разное пустое значение. Для ссылочных типов и составных типов удобно присваивать Неопределено, для строк — пустую строку, для чисел — ноль, для булевых значений — Ложь.

bsl
Процедура ПриКопировании(ОбъектКопирования)

	Комментарий = "";
	ДокументОснование = Неопределено;
	СуммаРучнаяКорректировка = 0;
	Согласовано = Ложь;

КонецПроцедуры

Более надёжный способ — не перечислять типы вручную, а присваивать реквизиту пустое значение его типа через метаданные. Это удобно, когда очищать нужно много реквизитов или тип реквизита может измениться при доработках конфигурации:

bsl
Процедура ПриКопировании(ОбъектКопирования)

	РеквизитыДляОчистки = Новый Массив;
	РеквизитыДляОчистки.Добавить("Комментарий");
	РеквизитыДляОчистки.Добавить("ДокументОснование");

	Для Каждого ИмяРеквизита Из РеквизитыДляОчистки Цикл
		ОписаниеРеквизита = Метаданные().Реквизиты.Найти(ИмяРеквизита);
		Если ОписаниеРеквизита <> Неопределено Тогда
			ЭтотОбъект[ИмяРеквизита] = ОписаниеРеквизита.Тип.ПривестиЗначение();
		КонецЕсли;
	КонецЦикла;

КонецПроцедуры

Метод ПривестиЗначение() без параметра возвращает значение по умолчанию для типа реквизита: пустую ссылку, пустую строку, ноль или Ложь. Такой код устойчив к переименованию типов и не сломается при изменении состава типов реквизита.

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

Табличные части очищаются методом Очистить(). Типичный сценарий — копирование документа-шаблона, где нужна только шапка, а строки товаров должны заполняться заново:

bsl
Процедура ПриКопировании(ОбъектКопирования)

	Товары.Очистить();
	Услуги.Очистить();

КонецПроцедуры

Иногда требуется не полная очистка, а частичная: например, оставить номенклатуру, но обнулить количество и цены. В этом случае строки не удаляются, а обходятся в цикле:

bsl
Процедура ПриКопировании(ОбъектКопирования)

	Для Каждого СтрокаТовара Из Товары Цикл
		СтрокаТовара.Количество = 0;
		СтрокаТовара.Цена = 0;
		СтрокаТовара.Сумма = 0;
	КонецЦикла;

КонецПроцедуры

Условная очистка: по виду операции, источнику или пользователю

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

bsl
Процедура ПриКопировании(ОбъектКопирования)

	Если ОбъектКопирования.ВидОперации <> ВидОперации Тогда
		ДоговорКонтрагента = Неопределено;
	КонецЕсли;

	Если Не Пользователи.ЭтоПолноправныйПользователь() Тогда
		РучнаяСкидка = 0;
	КонецЕсли;

КонецПроцедуры

Также полезно учитывать дату: при копировании документа прошлого периода часто имеет смысл очистить реквизиты, завязанные на старые цены, курсы или договоры, чтобы документ не ушёл в учёт с устаревшими данными.

Маршрут решения

Как выбрать способ очистки

Нужно очистить один-два реквизита фиксированного типаПрисвойте пустое значение напрямую: Неопределено, пустую строку, 0 или Ложь
Список очищаемых реквизитов большой или может менятьсяИспользуйте цикл по массиву имён с ПривестиЗначение() через метаданные
Табличную часть нужно заполнить зановоВызовите ТабличнаяЧасть.Очистить()
Очистка зависит от вида операции или прав пользователяДобавьте условия с анализом ОбъектКопирования и текущего пользователя

Отличия от ПриЗаполнении и ОбработкаЗаполнения

Частая путаница: разработчики пытаются очищать реквизиты в ОбработкаЗаполнения или ПриЗаполнении. Эти события работают иначе. ОбработкаЗаполнения вызывается при вводе на основании и при программном создании с данными заполнения, а при копировании через интерфейс она, как правило, не вызывается с данными источника. ПриЗаполнении — это событие формы, оно срабатывает при создании объекта в форме и зависит от параметров создания.

Ключевое отличие: ПриКопировании гарантированно вызывается именно при копировании и только при нём. Если очистить реквизит в ПриЗаполнении, это затронет и обычное создание документа, и ввод на основании — что чаще всего не требуется. Поэтому правило простое: логика «только для копии» — в ПриКопировании, логика «для любого нового документа» — в ОбработкаЗаполнения.

Сравнение событий заполнения

ПриКопировании

Вызывается только при копировании. Есть ссылка на источник. Подходит для очистки реквизитов именно в копии.

ОбработкаЗаполнения

Вызывается при вводе на основании и программном создании. Не срабатывает при обычном копировании через F9.

ПриЗаполнении (форма)

Срабатывает при создании объекта в форме по параметрам. Не вызывается при программном создании без формы.

Типичные ошибки и ограничения

Типичные ошибки
01
Очистка реквизита в ПриЗаполнении вместо ПриКопировании — реквизит стирается и при обычном создании документа, ломая стандартное заполнение
02
Вызов ЭтотОбъект.Записать() внутри ПриКопировании — приводит к преждевременной записи документа с номером и возможным конфликту с последующей записью из формы
03
Присвоение Неопределено реквизиту примитивного типа (число, булево) — в реквизите оказывается значение, не соответствующее типу, что вызывает ошибки при проведении
04
Очистка реквизитов, участвующих в обменах и синхронизации, — копия теряет связь с внешними системами, и при обмене возникают дубли
05
Забытая очистка табличной части с сериями или номерами ГТД — в копии остаются чужие серии, что искажает учёт

Ещё одно ограничение: ПриКопировании не вызывается, если документ создаётся программно методом Скопировать() у объекта — в этом случае разработчик сам управляет заполнением. Поэтому если в конфигурации есть механизмы пакетного копирования документов, логику очистки стоит вынести в отдельную экспортную процедуру и вызывать её из обоих мест.

Как реализовать очистку через расширение

Для типовых конфигураций рекомендуемый путь — расширение. В расширении добавьте документ в состав, откройте его модуль объекта и создайте обработчик с аннотацией &После:

bsl
&После("ПриКопировании")
Процедура Расш1_ПриКопировании(ОбъектКопирования)

	Комментарий = "";
	Товары.Очистить();

КонецПроцедуры

Аннотация &После означает, что сначала отработает типовой обработчик (если он есть), а затем ваш код. Это безопаснее, чем &Вместо, так как сохраняет типовую логику очистки служебных реквизитов, которую вендор мог добавить в обработчик.

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

Проверка результата

После внедрения проверьте доработку на нескольких сценариях: копирование проведённого документа, копирование непроведённого, копирование документа с другим видом операции. В каждом случае копия должна открываться с очищенными реквизитами, а остальные данные — сохраняться.

Контрольные точки

Как проверить результат

Открытие копии через F9
Норма

Целевые реквизиты пусты, остальные данные перенесены

Тревожный признак

Реквизит заполнен значением источника или очистились лишние поля

Проведение копии
Норма

Документ проводится без ошибок, движения корректны

Тревожный признак

Ошибки проведения из-за пустых обязательных реквизитов

Обычное создание документа
Норма

Стандартное заполнение нового документа работает как раньше

Тревожный признак

При создании нового документа реквизиты очищаются — значит, код попал не в то событие

Синхронизация и обмены
Норма

Копия корректно регистрируется к выгрузке

Тревожный признак

В обмене возникают дубли или ошибки сопоставления

Если копия не проводится из-за пустого обязательного реквизита — это сигнал, что очистка слишком агрессивна. Либо реквизит не нужно очищать, либо в обработчике следует заполнить его значением по умолчанию, а не оставлять пустым.

Удобный приём: держите список очищаемых реквизитов в одном массиве в начале обработчика. Когда бухгалтерия попросит добавить или убрать поле, правка займёт одну строку, и не придётся искать присвоения по всему коду.
ПЗ
Практическое замечание

Частые вопросы

Почему ПриКопировании не срабатывает при копировании документа?

Чаще всего обработчик размещён не в модуле объекта, а в модуле формы — событие ПриКопировании существует только у объекта. Также проверьте, что расширение применено к базе (обновление конфигурации БД выполнено) и что обработчик не перекрыт другим расширением с аннотацией &Вместо.

Можно ли очистить стандартный реквизит, например дату или организацию?

Технически — да, через то же присвоение пустого значения. Но очищать дату и номер не имеет смысла: платформа сама присваивает копии текущую дату и новый номер при записи. Организацию очищать стоит только если это осознанное требование учёта, иначе пользователю придётся заполнять её вручную в каждой копии.

Как очистить реквизит только у копий, созданных определённым пользователем?

Внутри ПриКопировании доступен контекст текущего сеанса: используйте ПользователиИнформационнойБазы.ТекущийПользователь() или функции общего модуля работы с пользователями и постройте условие по роли или имени пользователя. Учтите, что событие выполняется на сервере, поэтому клиентские функции там недоступны.

Чем очистка в ПриКопировании отличается от настройки «Заполнять при копировании» в свойствах реквизита?

В свойствах реквизита конфигуратора нет отдельного признака копирования — перенос значений при копировании выполняет платформа автоматически для всех реквизитов. Управлять этим можно только кодом в ПриКопировании. Поэтому доработка обработчика — единственный штатный способ выборочной очистки.

Будет ли работать очистка при копировании через внешнюю обработку или COM-соединение?

Нет. Событие ПриКопировании вызывается только при интерактивном копировании. Если документ копируется программно через Скопировать() или создаётся обработкой, логику очистки нужно продублировать в коде этой обработки — лучше через вызов общей экспортной процедуры.

Опасно ли очищать реквизиты, по которым документ участвует в критериях отбора?

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

Итог

Что важно запомнить

Очистка реквизитов при копировании выполняется в обработчике ПриКопировании модуля объекта: одиночные реквизиты сбрасываются присвоением пустого значения, табличные части — методом Очистить(). Для типовых конфигураций используйте расширение с аннотацией &После, не путайте событие с ПриЗаполнении и ОбработкаЗаполнения, и всегда проверяйте проведение копии и работу обменов после доработки.