В практике разработки на платформе 1С:Предприятие 8 часто возникает задача определить, является ли создаваемый документ новым (пустым) или он был создан путем копирования существующего объекта. Это необходимо для очистки специфических реквизитов (например, серийных номеров, статусов, дат), проверки прав доступа или предотвращения ошибок при заполнении данных пользователями. Рассмотрим подробно все доступные механизмы решения этой задачи.
Наиболее распространенный и эффективный способ для управляемых форм — это проверка параметров, передаваемых при открытии формы нового объекта. Когда пользователь нажимает кнопку «Скопировать» (или клавишу F9) в списке документов, платформа автоматически передает в форму специальный параметр ЗначениеКопирования.
Проанализируем программный код, который следует разместить в модуле формы документа:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, является ли объект новым
Если Объект.Ссылка.Пустая() Тогда
// Пытаемся получить параметр ЗначениеКопирования
СсылкаНаОригинал = Неопределено;
Если Параметры.Свойство("ЗначениеКопирования", СсылкаНаОригинал) Тогда
Если ЗначениеЗаполнено(СсылкаНаОригинал) Тогда
// Здесь мы точно знаем, что документ создан копированием.
// СсылкаНаОригинал содержит ссылку на документ-источник.
Сообщить("Документ создан копированием объекта: " + СсылкаНаОригинал);
// Пример: очистка реквизита, который не должен копироваться
Объект.Ответственный = Пользователи.ТекущийПользователь();
Объект.Дата = ТекущаяДатаСеанса();
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: Обратите внимание, что обращение к Параметры.ЗначениеКопирования напрямую может привести к ошибке «Поле объекта не обнаружено», если форма открывается в обычном режиме создания. Поэтому всегда используйте метод Свойство() для безопасного чтения.
Если логика должна срабатывать независимо от того, создается ли документ интерактивно через форму или программно в коде, следует использовать событие ПриКопировании в модуле самого объекта. Это событие вызывается платформой в момент создания нового объекта на основании существующего.
Разберем пример реализации в модуле объекта:
Процедура ПриКопировании(ОбъектКопирования)
// ОбъектКопирования — это ссылка на исходный документ
// В этот момент текущий объект (ЭтотОбъект) уже заполнен данными из оригинала
// Мы можем пометить документ специальным признаком
ЭтотОбъект.Комментарий = "Создан копированием из " + Строка(ОбъектКопирования);
// Или очистить табличную часть, если её нельзя копировать
// ЭтотОбъект.Товары.Очистить();
КонецПроцедуры
Этот метод считается более «фундаментальным», так как он гарантирует выполнение кода даже при программном вызове метода Скопировать().
Проанализируем еще одну системную процедуру — ОбработкаЗаполнения. Она вызывается первой при создании любого объекта. Если документ копируется, в параметр ДанныеЗаполнения передается ссылка на исходный объект.
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// Проверяем, не является ли это вводом на основании (через проверку параметра ТекстЗаполнения)
// Если ТекстЗаполнения пустой, скорее всего, это копирование.
// Однако метод ПриКопировании для этих целей подходит лучше.
КонецЕсли;
КонецПроцедуры
Если вы работаете в расширении и вам нужно изменить поведение типовой конфигурации, используйте аннотацию &После для процедуры ПриСозданииНаСервере. В некоторых релизах платформы или в зависимости от логики конкретной конфигурации (например, КА или ERP), параметры могут передаваться в структуру ПараметрыСоздания.
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// В расширениях иногда параметр называется ИсточникКопирования
Если Параметры.Свойство("ИсточникКопирования") Тогда
Если ЗначениеЗаполнено(Параметры.ИсточникКопирования) Тогда
// Выполняем действия при копировании
Объект.Артикул = "";
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Иногда требуется выяснить, был ли документ скопирован «задним числом», когда действие уже совершено и программист не предусмотрел специальный флаг. В этом случае мы можем использовать косвенные признаки:
F9 идентификаторы строк табличных частей часто переносятся «как есть». Проверка совпадения GUID строк в двух разных документах одного автора — весомый аргумент.Важно не путать эти два механизма. Для их разделения в ПриСозданииНаСервере проверяются разные параметры:
Параметры.ЗначениеКопирования — заполняется при копировании (F9).Параметры.Основание — заполняется при создании на основании другого типа документа.Выясним, можно ли определить факт копирования в процедуре ПриОткрытии на клиенте. Напрямую параметр ЗначениеКопирования в ЭтаФорма.Параметры на клиенте может быть недоступен (зависит от версии платформы и настроек формы).
Рекомендация: Если вам нужен этот признак на клиенте, создайте Реквизит формы (тип Булево, например, ЭтоКопия) и заполните его в ПриСозданииНаСервере. После этого вы сможете обращаться к нему в любом месте клиентского кода.
Подводя итог, можно сказать: для оперативного вмешательства в процесс создания используйте ЗначениеКопирования в форме, а для обеспечения целостности данных на уровне базы — процедуру ПриКопировании в модуле объекта. Для практического исследования последовательности вызова событий платформы пригодится инструмент для отслеживания событий 1С.