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