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