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