Передача данных между формами — одна из самых частых задач при разработке в 1С:Предприятие 8.3. Без правильной организации этого процесса даже простая логика работы приложения может превратиться в хаос: пользователи теряют введённые данные при переходе между окнами, формы открываются с пустыми полями, а отчёты формируются на основе устаревшей информации. В этой статье разберём все актуальные способы передачи параметров — от базовых (через конструктор открытия формы) до продвинутых (использование временных хранилищ и событий).

Особое внимание уделим типичным ошибкам, которые приводят к потере данных или зависанию интерфейса. Например, многие разработчики не учитывают, что при передаче сложных объектов (таблиц значений, деревьев) через параметры открытия форма может «подвисать» из-за сериализации больших данных. Также рассмотрим нюансы работы с модальными и немодальными окнами — они ведут себя по-разному при обмене данными.

Статья будет полезна как начинающим программистам , так и опытным специалистам, которые хотят оптимизировать код и избежать «костылей» вроде глобальных переменных. Все примеры приведены для актуальной платформы 1С:Предприятие 8.3.23 (и выше), но большинство методов работают и в более ранних версиях.

1. Передача параметров через конструктор открытия формы

Самый простой и очевидный способ — передать данные непосредственно при открытии формы через метод ОткрытьФорму(). Этот подход подходит для передачи примитивных типов (чисел, строк, дат) или небольших объектов (ссылок, простых структур). Основное преимущество — минимальный код и отсутствие необходимости в дополнительных обработчиках.

Синтаксис метода:

ОткрытьФорму("ИмяФормы", ЭтотОбъект, , , , Параметры);

Где Параметры — это структура или фиксированный набор значений, которые будут доступны в целевой форме через свойство Параметры.

  • Плюсы: простота реализации, не требует дополнительных обработчиков.
  • Минусы: не подходит для больших объёмов данных (например, таблиц значений), так как параметры сериализуются при передаче.
  • ⚠️ Ограничение: если форма уже открыта, повторное открытие с новыми параметрами создаст новый экземпляр.

Пример передачи данных о клиенте из формы списка в форму элемента:

ПараметрыФормы = Новый Структура();

ПараметрыФормы.Вставить("Клиент", ТекущийЭлемент.Ссылка);

ПараметрыФормы.Вставить("Режим", "Просмотр");

ОткрытьФорму("Справочник.Клиенты.ФормаЭлемента", ЭтотОбъект, , , , ПараметрыФормы);

💡

Если нужно передать несколько параметров одного типа (например, массив ссылок), лучше упаковать их в коллекцию или структуру, чем передавать по отдельности. Это упростит обработку в целевой форме.

2. Использование реквизитов формы для обмена данными

Если формы взаимодействуют длительное время (например, главная форма и подчинённая панель), удобнее использовать реквизиты формы. Этот метод позволяет динамически обновлять данные без повторного открытия формы. Например, так часто организуют работу с фильтрами в отчётах или настройками отображения.

Алгоритм работы:

  1. В целевой форме declare реквизит с нужным типом (например, ФильтрДокументов типа Структура).
  2. При открытии формы передайте ссылку на неё в исходную форму через параметры или глобальный контекст.
  3. Изменяйте реквизит целевой формы напрямую через точку (например, ЦелеваяФорма.ФильтрДокументов = НовыйФильтр).

Пример кода для передачи фильтра в форму отчёта:

// В форме отчёта (при создании)

Реквизит ФильтрДокументов;

// В исходной форме (при открытии отчёта)

Параметры = Новый Структура();

Параметры.Вставить("ФормаОтчета", ОткрытьФорму("Отчет.Продажи.ФормаОтчета"));

Параметры.ФормаОтчета.ФильтрДокументов = ТекущийФильтр;

⚠️ Внимание: При таком подходе убедитесь, что целевая форма не закрывается раньше исходной — это приведёт к ошибке доступа к освобождённому объекту. Используйте обработчик ПриЗакрытии для очистки ссылок.
📊 Какой способ передачи данных вы используете чаще?
Через параметры открытия формы
Через реквизиты
Через временные хранилища
Через события
Другой вариант

3. Временные хранилища: когда параметров слишком много

Если нужно передать большие объёмы данных (например, таблицу значений с тысячами строк или дерево категорий), параметры открытия формы становятся неэффективны из-за сериализации. В таких случаях используют временные хранилища (ПоместитьВоВременноеХранилище() и ПолучитьИзВременногоХранилища()).

Преимущества метода:

  • 🚀 Производительность: данные не копируются при передаче, а хранятся в памяти сеанса.
  • 🔄 Гибкость: можно передавать любые типы данных, включая двоичные (например, картинки для предварительного просмотра).
  • 🔒 Безопасность: хранилище очищается автоматически при завершении сеанса.

Пример передачи большой таблицы значений:

// В исходной форме

Идентификатор = ПоместитьВоВременноеХранилище(БольшаяТаблицаЗначений);

// В целевой форме (при создании)

Таблица = ПолучитьИзВременноеХранилище(Параметры.Идентификатор);

МетодМакс. размер данныхСериализацияСкорость
Параметры открытия~10 МБДаСредняя
Реквизиты формыНе ограниченоНетВысокая
Временное хранилище~1 ГБНетОчень высокая
Глобальные переменныеНе ограниченоНетВысокая (но небезопасно)
⚠️ Внимание: Идентификаторы временного хранилища действуют только в пределах одного сеанса. Если пользователь обновит страницу браузера (в веб-клиенте) или перезапустит толстый клиент, данные будут утеряны.

4. Передача данных через события

Для сложных сценариев, когда формы должны обмениваться данными динамически (например, при изменении фильтра в одной форме нужно обновить данные в другой), удобно использовать события платформы 1С. Этот метод требует больше кода, но обеспечивает гибкость и расширяемость.

Алгоритм реализации:

  1. В модуле управляемого приложения declare обработчик события (например, ОбновлениеФильтра).
  2. В исходной форме при изменении данных вызывайте Оповестить("ОбновлениеФильтра", Параметры).
  3. В целевой форме подпишитесь на событие через ПодписатьсяНаСобытие() и обработайте данные.

Пример кода:

// В модуле управляемого приложения

Процедура ОбновлениеФильтра(Параметры) Экспорт

Сообщить("Получен новый фильтр: " + Параметры.Описание);

КонецПроцедуры

// В исходной форме

Оповестить("ОбновлениеФильтра", Новый Структура("Описание,ТекущийФильтр"));

// В целевой форме (при создании)

ПодписатьсяНаСобытие("ОбновлениеФильтра", "ОбновлениеФильтраОбработчик");

Процедура ОбновлениеФильтраОбработчик(Параметры) Экспорт

Фильтр = Параметры.ТекущийФильтр;

ОбновитьДанные();

КонецПроцедуры

Подписка на событие добавлена в целевой форме|Обработчик события объявлен как Экспорт|Параметры события упакованы в структуру|Отписка от события реализована при закрытии формы-->

5. Особенности работы с модальными и немодальными формами

Способ открытия формы (ОткрытьФормуМодально() vs ОткрытьФорму()) существенно влияет на механизм передачи данных. Разберём ключевые различия:

  • 🔹 Модальные формы:
    • Блокируют работу исходной формы до закрытия.
    • Могут возвращать результат через ЗначениеВозврата.
    • Подходят для диалогов с подтверждением (например, выбор файла для загрузки).
  • 🔲 Немодальные формы:
    • Работают параллельно с исходной формой.
    • Требуют явной синхронизации данных (через реквизиты или события).
    • Используются для панелей инструментов или фоновых процессов.

Пример возврата данных из модальной формы:

Результат = ОткрытьФормуМодально("Справочник.Номенклатура.ФормаВыбора", ЭтотОбъект);

Если НЕ Результат.Пустая() Тогда

ВыбраннаяНоменклатура = Результат.ВыбранноеЗначение;

КонецЕсли;

Что будет, если не обработать ЗначениеВозврата в модальной форме?

Если в модальной форме не установить значение возврата (например, забыть вызвать Закрыть(Истина, ВыбранныеДанные)), исходная форма получит Неопределённо. Это приведёт к ошибкам при попытке разбора результата. Всегда проверяйте возвращаемое значение на пустоту!

Для немодальных форм актуальна проблема гонки данных — когда исходная форма пытается прочитать реквизит целевой формы раньше, чем он будет установлен. Решение: используйте события или флаги готовности (например, реквизит ДанныеЗагружены типа Булево).

6. Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при передаче параметров между формами. Вот самые распространённые из них и способы их решения:

  1. Передача больших данных через параметры открытия.

    Симптомы: форма долго открывается или «подвисает».

    Решение: используйте временные хранилища или реквизиты формы.

  2. Утечка ссылок на формы.

    Симптомы: ошибка «Объект не найден» при закрытии формы.

    Решение: очищайте ссылки в обработчике ПриЗакрытии.

  3. Игнорирование типов данных.

    Симптомы: некорректное отображение данных (например, дата превращается в строку).

    Решение: явно преобразуйте типы при передаче (например, Дата(Параметры.ДатаНачала)).

  4. Отсутствие обработки ошибок.

    Симптомы: падение программы при отсутствии параметра.

    Решение: проверяйте наличие параметров через Параметры.Свойство("ИмяПараметра").

💡

Всегда проверяйте передаваемые параметры на корректность типов и наличие значений. Это убережёт от ошибок при изменении логики формы в будущем.

Ещё одна частая проблема — конфликт имён параметров. Если в целевой форме уже есть реквизит с именем, совпадающим с именем параметра, платформа может некорректно разрешить конфликт. Решение: используйте уникальные префиксы (например, Параметры_Фильтр вместо просто Фильтр).

FAQ: Ответы на частые вопросы

Можно ли передавать между формами объекты с круговой ссылкой (например, два документа, ссылающихся друг на друга)?

Нет, платформа не поддерживает сериализацию объектов с круговой ссылкой при передаче через параметры или временные хранилища. В таких случаях:

  • Передавайте только идентификаторы объектов (ссылки), а сами объекты загружайте в целевой форме по этим ссылкам.
  • Используйте реквизиты формы для хранения ссылок на объекты.
Как передать данные из формы в отчёт, который открывается в новом окне?

Для отчётов, открываемых через ОткрытьЗначениеВНовомОкне(), используйте:

  1. Параметры компоновки данных (если отчёт на СКД).
  2. Глобальные параметры отчёта (задаются через УстановитьПараметр()).
  3. Временные хранилища для больших данных.

Пример:

Отчет = ПолучитьОтчет("Продажи");

Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));

ОткрытьЗначениеВНовомОкне(Отчет);

Почему при передаче таблицы значений через параметры теряются некоторые колонки?

Это происходит из-за особенностей сериализации: платформа не сохраняет структуру колонок таблицы значений при передаче через параметры. Решения:

  • Передавайте таблицу через временное хранилище.
  • Восстанавливайте структуру колонок в целевой форме вручную (через Таблица.Колонки.Добавить()).
  • Используйте ЗаписатьJSON()/ПрочитатьJSON() для сохранения структуры (но это медленнее).
Как передать данные между формами в веб-клиенте?

В веб-клиенте все описанные методы работают, но с учётом особенностей:

  • Временные хранилища действуют только в пределах одного HTTP-сеанса.
  • При обновлении страницы (F5) все немодальные формы закрываются, а их данные теряются.
  • Для долговременного хранения используйте ПоместитьВХранилищеЗначения() с указанием области видимости ОбластьВидимостиХранилища.Сеанс.
Можно ли передавать между формами двоичные данные (например, картинки или файлы)?

Да, но с оговорками:

  • Через параметры открытия — только небольшие файлы (до ~10 МБ), так как они сериализуются в строку.
  • Через временное хранилище — самый надёжный способ для больших файлов.
  • Для изображений в формах можно использовать реквизит типа ХранилищеЗначения с привязкой к элементу ПолеКартинки.

Пример передачи картинки:

ИдентификаторКартинки = ПоместитьВоВременноеХранилище(КартинкаВДвоичныхДанных);

Параметры.ИдентификаторКартинки = ИдентификаторКартинки;