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