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