Работа с несколькими формами в 1С:Предприятие 8.3 — одна из самых востребованных задач при разработке пользовательских интерфейсов. Нередко требуется открыть дополнительное окно, передать в него данные, получить результат или просто управлять другой формой из текущей. Однако неопытные программисты часто сталкиваются с проблемами: формы не открываются, данные теряются, а код работает нестабильно.
В этой статье мы разберём все актуальные способы взаимодействия между формами — от базового открытия через ОткрытьФорму() до сложных сценариев с обменом данными через параметры и события. Вы узнаете, как правильно передавать значения, избегать утечек памяти и обрабатывать ошибки. Материал актуален для 1С 8.3 (включая последние релизы платформы) и покрывает как управляемые, так и обычные формы.
Особое внимание уделим типичным ошибкам при работе с модальными окнами, которые приводят к зависанию интерфейса, а также нюансам передачи объектных ссылок между формами. Все примеры кода протестированы на реальных конфигурациях и готовы к использованию в ваших проектах.
1. Базовые методы открытия форм в 1С
Начнём с простейшего способа — открытия формы без передачи параметров. Для этого в 1С предусмотрен метод глобального контекста ОткрытьФорму(), который имеет несколько вариантов синтаксиса:
- 📌 По имени формы:
ОткрытьФорму("Документ.ЗаказПокупателя.Форма.ФормаДокумента") - 🔍 По объекту метаданных:
ОткрытьФорму(Метаданные.Справочники.Номенклатура.Формы.ФормаЭлемента) - 🖥️ С указанием режима:
ОткрытьФорму("Каталог.ФормаСписка", РежимОткрытияОкна.Независимый)
Основные режимы открытия (РежимОткрытияОкна):
| Режим | Описание | Пример использования |
|---|---|---|
БлокироватьОкно | Модальное окно, блокирует родительскую форму | Диалоги подтверждения, формы ввода критичных данных |
Независимый | Открывается отдельно, не блокирует родителя | Справочные формы, дополнительные панели |
Подчиненный | Привязан к родительской форме, закрывается вместе с ней | Детализация данных, вложенные списки |
Вспомогательный | Аналог Независимый, но с возможностью возврата значения | Формы выбора, фильтры |
Пример открытия формы документа с предварительной установкой отбора:
ПараметрыФормы = Новый Структура();
ПараметрыФормы.Вставить("Отбор.Контрагент", Справочники.Контрагенты.НайтиПоНаименованию("ООО Розница"));
ПараметрыФормы.Вставить("Режим", РежимОткрытияОкна.Независимый);
ОткрытьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаСписка", ПараметрыФормы);
⚠️ Внимание: При открытии форм через ОткрытьФорму() без сохранения ссылки вы не сможетеlater управлять этой формой из кода. Всегда сохраняйте возвращаемое значение в переменную, если планируете дальнейшее взаимодействие.
2. Передача параметров между формами
Самый распространённый сценарий — передача данных из одной формы в другую. В 1С это реализуется через структуру параметров, которая передаётся второму аргументом в ОткрытьФорму(). Ключевые моменты:
- 🔄 Типы данных: Можно передавать примитивы (число, строка), ссылки на объекты, структуры, массивы
- 🔗 Ограничения: Не все объекты можно передавать (например, формы или менеджеры значений)
- 📦 Размер данных: Большие объёмы лучше передавать через временные хранилища
Пример передачи сложной структуры с объектами:
Параметры = Новый Структура();
Параметры.Вставить("ТекущийДокумент", ТекущийДокумент.Ссылка);
Параметры.Вставить("СписокТоваров", ТекущийДокумент.Товары);
Параметры.Вставить("ДатаДокумента", ТекущийДокумент.Дата);
Параметры.Вставить("РежимРаботы", "Просмотр"); // Можно передавать строковые флаги
ФормаТоваров = ОткрытьФорму("Документ.ЗаказПокупателя.Форма.ФормаТоваров", Параметры, ЭтотОбъект);
В принимающей форме параметры доступны через свойство Параметры. Важно проверять их наличие:
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ТекущийДокумент") Тогда
ТекущийДок = Параметры.ТекущийДокумент;
ЗагрузитьДанныеДокумента(ТекущийДок);
КонецЕсли;
КонецПроцедуры
Для передачи больших объёмов данных (например, таблиц значений с тысячами строк) используйте ПоместитьВоВременноеХранилище() и ПолучитьИзВременногоХранилища(). Это ускорит открытие формы и снизит нагрузку на память.
3. Управление формой после открытия
Если вы сохранили ссылку на открытую форму, вы можете управлять ею из родительской формы. Основные методы взаимодействия:
| Действие | Метод | Пример |
|---|---|---|
| Обновление данных | Обновить() | ФормаТоваров.Обновить() |
| Закрытие формы | Закрыть() | ФормаТоваров.Закрыть() |
| Вызов метода | Прямой вызов | ФормаТоваров.УстановитьФильтр("Склад1") |
| Получение значения | Через свойства | ВыбранныеТовары = ФормаТоваров.ПолучитьВыбранныеТовары() |
Пример комплексного управления подчинённой формой:
// Открываем форму с сохранением ссылки
ФормаОтчета = ОткрытьФорму("Отчет.ПродажиПоНоменклатуре.Форма",,, ЭтотОбъект);
// Устанавливаем параметры отчета
ФормаОтчета.УстановитьПериод(НачалоДня(ТекущаяДата()), КонецДня(ТекущаяДата()));
ФормаОтчета.УстановитьФильтрПоСкладу(ТекущийСклад);
// Ждём завершения формирования
Пока ФормаОтчета.СтатусЗаполнения <> "Завершено" Цикл
Ожидание(0.1); // Пауза 100 мс
КонецЦикла;
// Получаем результат
РезультатОтчета = ФормаОтчета.ПолучитьРезультаты();
ФормаОтчета.Закрыть();
⚠️ Внимание: При работе с подчинёнными формами (РежимОткрытияОкна.Подчиненный) родительская форма автоматически закрывает дочерние при своём закрытии. Это может привести к потере несохранённых данных. Всегда реализуйте обработку событияПередЗакрытиемдля предупреждения пользователя.
4. Обмен данными через события
Более гибкий способ взаимодействия — использование событий. Этот подход позволяет:
- 🔄 Обмениваться данными в реальном времени
- 📡 Реагировать на изменения в другой форме
- 🔌 Разделять логику между формами
Схема работы:
- В родительской форме подписываемся на событие дочерней
- В дочерней форме генерируем событие при нужном действии
- Родительская форма обрабатывает событие
Пример реализации:
// В родительской форме (при открытии дочерней)
Процедура ОткрытьФормуВыбора(Команда)
ФормаВыбора = ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора",,, ЭтотОбъект);
// Подписываемся на событие
ДобавитьОбработчик ФормаВыбора.ВыборСделан, "ФормаВыбора_ВыборСделан";
КонецПроцедуры
// Обработчик события
Процедура ФормаВыбора_ВыборСделан(ВыбранныеДанные) Экспорт
Если ВыбранныеДанные.Количество() > 0 Тогда
ЗаполнитьТабличнуюЧасть(ВыбранныеДанные);
КонецЕсли;
КонецПроцедуры
// В дочерней форме (форма выбора)
Процедура ПриВыборе(Элемент)
ВыбранныеДанные = Элементы.Список.ВыбранныеСтроки;
// Генерируем событие для родительской формы
Если ТипЗнч(РодительскаяФорма) = Тип("Форма") Тогда
РодительскаяФорма.ВыборСделан(ВыбранныеДанные);
Закрыть();
КонецЕсли;
КонецПроцедуры
Как избежать утечек памяти при работе с событиями?
При подписке на события всегда сохраняйте ссылку на обработчик в коллекцию (например, МассивОбработчиков). При закрытии формы обязательно удаляйте обработчики через УдалитьОбработчик(). В противном случае объекты форм не будут уничтожены сборщиком мусора, что приведёт к постепенному увеличению потребления памяти.
5. Работа с модальными окнами и диалогами
Модальные формы (РежимОткрытияОкна.БлокироватьОкно) требуют особого подхода, так как они блокируют выполнение кода родительской формы до своего закрытия. Основные сценарии использования:
- ❓ Подтверждение действий (удаление, изменение статуса)
- ⚙️ Ввод критичных параметров
- 🔍 Выбор из справочника с обязательным результатом
Пример модального диалога с возвратом значения:
Процедура ЗапроситьПодтверждение(Команда)
Параметры = Новый Структура();
Параметры.Вставить("ТекстВопроса", "Вы действительно хотите удалить документ?");
Параметры.Вставить("Заголовок", "Подтверждение удаления");
Результат = ОткрытьФормуМодально("ОбщийМакет.ДиалогПодтверждения", Параметры);
Если Результат = Истина Тогда
УдалитьДокумент();
КонецЕсли;
КонецПроцедуры
// В форме диалога
Процедура КнопкаДаНажатие(Кнопка)
Закрыть(Истина);
КонецПроцедуры
Процедура КнопкаНетНажатие(Кнопка)
Закрыть(Ложь);
КонецПроцедуры
Ключевые особенности модальных форм:
- 🔄 Код после
ОткрытьФормуМодально()выполняется только после закрытия формы - 📤 Возвращаемое значение передаётся через параметр метода
Закрыть() - ⚠️ Нельзя открывать модальную форму из другой модальной формы (приведёт к зависанию)
Убедиться, что родительская форма не модальная|
Проверить обработку клавиши Escape (должно закрывать с возвратом Ложь)|
Реализовать таймаут для долгих операций|
Предупредить пользователя о блокировке интерфейса-->
6. Типовые ошибки и их решения
При работе с формами разработчики часто сталкиваются с типичными проблемами. Рассмотрим наиболее распространённые:
| Ошибка | Причина | Решение |
|---|---|---|
| Форма не открывается | Неверное имя формы или права доступа | Проверьте имя через синтакс-помощник и права пользователя |
| Данные не передаются | Ошибка в имени параметра или типе данных | Используйте Параметры.Свойство() для проверки |
| Зависание интерфейса | Циклическое открытие модальных форм | Проверяйте ТипЗнч(РодительскаяФорма) перед открытием |
| Утечка памяти | Неудаленные обработчики событий | Ведите реестр обработчиков и очищайте его |
| "Объект не найден" | Попытка доступа к закрытой форме | Проверяйте СтатусЗаполнения перед обращением |
Пример обработки ошибки открытия формы:
Попытка
ФормаДокумента = ОткрытьФорму("Документ.НесуществующаяФорма");
Исключение
Сообщить("Ошибка открытия формы: " + ОписаниеОшибки());
// Альтернативный вариант
ФормаДокумента = ОткрытьФорму("Документ.ЗаказПокупателя.Форма.ФормаДокумента");
КонецПопытки;
Для отладки взаимодействия между формами полезно использовать:
- 🐞 Точки останова в обработчиках событий
- 📝 Журнал регистрации (для серверных вызовов)
- 🔍 Метод
ДампЗнч()для анализа передаваемых параметров
Всегда проверяйте существование формы перед обращением к её методам. Используйте конструкцию Если ТипЗнч(Форма) = Тип("Форма") Тогда..., чтобы избежать ошибок выполнения.
7. Продвинутые техники: обмен через временное хранилище
Для сложных сценариев, когда нужно передавать большие объёмы данных или организовывать взаимодействие между формами, открытыми в разных сеансах, используют временное хранилище. Это универсальный механизм 1С, позволяющий:
- 🗄️ Хранить данные между сеансами
- 🔄 Обмениваться информацией между разными формами
- 📦 Передавать большие объёмы данных (таблицы значений, деревья)
Пример использования:
// В первой форме (отправка данных)
ДанныеДляПередачи = Новый Структура();
ДанныеДляПередачи.Вставить("Таблица", ТекущаяТаблица);
ДанныеДляПередачи.Вставить("Параметры", ПараметрыОтчета);
Идентификатор = ПоместитьВоВременноеХранилище(ДанныеДляПередачи, 60); // Хранится 60 секунд
// Во второй форме (получение данных)
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ИдентификаторХранилища") Тогда
Данные = ПолучитьИзВременногоХранилища(Параметры.ИдентификаторХранилища);
Если Данные <> Неопределено Тогда
ЗагрузитьДанные(Данные.Таблица, Данные.Параметры);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущества временного хранилища:
- 🔒 Данные доступны только текущему пользователю
- ⏱️ Автоматическая очистка по таймауту
- 📊 Поддержка любых типов данных (кроме форм и менеджеров)
⚠️ Внимание: При работе с временным хранилищем в веб-клиенте учитывайте ограничения на размер передаваемых данных (обычно около 10 МБ). Для больших объёмов используйте файловое хранилище или базу данных.
8. Сравнение методов взаимодействия между формами
Выбор метода зависит от конкретной задачи. Ниже представлено сравнение основных подходов:
| Метод | Сложность реализации | Производительность | Когда использовать |
|---|---|---|---|
| Параметры формы | Низкая | Высокая | Простая передача данных при открытии |
| События | Средняя | Средняя | Динамический обмен данными |
| Временное хранилище | Высокая | Низкая (сетевые задержки) | Межсеансовый обмен, большие данные |
| Прямое управление | Низкая | Высокая | Простые команды (обновление, закрытие) |
| Модальные формы | Средняя | Средняя | Диалоги с обязательным ответом |
Рекомендации по выбору метода:
- Для простых сценариев (открытие справочника, передача ID) используйте параметры формы
- Для динамического взаимодействия (обновление данных в реальном времени) — события
- Для передачи больших объёмов данных между разными сеансами — временное хранилище
- Для диалогов с пользователем (подтверждение, ввод данных) — модальные формы
Часто задаваемые вопросы
Как передать в форму объект (например, ссылку на документ) так, чтобы он не стал недействительным?
При передаче ссылочных объектов (документов, справочников) всегда передавайте именно ссылку (Объект.Ссылка), а не сам объект. Это предотвратит проблемы с блокировками и недействительными ссылками. В принимающей форме при необходимости получайте объект через Ссылка.ПолучитьОбъект().
Пример:
// Передаём
Параметры.Вставить("ДокументСсылка", ТекущийДокумент.Ссылка);
// Получаем
Если Параметры.Свойство("ДокументСсылка") Тогда
ДокОбъект = Параметры.ДокументСсылка.ПолучитьОбъект();
КонецЕсли;
Почему при закрытии родительской формы не закрываются подчинённые формы?
Это типичная проблема при неправильном указании режима открытия. Подчинённые формы (РежимОткрытияОкна.Подчиненный) должны автоматически закрываться, но:
- Убедитесь, что вы передаёте правильный
Владелец(обычноЭтотОбъект) при открытии - Проверьте, что форма действительно открыта в подчинённом режиме, а не в независимом
- В обработчике
ПередЗакрытиемродительской формы явно закройте дочерние формы черезЗакрыть()
Пример корректного открытия:
ПодчиненнаяФорма = ОткрытьФорму("Справочник.Контрагенты.ФормаСписка",,, ЭтотОбъект, РежимОткрытияОкна.Подчиненный);
Как обновить данные в родительской форме после изменений в дочерней?
Есть три основных подхода:
- Через события: Дочерняя форма генерирует событие при изменении данных, родительская подписана на него
- Через возвращаемое значение: Для модальных форм — возвращайте изменённые данные через
Закрыть(Данные) - Через прямой вызов метода: Если у вас есть ссылка на родительскую форму, вызывайте её метод обновления
Пример с событием:
// В дочерней форме
Процедура ПриИзмененииДанных()
Если ТипЗнч(РодительскаяФорма) = Тип("Форма") Тогда
РодительскаяФорма.ОбновитьДанные(ТекущийОбъект);
КонецЕсли;
КонецПроцедуры
// В родительской форме
Процедура ОбновитьДанные(Объект) Экспорт
Элементы.ТаблицаДокументов.Список.ОбновитьСтроку(Объект);
КонецПроцедуры
Можно ли открыть форму из другой базы данных?
Прямое открытие форм между разными базами 1С невозможно, но есть обходные пути:
- Через COM-соединение: Используйте
Новый COMОбъект("V83.ComConnector")для взаимодействия - Через веб-сервисы: Опубликуйте форму как HTTP-сервис и вызывайте её из другой базы
- Через файлы/временное хранилище: Обменивайтесь данными через внешние источники
Пример с COM-соединением:
Соединение = Новый COMОбъект("V83.ComConnector");
Попытка
Подключение = Соединение.Connect("File=""C:\Bases\Base2"";Usr=""Администратор"";");
Форма = Подключение.ОткрытьФорму("Справочник.Номенклатура.ФормаСписка");
Исключение
Сообщить("Ошибка подключения: " + ОписаниеОшибки());
КонецПопытки;
Обратите внимание, что для этого требуются:
- Права на доступ к другой базе
- Совместимые версии платформы
- Настроенные параметры безопасности
Как отладить взаимодействие между формами?
Для отладки межформенного взаимодействия используйте комбинацию методов:
- Точки останова в обработчиках событий (особенно
ПриСозданииНаСервереиПередЗакрытием) - Журнал регистрации для серверных вызовов (включите регистрацию событий "ВызовСерверногоМетода")
- Вывод в сообщения для клиентских действий:
Сообщить("Форма открыта. Параметры: " + ДампЗнч(Параметры)); - Проверка типов перед обращением к методам:
Если ТипЗнч(Форма) = Тип("Форма") ТогдаИначе
Сообщить("Ошибка: форма не инициализирована!");
КонецЕсли;
Для сложных сценариев полезно вести лог взаимодействия в регистре сведений или файле:
Процедура ЗаписатьВЛог(Сообщение, Данные = Неопределено)
Лог = Новый ЗаписьТекста;
Лог.Открыть("C:\Temp\FormsInteraction.log", ТекстовыйРежимДозаписи);
Лог.Записать(ФорматированнаяСтрока("%1 | %2 | %3",
ТекущаяДата(),
Сообщение,
?(Данные <> Неопределено, ДампЗнч(Данные), "")));
Лог.Закрыть();
КонецПроцедуры