Как при копировании справочника перенести данные из регистра сведений в реквизиты новой формы?

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

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

Рассмотрим подробнее, как правильно организовать этот процесс, разберем типичные ошибки и проанализируем лучшие практики архитектуры платформы.

Метод 1. Использование обработчика ОбработкаЗаполнения в модуле объекта

Наиболее правильным и «красивым» решением с точки зрения архитектуры является использование серверного события модуля объекта ОбработкаЗаполнения. Этот метод вызывается платформой автоматически в момент создания нового объекта, в том числе при копировании.

Проанализируем ситуацию: когда пользователь нажимает кнопку «Скопировать», платформа передает в параметр ДанныеЗаполнения ссылку на исходный объект (Объект-источник). Мы можем использовать эту ссылку для получения данных из регистра сведений.

Разберем пример кода в модуле объекта справочника Номенклатура:


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

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

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

Метод 2. Перехват данных в модуле управляемой формы

После того как данные были подготовлены в модуле объекта, нам нужно «поднять» их на форму. Это делается в обработчике ПриСозданииНаСервере. Выясним, как это работает: форма создается на основе объекта, и у нас есть доступ к расширению этого объекта.


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

Этот подход гарантирует, что данные будут получены один раз при инициализации и пользователь сразу увидит их в интерфейсе еще до того, как нажмет кнопку «Записать».

Метод 3. Программное управление ссылкой (УстановитьСсылкуНового)

Иногда программисты пытаются использовать метод УстановитьСсылкуНового(), чтобы сразу получить ссылку и записать данные в регистр. Посмотрим на риски этого метода: если вы запишете данные в регистр сведений по этой «будущей» ссылке, а пользователь в итоге передумает и закроет форму без сохранения (нажмет «Отмена»), в базе данных останется «битая» запись. В регистре будет ссылка, которой не существует в справочнике.

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

Метод 4. Работа с набором записей как реквизитом формы

Если данных в регистре много (например, таблица цен или спецификаций), мы можем пойти другим путем — добавить на форму реквизит с типом РегистрСведенийНаборЗаписей.ИмяРегистра.

Рассмотрим алгоритм действий:

  1. Добавляем реквизит формы (например, НаборПараметров) с типом соответствующего набора записей.
  2. В событии ПриСозданииНаСервере, если передан параметр ЗначениеКопирования, читаем набор записей по источнику.
  3. Очищаем измерение (владельца) в прочитанном наборе, чтобы он считался «новым».

Пример заполнения набора записей при копировании:


&НаСервере
Процедура ЗаполнитьНаборПриКопировании(СсылкаИсточник)
	
	НаборЗаписей = РегистрыСведений.ПараметрыИзделия.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Номенклатура.Установить(СсылкаИсточник);
	НаборЗаписей.Прочитать();
	
	// Копируем данные из набора в реквизит формы (НаборПараметров)
	ЗначениеВДанныеФормы(НаборЗаписей, НаборПараметров);
	
	// Важно: в НабореПараметров на форме нужно будет 
	// при записи установить новую ссылку текущего объекта
КонецПроцедуры

Метод 5. Использование параметров формы

Если копирование происходит программно (например, из другой формы), мы можем передать данные через структуру Параметры. Проанализируем ситуацию: мы вызываем ОткрытьФорму и передаем туда готовую структуру с данными из регистра.


// В исходной форме
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ЗначениеКопирования", СсылкаНаОбъект);
ПараметрыОткрытия.Вставить("ДополнительныеПараметрыИзРегистра", ПолучитьСтруктуруИзРегистра(СсылкаНаОбъект));

ОткрытьФорму("Справочник.Номенклатура.ФормаОбъекта", ПараметрыОткрытия);

Затем в целевой форме в ПриСозданииНаСервере мы просто считываем Параметры.ДополнительныеПараметрыИзРегистра и распределяем их по полям ввода.

Подведение итогов

Для решения задачи копирования данных из регистра в управляемую форму справочника мы рекомендуем придерживаться следующих правил:

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

← На главную