Как передать данные из одной управляемой формы в другую в 1С 8.3: Разбор лучших практик и частых ошибок

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Передача данных между различными управляемыми формами — одна из наиболее частых задач, с которой сталкивается любой разработчик на платформе 1С:Предприятие 8. Начинающие программисты часто пытаются применить привычные по другим языкам программирования методы, например, объявление глобальных или экспортных переменных в модуле формы. Однако в управляемом приложении этот подход не работает.

В этой статье мы подробно разберем, почему стандартные экспортные переменные не подходят для обмена данными между формами, и рассмотрим три надежных, методологически верных способа решения этой задачи в соответствии со стандартами разработки фирмы «1С».

Почему не работает экспорт переменных в управляемых формах?

Давайте проанализируем ситуацию, с которой столкнулся автор темы на форуме. Он объявил переменную в Форме 1 следующим образом:


&НаКлиенте
Перем Приветствие Экспорт;

И попытался обратиться к ней из Формы 2. Почему возникла ошибка «Переменная не определена»?

Дело в том, что в управляемом приложении 1С каждая форма существует в своем собственном изолированном контексте. Объявление переменной с ключевым словом Экспорт внутри модуля формы делает эту переменную доступной только как свойство конкретного экземпляра этой формы. Вторая форма ничего не знает о существовании первой формы в памяти и не имеет прямого доступа к ее контексту.

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

Теперь разберем, как сделать это правильно.

Способ №1. Передача простых данных через параметры формы (Основной способ)

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

Рассмотрим по шагам, как реализовать этот механизм.

Шаг 1. Отправка данных из Формы 1

При открытии Формы 2 мы подготавливаем специальную структуру параметров и передаем ее вторым аргументом в функцию ОткрытьФорму. Назовем наш параметр Приветствие.


&НаКлиенте
Процедура ОткрытьФорму2(Команда)
    
    // Создаем структуру для передачи параметров
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Приветствие", "Привет, мир!");
    
    // Открываем вторую форму нашей внешней обработки
    ОткрытьФорму("ВнешняяОбработка.ТестЭкспортПеременной.Форма.Форма2", ПараметрыФормы);
    
КонецПроцедуры

Шаг 2. Прием данных в Форме 2

Чтобы Форма 2 могла принять данные, нам нужно обработать их в момент создания формы на сервере. Для этого используется стандартный обработчик события ПриСозданииНаСервере. Все переданные параметры автоматически попадают в коллекцию Параметры открываемой формы.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли нужный параметр
    Если Параметры.Свойство("Приветствие") Тогда
        // Записываем полученное значение в реквизит формы, чтобы к нему был доступ на клиенте
        РеквизитПриветствие = Параметры.Приветствие;
    КонецЕсли;
    
КонецПроцедуры

Важное примечание: Чтобы этот код успешно отработал, в Форме 2 необходимо заранее создать реквизит формы с именем РеквизитПриветствие (тип Строка) на вкладке «Реквизиты» в конфигураторе. Также вы можете явно добавить параметр Приветствие на вкладку «Параметры» в окне редактирования Формы 2. В этом случае платформа автоматически инициализирует его при открытии.

Способ №2. Передача сложных данных через Временное хранилище

Что делать, если вам нужно передать не просто строку, а сложный объект или большой объем данных? Например, таблицу значений, дерево, структуру с большим количеством вложенных элементов или системный объект, который не может быть передан напрямую с клиента на клиент?

Прямая передача таких объектов через параметры формы вызовет ошибку передачи мутабельных значений или приведет к критическому падению производительности из-за избыточного трафика между клиентом и сервером. Для решения этой проблемы мы используем Временное хранилище.

Суть метода: мы помещаем объект во временную память на сервере Формы 1, получаем уникальный текстовый адрес (ссылку на эти данные) и передаем этот адрес Форме 2 через параметры. Форма 2 по этому адресу считывает данные из хранилища.

Проанализируем программный код для этого сценария:

Код в Форме 1 (отправитель):


&НаСервере
Функция ПоместитьДанныеВХранилище()
    
    // Формируем таблицу значений (или любой другой сложный объект)
    ТаблицаДанных = Новый ТаблицаЗначений;
    ТаблицаДанных.Колонки.Добавить("ТекстСообщения");
    
    НоваяСтрока = ТаблицаДанных.Добавить();
    НоваяСтрока.ТекстСообщения = "Привет из временного хранилища!";
    
    // Помещаем во временное хранилище, привязывая его к УникальномуИдентификатору данной формы
    Адрес = ПоместитьВоВременноеХранилище(ТаблицаДанных, УникальныйИдентификатор);
    Возврат Адрес;
    
КонецФункции

&НаКлиенте
Процедура ОткрытьФорму2(Команда)
    
    // Получаем адрес временного хранилища на сервере
    АдресДанных = ПоместитьДанныеВХранилище();
    
    // Передаем адрес как обычный параметр
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("АдресДанных", АдресДанных);
    
    ОткрытьФорму("ВнешняяОбработка.ТестЭкспортПеременной.Форма.Форма2", ПараметрыФормы);
    
КонецПроцедуры

Код в Форме 2 (получатель):


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем наличие параметра с адресом данных
    Если Параметры.Свойство("АдресДанных") Тогда
        
        // Извлекаем объект из хранилища
        ПолученныеДанные = ПолучитьИзВременногоХранилища(Параметры.АдресДанных);
        
        // Обрабатываем извлеченную таблицу значений
        Если ТипЗнч(ПолученныеДанные) = Тип("ТаблицаЗначений") Тогда
            Для Каждого СтрокаТаблицы Из ПолученныеДанные Цикл
                // Выполняем полезные действия, например, заполняем реквизит формы
                РеквизитПриветствие = СтрокаТаблицы.ТекстСообщения;
            КонецЦикла;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Способ №3. Возврат значения при закрытии (Обратная передача данных)

Очень часто в практике разработки возникает обратная задача: нам нужно открыть Форму 2 (например, форму выбора или калькулятор значения), пользователь выполняет там какие-то действия, закрывает ее, и мы должны получить результат работы обратно в Форме 1.

В управляемом приложении 1С для этих целей используется асинхронный механизм описания оповещений — объект ОписаниеОповещения.

Выясним, как связать две формы в единую цепочку возврата данных:

Шаг 1. Открытие формы с ожиданием возврата в Форме 1:


&НаКлиенте
Процедура ОткрытьФормуДляВводаДанных(Команда)
    
    // Описываем процедуру, которая будет вызвана в текущей форме после закрытия Формы 2
    Оповещение = Новый ОписаниеОповещения("ОбработатьРезультатВыбора", ЭтотОбъект);
    
    // Открываем форму, передавая описание оповещения седьмым параметром метода ОткрытьФорму
    ОткрытьФорму("ВнешняяОбработка.ТестЭкспортПеременной.Форма.Форма2", , , , , , Оповещение);
    
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьРезультатВыбора(Результат, ДополнительныеПараметры) Экспорт
    
    // Сюда управление придет автоматически, когда закроется Форма 2
    Если Результат <> Неопределено Тогда
        Сообщить("Вторая форма вернула значение: " + Результат);
    КонецЕсли;
    
КонецПроцедуры

Шаг 2. Возврат значения при закрытии Формы 2:

Во второй форме мы перехватываем действие пользователя (например, нажатие кнопки «Готово») и закрываем форму, передавая результат в метод Закрыть().


&НаКлиенте
Процедура КнопкаОК(Команда)
    
    ЗначениеДляПередачи = "Пользователь успешно завершил ввод!";
    // Закрываем форму и возвращаем результат в вызывающую форму
    Закрыть(ЗначениеДляПередачи);
    
КонецПроцедуры

Подведем итоги

Для создания стабильно работающих и легко поддерживаемых решений в 1С:Предприятии 8 всегда придерживайтесь следующих правил:

  1. Никогда не используйте экспортные переменные в контексте модуля формы для обмена данными между разными формами.
  2. Для передачи простых данных (строки, числа, ссылки) используйте параметры формы и обрабатывайте их в процедуре ПриСозданииНаСервере.
  3. Если объем данных велик (таблицы значений, структуры, массивы), передавайте их через временное хранилище, передавая во вторую форму только текстовый адрес в памяти.
  4. Для возврата значений из открытой формы назад в вызывающую всегда используйте асинхронный механизм ОписаниеОповещения.

Соблюдение этих простых принципов позволит вам писать качественный, отказоустойчивый код, который будет легко проходить любые аудиты и проверки на соответствие стандартам разработки 1С.

← На главную