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