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