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

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

При разработке конфигураций на платформе 1С часто возникает типовая задача: при создании нового элемента справочника (например, «Задания») необходимо автоматически подставить значение реквизита по умолчанию (например, «Канал» из справочника «КаналыРаспространения»), специфичное для текущего пользователя. Затем, на основании выбранного канала, требуется подтянуть зависимые параметры (например, «Поле1» и «Поле2»), динамически обновлять их при смене канала в форме и обновлять значения в исходном справочнике при сохранении. Разберем по шагам, как решить эту цепочку задач методически грамотно с точки зрения клиент-серверной архитектуры управляемых форм.

1. Инициализация реквизитов нового элемента: выбор правильного обработчика

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

  1. Событие ПриУстановкеНовогоКода вызывается исключительно в момент фактической записи объекта в базу данных (когда срабатывает автонумерация), а не в момент открытия формы нового элемента.
  2. Событие ПриОткрытии выполняется на клиенте, что требует дополнительных контекстных серверных вызовов.

Методически верным местом для установки начальных значений является обработчик ОбработкаЗаполнения в модуле объекта. Это гарантирует, что объект будет корректно инициализирован как при интерактивном создании через интерфейс, так и при программном создании с помощью метода Справочники.Задания.СоздатьЭлемент().


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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	// Проверяем, что создается новый элемент (ключ пустой)
	Если Не ЗначениеЗаполнено(Параметры.Ключ) Тогда
		// Логика инициализации реквизитов Объект.Канал, Объект.Поле1, Объект.Поле2
	КонецЕсли;
	
КонецПроцедуры

2. Хранение индивидуальных настроек пользователей

Проанализируем варианты хранения персональных значений пользователей (например, основного канала):

  1. ХранилищеОбщихНастроек — встроенный платформенный механизм. Данные сохраняются в системной таблице информационной базы в разрезе пользователей 1С. Это означает, что настройки не привязаны к конкретному компьютеру: если пользователь зайдет под своей учетной записью с другого рабочего места, настройки сохранятся.
  2. Регистр сведений — оптимальный вариант, если требуется предоставить администраторам или ответственным лицам возможность централизованно просматривать и редактировать настройки всех пользователей через привычный интерфейс списков.

3. Динамическое обновление зависимых полей при изменении канала на форме

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

Для минимизации трафика между клиентом и сервером используем неконтекстный серверный вызов с директивой &НаСервереБезКонтекста. В процедуру передается только ссылка на выбранный канал, а возвращается структура с нужными значениями:


&НаКлиенте
Процедура КаналПриИзменении(Элемент)
	
	Если ЗначениеЗаполнено(Объект.Канал) Тогда
		ПараметрыКанала = ПолучитьПараметрыКаналаНаСервере(Объект.Канал);
		Объект.Поле1 = ПараметрыКанала.Поле1;
		Объект.Поле2 = ПараметрыКанала.Поле2;
	Иначе
		Объект.Поле1 = "";
		Объект.Поле2 = "";
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьПараметрыКаналаНаСервере(СсылкаНаКанал)
	
	Результат = Новый Структура("Поле1,Поле2");
	
	// Считываем реквизиты без получения тяжелого объекта в память
	Результат.Поле1 = СсылкаНаКанал.Поле1;
	Результат.Поле2 = СсылкаНаКанал.Поле2;
	
	Возврат Результат;
	
КонецФункции

4. Сохранение измененных параметров обратно в справочник «КаналыРаспространения»

Если по бизнес-логике требуется, чтобы введенные в задании значения «Поле1» и «Поле2» перезаписывали значения по умолчанию в самом элементе «КаналыРаспространения», данную операцию методически правильно выполнять в модуле объекта СправочникОбъект.Задания в обработчике ПередЗаписью или ПриЗаписи.

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


// Модуль объекта справочника "Задания"
Процедура ПередЗаписью(Отказ, РежимЗаписи)
	
	Если ЗначениеЗаполнено(ЭтотОбъект.Канал) Тогда
		
		ОбъектКанал = ЭтотОбъект.Канал.ПолучитьОбъект();
		
		Если ОбъектКанал <> Неопределено Тогда
			// Проверяем фактическое изменение данных для оптимизации
			Если ОбъектКанал.Поле1 <> ЭтотОбъект.Поле1 
				Или ОбъектКанал.Поле2 <> ЭтотОбъект.Поле2 Тогда
				
				ОбъектКанал.Поле1 = ЭтотОбъект.Поле1;
				ОбъектКанал.Поле2 = ЭтотОбъект.Поле2;
				
				Попытка
					ОбъектКанал.Записать();
				Исключение
					Отказ = Истина;
					ВызватьИсключение "Не удалось обновить параметры канала: " + ОписаниеОшибки();
				КонецПопытки;
				
			КонецЕсли;
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

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

← На главную