При разработке интеграций и автоматизации ввода данных часто возникает задача: открыть форму нового элемента справочника (например, КонтактныеЛица, Контрагенты или ФизическиеЛица) из внешней обработки или документа, сразу заполнив контактную информацию — телефон, email или юридический адрес.
Нередко разработчики сталкиваются с неожиданным поведением: значения передаются в форму на клиенте, записываются в реквизиты объекта или в служебную таблицу формы, но на самом экране поля ввода остаются абсолютно пустыми. При этом после нажатия пользователем кнопки «Записать и закрыть» данные успешно сохраняются, и при повторном открытии карточки всё отображается на своих местах. Разберем подробно, почему так происходит и как правильно организовать заполнение контактной информации в конфигурациях на базе «1С:Библиотеки стандартных подсистем» (БСП).
Проанализируем архитектуру подсистемы «Контактная информация» БСП на управляемых формах. В типовых конфигурациях поля ввода для контактной информации не привязаны напрямую к реквизитам табличной части Объект.КонтактнаяИнформация. Привычный механизм связи элементов формы с данными здесь работает иначе:
ПриСозданииНаСервере общий модуль БСП динамически добавляет на форму новые реквизиты с системными именами вида КонтактнаяИнформацияПоле<УникальныйИдентификатор> и связанные с ними элементы управления.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов предназначена для хранения описания структуры полей, типов и привязок. Прямое изменение значений колонок Представление или ЗначенияПолей в этой таблице на клиенте не вызывает автоматической передачи данных в динамические реквизиты формы.Объект.КонтактнаяИнформация на стороне клиента уже после создания формы, созданные сервером элементы управления не обновят свое отображение, так как они инициализируются только один раз при компоновке формы на сервере.Наиболее надежный и платформенный способ — передать данные до того, как форма начнет создавать свои элементы управления на сервере. Для этого воспользуемся механизмом заполнения нового объекта платформы «1С:Предприятие».
Рассмотрим порядок событий: когда мы передаем в метод ОткрытьФорму параметр ЗначенияЗаполнения, платформа сначала выполняет процедуру ОбработкаЗаполнения в модуле объекта и лишь затем вызывает событие формы ПриСозданииНаСервере. В этот момент модуль БСП считывает уже заполненную табличную часть объекта и корректно инициализирует все динамические элементы формы.
Разберем код клиентской процедуры вызова формы:
&НаКлиенте
Процедура СоздатьКонтактноеЛицо(Команда)
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьЗначение", ЭтаФорма);
// Формируем структуру данных для передачи в новый объект
СтруктураЗаполнения = Новый Структура;
СтруктураЗаполнения.Вставить("Владелец", Запись.Контрагент);
СтруктураЗаполнения.Вставить("Наименование", Запись.КонтактноеЛицо);
// Передаем список контактной информации через произвольный реквизит структуры
МассивКИ = Новый Массив;
Если ЗначениеЗаполнено(Запись.Телефон) Тогда
ДанныеТелефона = Новый Структура;
ДанныеТелефона.Вставить("Тип", "Телефон");
ДанныеТелефона.Вставить("Значение", Запись.Телефон);
МассивКИ.Добавить(ДанныеТелефона);
КонецЕсли;
Если ЗначениеЗаполнено(Запись.Емайл) Тогда
ДанныеПочты = Новый Структура;
ДанныеПочты.Вставить("Тип", "Email");
ДанныеПочты.Вставить("Значение", Запись.Емайл);
МассивКИ.Добавить(ДанныеПочты);
КонецЕсли;
СтруктураЗаполнения.Вставить("СписокКонтактнойИнформации", МассивКИ);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначенияЗаполнения", СтруктураЗаполнения);
ОткрытьФорму(
"Справочник.КонтактныеЛица.ФормаОбъекта",
ПараметрыФормы,
ЭтаФорма,
,
,
,
ОписаниеОповещения,
РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс
);
КонецПроцедуры
Теперь перейдем в модуль объекта справочника КонтактныеЛица и опишем обработку переданных данных:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
Если ДанныеЗаполнения.Свойство("Владелец") Тогда
ЭтотОбъект.Владелец = ДанныеЗаполнения.Владелец;
КонецЕсли;
Если ДанныеЗаполнения.Свойство("Наименование") Тогда
ЭтотОбъект.Наименование = ДанныеЗаполнения.Наименование;
КонецЕсли;
// Обработка переданной контактной информации
Если ДанныеЗаполнения.Свойство("СписокКонтактнойИнформации")
И ТипЗнч(ДанныеЗаполнения.СписокКонтактнойИнформации) = Тип("Массив") Тогда
Для Каждого ЭлементКИ Из ДанныеЗаполнения.СписокКонтактнойИнформации Цикл
Если ЭлементКИ.Тип = "Телефон" Тогда
ВидКИ = Справочники.ВидыКонтактнойИнформации.ТелефонКонтактногоЛица;
ИначеЕсли ЭлементКИ.Тип = "Email" Тогда
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтактногоЛица;
Иначе
Продолжить;
КонецЕсли;
СтрокаКИ = ЭтотОбъект.КонтактнаяИнформация.Добавить();
СтрокаКИ.Вид = ВидКИ;
СтрокаКИ.Тип = ВидКИ.Тип;
СтрокаКИ.Представление = ЭлементКИ.Значение;
// Для корректной валидации преобразуем представление в формат БСП
СтрокаКИ.ЗначенияПолей = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияПоПредставлению(
ЭлементКИ.Значение,
ВидКИ
);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: при формировании структуры передачи избегайте совпадения имен ключей с предопределенными реквизитами и табличными частями (например, не используйте ключ структуры с именем КонтактнаяИнформация, если вы передаете массив произвольного формата). Платформа при инициализации объекта попытается автоматически сопоставить коллекцию с табличной частью объекта, что приведет к ошибке несоответствия типов.
Если по каким-либо причинам редактировать модуль объекта нельзя (например, конфигурация находится на полной типовой поддержке без возможности внесения изменений в модули объектов), форму можно заполнить непосредственно на клиенте.
Выясним, где хранятся имена сгенерированных элементов. В таблице КонтактнаяИнформацияОписаниеДополнительныхРеквизитов присутствует колонка ИмяРеквизита, в которой записано точное имя созданного на форме динамического свойства. Если записать значение напрямую в это свойство формы по его имени, оно моментально отобразится на экране:
&НаКлиенте
Процедура ЗаполнитьКИНаФорме(ФормаНовогоЭлемента, ВидКИ, НовоеЗначение)
Отбор = Новый Структура("Вид", ВидКИ);
НайденныеСтроки = ФормаНовогоЭлемента.КонтактнаяИнформацияОписаниеДополнительныхРеквизитов.НайтиСтроки(Отбор);
Если НайденныеСтроки.Количество() > 0 Тогда
ИмяДинамическогоРеквизита = НайденныеСтроки[0].ИмяРеквизита;
// Присваиваем значение напрямую в динамический реквизит формы
ФормаНовогоЭлемента[ИмяДинамическогоРеквизита] = НовоеЗначение;
// Обновляем служебную строку метаданных
НайденныеСтроки[0].Представление = НовоеЗначение;
НайденныеСтроки[0].ЗначенияПолей = НовоеЗначение;
КонецЕсли;
КонецПроцедуры
Когда интерактивное создание карточки с нуля не принципиально, самым чистым архитектурным решением будет предварительное создание и сохранение объекта на сервере с помощью штатного программного интерфейса БСП:
Справочники.КонтактныеЛица.СоздатьЭлемент().УправлениеКонтактнойИнформацией.КонтактнаяИнформацияПоПредставлению(), чтобы БСП сгенерировала корректный XML/JSON в реквизитах ЗначенияПолей и Значение.Записать().Ключ со ссылкой на записанный объект. Форма откроется в стандартном режиме чтения, а все поля контактной информации будут штатно отображены.