При разработке расширений для 1С многие из нас сталкиваются с ситуацией, когда глобальная переменная, казалось бы, правильно объявленная в одном модуле расширения, оказывается недоступной в другом. Особенно часто этот вопрос возникает, когда речь идет о взаимодействии между
МодулемУправляемогоПриложения
МодулемМенеджера
Для того чтобы понять, почему глобальная переменная не видна, нам необходимо глубже погрузиться в архитектуру платформы 1С:Предприятие, а именно в разделение кода на клиентский и серверный контексты. Это фундаментальное понятие, определяющее, где и как будет выполняться ваш код.
Модуль управляемого приложения
Этот модуль компилируется и выполняется на клиенте. Он предназначен для обработки событий, связанных с сеансом работы пользователя, таких как
ПриНачалеРаботыСистемы
ПриЗавершенииРаботыСистемы
&НаКлиенте
&НаСервере
Куда доступны экспортируемые переменные? Экспортируемые переменные, процедуры и функции, определенные в
МодулеУправляемогоПриложения
Важно отметить, что ни один из этих контекстов не является серверным.
Модуль менеджера объекта
В отличие от модуля управляемого приложения,
МодульМенеджера
Проанализируем его особенности:
МодульМенеджера
&НаКлиенте
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Здесь может быть ваш серверный код
#КонецЕсли;
МодуляМенеджера
Вывод: Теперь нам становится очевидно, почему переменная, объявленная в клиентском
МодулеУправляемогоПриложения
МодулеМенеджера
Помимо разделения на клиентский и серверный контексты, существует также разделение пространств имен между основной конфигурацией и расширением. Хотя расширение и "встраивается" в основную конфигурацию, оно все же существует как отдельный слой. Это означает, что:
Поскольку прямое использование "глобальных" переменных модуля приложения расширения в серверных модулях невозможно, нам нужно рассмотреть другие, более подходящие механизмы платформы для обмена данными между различными контекстами и модулями. Разберем по шагам несколько эффективных подходов.
Передача параметров через процедуры и функции
Это самый очевидный, надежный и рекомендуемый способ передачи данных. Когда вам нужно использовать данные из клиентского контекста на сервере (или наоборот), просто передайте их как параметры в вызов серверной (или клиентской) процедуры или функции.
Пример:
// На клиенте (например, в модуле формы или МодулеУправляемогоПриложения расширения)
&НаКлиенте
Процедура МояКлиентскаяПроцедура()
МояПеременная = "Значение из клиента";
РезультатСервера = МойОбщийМодульРасширения.ВыполнитьНаСервере(МояПеременная);
Сообщить("Результат с сервера: " + РезультатСервера);
КонецПроцедуры;
// В ОбщемМодулеРасширения (свойство "Сервер")
&НаСервере
Функция ВыполнитьНаСервере(ПараметрСКлиента) Экспорт
// Здесь мы можем использовать ПараметрСКлиента
Возврат "Сервер обработал: " + ПараметрСКлиента;
КонецФункции;
Параметры сеанса
Если данные должны быть доступны на протяжении всего сеанса работы пользователя и не привязаны к конкретной форме или модулю, мы можем использовать параметры сеанса. Они доступны как на клиенте, так и на сервере.
Ограничения: Параметры сеанса могут хранить не все типы значений. В основном это примитивные типы, ссылки на объекты базы данных и некоторые стандартные объекты платформы. Для сложных структур данных или больших объемов информации этот способ может быть неоптимальным.
Пример:
// В МодулеСеанса (или в МодулеУправляемогоПриложения при начале сеанса)
// Для расширения: нужно создать или расширить существующий параметр сеанса
// и установить его значение.
// Допустим, у нас есть параметр сеанса "МойПараметрСеанса" в расширении.
// Установка значения (например, на клиенте через серверный вызов)
&НаСервере
Процедура УстановитьМойПараметрСеансаНаСервере(Значение)
ПараметрыСеанса.МойПараметрСеанса = Значение;
КонецПроцедуры;
// Получение значения (доступно как на клиенте, так и на сервере)
// На клиенте:
&НаКлиенте
Процедура ПолучитьПараметрСеансаНаКлиенте()
Сообщить("Значение параметра сеанса: " + ПараметрыСеанса.МойПараметрСеанса);
КонецПроцедуры;
// На сервере:
&НаСервере
Процедура ПолучитьПараметрСеансаНаСервере()
Сообщить("Значение параметра сеанса: " + ПараметрыСеанса.МойПараметрСеанса);
КонецПроцедуры;
Временное хранилище
Для передачи больших объемов данных, двоичных данных или файлов между клиентом и сервером (или наоборот) используйте временное хранилище. Это позволяет избежать передачи данных через параметры процедур, что может быть неэффективно для больших объемов.
Механизм: Мы помещаем данные в хранилище на одной стороне и получаем уникальный адрес, который затем передаем на другую сторону. По этому адресу данные можно извлечь.
Пример:
// На клиенте
&НаКлиенте
Процедура ПередатьФайлНаСервер()
ИмяФайла = "C:\temp\MyFile.txt";
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайла);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
// Передаем адрес на сервер
МойОбщийМодульРасширения.ОбработатьФайлНаСервере(АдресХранилища);
КонецПроцедуры;
// На сервере (в ОбщемМодулеРасширения)
&НаСервере
Процедура ОбработатьФайлНаСервере(АдресХранилища) Экспорт
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
Если ДвоичныеДанные <> Неопределено Тогда
// Обрабатываем двоичные данные
Текст = Новый ТекстовыйДокумент();
Текст.УстановитьДвоичныеДанные(ДвоичныеДанные);
Сообщить("Содержимое файла на сервере: " + Текст.ПолучитьТекст());
КонецЕсли;
КонецПроцедуры;
Переменные управляемого или обычного приложения (только на клиенте)
Если вам нужны глобальные переменные, доступные только в клиентском контексте (например, из разных клиентских форм), вы можете использовать переменные, определенные в
МодулеУправляемогоПриложения
Пример:
// В МодулеУправляемогоПриложения расширения
Перем МояКлиентскаяГлобальнаяПеременная Экспорт;
Процедура ПриНачалеРаботыСистемы()
МояКлиентскаяГлобальнаяПеременная = "Значение установлено при старте";
КонецПроцедуры;
// В модуле клиентской формы расширения
&НаКлиенте
Процедура ПриОткрытии()
Сообщить("Переменная из МодуляУправляемогоПриложения: " + Модули.МодульУправляемогоПриложенияРасширения.МояКлиентскаяГлобальнаяПеременная);
КонецПроцедуры;
Обратите внимание, что для обращения к экспортируемой переменной из другого модуля расширения может потребоваться указание полного пути к модулю (например,
Модули.МодульУправляемогоПриложенияРасширения.МояКлиентскаяГлобальнаяПеременная
Общие модули расширения
В расширении мы можем создавать собственные общие модули. Это очень мощный инструмент для организации кода.
Используя общие модули с правильными директивами компиляции, мы можем легко обмениваться данными между клиентским и серверным кодом, вызывая процедуры и функции с нужными параметрами.
Таким образом, понимание контекстов выполнения и применение подходящих механизмов передачи данных вместо попыток использования "глобальных" переменных там, где это архитектурно невозможно, позволит нам создавать надежные и эффективные решения в расширениях 1С.
← К списку