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