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