В разработке на платформе 1С:Предприятие 8.3 (управляемые формы) часто возникает задача интерактивного взаимодействия между различными окнами. Типичный сценарий: на основной форме (например, «Рабочий стол») расположены две таблицы. Из первой таблицы мы открываем форму подбора, чтобы уточнить количество или цену товара, а результат должны поместить во вторую таблицу, которая формально не является «родителем» или «владельцем» для окна подбора. Разберем детально, как реализовать такую передачу данных, используя стандартные механизмы платформы.
Рассмотрим ситуацию, описанную автором: есть ФормаОсновная, на ней ТаблицаОстатки и ТаблицаВыбранныеТовары. При выборе строки в ТаблицаОстатки открывается ФормаПодбора. После ввода количества в ФормаПодбора данные должны попасть в ТаблицаВыбранныеТовары. Основная сложность для новичков заключается в том, что по умолчанию форма подбора «знает» только своего владельца, а нам нужно передать данные в конкретный элемент интерфейса или просто вернуть их на основную форму для дальнейшего распределения.
Для решения этой задачи в 1С существует три основных способа:
Оповестить() (гибкий путь для несвязанных форм).Проанализируем этот метод как самый простой в реализации. Его суть заключается в том, что открываемая форма при закрытии вызывает метод ОповеститьОВыборе(), а форма-владелец ловит эти данные в предопределенном обработчике ОбработкаВыбора.
Выясним, как правильно вызвать форму, чтобы она считала основную форму своим владельцем. Посмотрим на пример кода в основной форме:
&НаКлиенте
Процедура ТаблицаОстаткиВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отменяем стандартное действие
// Подготавливаем параметры для открытия формы подбора
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Товар", Элементы.ТаблицаОстатки.ТекущиеДанные.Товар);
ПараметрыФормы.Вставить("Цена", Элементы.ТаблицаОстатки.ТекущиеДанные.Цена);
// Открываем форму, указывая Владельцем ТЕКУЩУЮ ФОРМУ (ЭтаФорма)
// Это критически важно для работы ОбработкаВыбора
ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаПодбора", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры
Теперь рассмотрим, как передать данные обратно из формы подбора при нажатии кнопки «ОК» или «Перенести»:
&НаКлиенте
Процедура КомандаПеренестиДанные(Команда)
// Формируем структуру с результатами подбора
СтруктураРезультата = Новый Структура;
СтруктураРезультата.Вставить("Товар", Объект.Товар);
СтруктураРезультата.Вставить("Количество", Объект.Количество);
СтруктураРезультата.Вставить("Сумма", Объект.Цена * Объект.Количество);
// Отправляем данные владельцу и закрываем форму
ОповеститьОВыборе(СтруктураРезультата);
КонецПроцедуры
Наконец, нам нужно принять эти данные в основной форме. Для этого создадим обработчик события формы ОбработкаВыбора:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
// Проверяем, что к нам пришла именно наша структура
Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") И ВыбранноеЗначение.Свойство("Товар") Тогда
// Добавляем данные во ВТОРУЮ таблицу (неподчиненную)
НоваяСтрока = Объект.ТаблицаВыбранныеТовары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ВыбранноеЗначение);
КонецЕсли;
КонецПроцедуры
Если формы открыты независимо друг от друга и вы не можете (или не хотите) явно назначать одну форму владельцем другой, используем метод Оповестить(). Рассмотрим этот механизм подробнее. Он позволяет отправить «сигнал» всем открытым окнам приложения.
В форме подбора (отправитель):
&НаКлиенте
Процедура ЗавершитьПодбор(Команда)
Данные = Новый Структура("Товар, Количество", Объект.Товар, Объект.Количество);
// Имя события должно быть уникальным, чтобы другие формы не среагировали случайно
Оповестить("ЗавершениеПодбораТовара", Данные);
Закрыть();
КонецПроцедуры
В основной форме (получатель) нужно создать обработчик события ОбработкаОповещения. Обратите внимание, что это событие самой формы, а не конкретной таблицы.
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ЗавершениеПодбораТовара" Тогда
// Обрабатываем полученную структуру данных
НоваяСтрока = Объект.ТаблицаВыбранныеТовары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Параметр);
// Если вторая таблица — это Динамический Список,
// данные нужно сначала записать в БД, а список обновится сам
КонецЕсли;
КонецПроцедуры
Разберем наиболее продвинутый метод, который стал стандартом в современной разработке. Он исключает путаницу в событии ОбработкаВыбора, если на форме вызывается сразу несколько разных подборов.
Суть метода: при открытии формы мы сразу передаем ей «адрес» процедуры, которую нужно выполнить после закрытия окна подбора. Посмотрим на пример реализации в основной форме:
&НаКлиенте
Процедура ОткрытьПодборСУмнымВозвратом()
// 1. Создаем описание оповещения, указывая имя экспортной (!) процедуры
ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияФормыПодбора", ЭтаФорма);
// 2. Открываем форму, передавая оповещение в 7-й параметр
ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаПодбора", , ЭтаФорма, , , , ОповещениеОЗакрытии);
КонецПроцедуры
&НаКлиенте
// Процедура ДОЛЖНА БЫТЬ ЭКСПОРТНОЙ
Процедура ПослеЗакрытияФормыПодбора(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
// Результат — это то, что мы передали в Закрыть() в форме подбора
НоваяСтрока = Объект.ТаблицаВыбранныеТовары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Результат);
КонецЕсли;
КонецПроцедуры
В форме подбора нам достаточно просто вызвать метод Закрыть() с передаваемым значением:
&НаКлиенте
Процедура КнопкаОК(Команда)
Результат = Новый Структура("Товар, Цена", Объект.Товар, Объект.Цена);
Закрыть(Результат); // Параметр попадет в процедуру ПослеЗакрытияФормыПодбора
КонецПроцедуры
Проанализируем ситуацию, если ваша вторая таблица — это не просто ТаблицаЗначений, а ДинамическийСписок. Это в корне меняет подход. Динамический список напрямую редактировать нельзя. Если форма подбора должна добавить строку в такой список, алгоритм должен быть следующим:
ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура")) или аналогичный для вашего объекта.Помните про типизацию: при передаче данных через структуры старайтесь передавать ссылки (СправочникСсылка), а не строковые наименования. Это позволит избежать ошибок при поиске объектов в принимающей форме.
Рассмотренные методы покрывают 100% потребностей при взаимодействии управляемых форм. Выбор конкретного способа зависит от сложности вашей конфигурации: для простых подборов используйте ОповеститьОВыборе, для сложных систем с множеством окон — ОписаниеОповещения.