Почему возникает ошибка «Переменная не определена (глТекущийПользователь)» в клиент-серверном режиме и как правильно создавать элементы справочника?

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

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

Выясним причину ошибки: контексты выполнения и разница режимов

Главная причина кроется в разделении контекстов выполнения кода на клиентский и серверный:

  1. Разделение контекстов: Глобальная переменная глТекущийПользователь обычно объявляется в модуле обычного приложения или модуле управляемого приложения. Данный контекст существует только на клиенте. Модули объектов (справочников, документов) в клиент-серверном режиме исполняются строго на сервере, где клиентские переменные не создаются и не видны.
  2. Различие файлового и клиент-серверного режимов: В файловой базе при работе через толстый клиент клиентский и серверный код исполняются в одном и том же процессе. В клиент-серверном варианте серверный код исполняется процессом кластера 1С (ragent / rphost), в котором клиентский контекст полностью отсутствует.
  3. Ошибки вызова интерфейсных методов на сервере: Вызов методов ПолучитьФорму() или Форма.Открыть() на сервере является критической ошибкой. Сервер 1С занимается только обработкой данных и не может отрендерить и показать пользовательский интерфейс.

Рассмотрим, как правильно решить обе задачи: получить текущего пользователя на сервере и интерактивно открыть форму создания нового элемента.

Способ 1. Использование параметров сеанса для получения пользователя на сервере

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

В модуле объекта справочника (например, в событии ПередЗаписью или ОбработкаЗаполнения) обращение к пользователю должно выглядеть следующим образом:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
	
	Если ЭтоНовый() Тогда
		// Обращаемся к параметру сеанса, доступному на сервере
		Ответственный = ПараметрыСеанса.ТекущийПользователь;
		ДатаСоздания  = ТекущаяДата();
	КонецЕсли;

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

Если в конфигурации используется Библиотека Стандартных Подсистем (БСП), то получить текущего авторизованного пользователя на сервере можно через функцию подсистемы:

ТекущийПользователь = Пользователи.АвторизованныйПользователь();

Способ 2. Правильное открытие формы нового элемента с клиента

Разберем типичное заблуждение: метод СоздатьЭлемент() используется для программного создания и записи объекта в базу данных на сервере. Если же требуется предоставить пользователю возможность заполнить реквизиты в интерфейсе и самому нажать кнопку «Записать и закрыть», создавать объект вручную не требуется.

В управляемом приложении для интерактивного создания элемента используется метод ОткрытьФорму() с передачей структуры ЗначенияЗаполнения.

Рассмотрим пример кода на клиенте:


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

При вызове этого кода платформа автоматически выполнит следующие действия:

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

Способ 3. Программное создание элемента на сервере без формы

Если стоит задача создавать элемент справочника программно (автоматически, без показа формы пользователю), весь цикл работы с объектом выполним внутри серверной процедуры:


&НаСервере
Функция СоздатьАвтоНаСервере(СсылкаКонтрагента)
	
	НовоеАвто = Справочники.асАвтомобили.СоздатьЭлемент();
	НовоеАвто.Контрагент = СсылкаКонтрагента;
	НовоеАвто.Ответственный = ПараметрыСеанса.ТекущийПользователь;
	НовоеАвто.ДатаСоздания = ТекущаяДата();
	
	Попытка
		НовоеАвто.Записать();
		Возврат НовоеАвто.Ссылка;
	Исключение
		ЗаписатьЛогОшибки(ОписаниеОшибки());
		Возврат Неопределено;
	КонецПопытки;

КонецФункции

После записи ссылку на созданный объект можно вернуть на клиент и при необходимости открыть форму уже существующего элемента:


&НаКлиенте
Процедура ДобавитьАвтоИОткрыть(Команда)
	
	СсылкаНаАвто = СоздатьАвтоНаСервере(Объект.Ссылка);
	
	Если ЗначениеЗаполнено(СсылкаНаАвто) Тогда
		ПоказатьЗначение(, СсылкаНаАвто);
	КонецЕсли;
	
КонецПроцедуры

Резюме

Чтобы избежать ошибок при работе в клиент-серверном режиме 1С:

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