К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как открыть форму из серверной процедуры 1С

Почему серверная процедура 1С не может открыть форму напрямую, и как правильно решить задачу: возврат данных на клиент, ОткрытьФорму, Оповестить и ФоновыеЗадания.

Открыть форму напрямую из серверной процедуры в 1С нельзя — это ограничение архитектуры платформы, а не недочёт конкретного кода. Серверный контекст выполняется на стороне сервера приложений, где нет пользовательского интерфейса: там недоступны методы ОткрытьФорму(), ПоказатьВопрос() и любые другие интерактивные вызовы. Попытка использовать их приведёт к ошибке времени выполнения.

Правильная схема всегда строится вокруг разделения ответственности: сервер выполняет работу с данными (запросы, расчёты, создание объектов), а клиент отвечает за интерфейс — открытие форм, диалоги, оповещения. Задача разработчика — корректно передать результат с сервера на клиент и там уже вызвать ОткрытьФорму() с нужными параметрами.

Ниже разобраны рабочие подходы: классическая схема «клиент вызывает сервер и открывает форму по результату», механизм оповещений для связи между формами, вариант с фоновыми заданиями и типичные ошибки, которые приводят к падению кода или потере данных.

Почему сервер не может открыть форму

В клиент-серверной архитектуре 1С код с директивой компиляции &НаСервере исполняется в процессе сервера приложений (rphost), который не имеет доступа к экрану пользователя, окнам и диалогам. Интерактивные методы там попросту отсутствуют в контексте выполнения. Даже если код скомпилируется, при выполнении возникнет ошибка вида «Вызов интерактивных методов на сервере недопустим».

Дополнительное ограничение — модальность. В тонком и веб-клиенте модальные вызовы запрещены на уровне конфигурации (свойство «Режим использования модальности»), а серверный контекст в принципе не поддерживает ожидание реакции пользователя. Серверная процедура должна отработать и завершиться, вернув управление клиенту.

Базовый шаблон: сервер возвращает данные, клиент открывает форму

Самый частый сценарий: на сервере создаётся или подбирается объект (документ, элемент справочника), а затем нужно показать его пользователю. Решение — вернуть ссылку на клиент и открыть форму там.

&НаКлиенте

Процедура СоздатьИОткрытьДокумент(Команда)

НоваяСсылка = СоздатьДокументНаСервере();

Если ЗначениеЗаполнено(НоваяСсылка) Тогда

ПоказатьЗначение(, НоваяСсылка);

КонецЕсли;

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

&НаСервере

Функция СоздатьДокументНаСервере()

Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

Док.Дата = ТекущаяДатаСеанса();

Док.Записать(РежимЗаписиДокумента.Проведение);

Возврат Док.Ссылка;

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

Метод ПоказатьЗначение() открывает форму объекта по ссылке. Если нужна форма с параметрами или нестандартная форма, используется ОткрытьФорму():

&НаКлиенте

Процедура ОткрытьСПараметрами(Команда)

ДанныеОтбора = ПодготовитьДанныеНаСервере();

ПараметрыФормы = Новый Структура("Отбор", ДанныеОтбора);

ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаСписка", ПараметрыФормы);

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

Порядок действий
  1. 1
    Вынесите работу с данными в серверную функцию с возвращаемым значением
  2. 2
    Убедитесь, что возвращаемые данные сериализуемы: ссылка, структура простых типов, массив
  3. 3
    В клиентской процедуре вызовите серверную функцию и получите результат
  4. 4
    Проверьте результат на заполненность и ошибки
  5. 5
    Вызовите ОткрытьФорму() или ПоказатьЗначение() на клиенте с полученными параметрами

Какие данные можно передавать с сервера на клиент

Возвращаемое значение серверной процедуры проходит сериализацию при передаче между процессами. Поддерживаются примитивные типы, ссылки, структуры, массивы, соответствия, таблицы значений (в форме — через реквизиты). Нельзя передать COM-объекты, запросы, построители, объекты типа «ДокументОбъект» без записи и прочие несериализуемые сущности.

Если нужно передать сложный набор параметров для открываемой формы, соберите их в структуру на сервере и верните её целиком. Ключи структуры должны быть допустимыми идентификаторами — иначе при обращении к ПараметрыФормы.ИмяКлюча получите ошибку.

Типичные ошибки
01
Возврат объекта ДокументОбъект вместо ссылки — ошибка сериализации при передаче на клиент; сначала запишите объект и верните Ссылка
02
Вызов ОткрытьФорму() внутри серверной процедуры — ошибка времени выполнения; перенесите вызов в клиентский контекст
03
Передача несериализуемых типов (Запрос, COMОбъект) в структуре параметров — падение вызова; оставляйте только простые типы и ссылки
04
Открытие формы до завершения транзакции на сервере — пользователь видит незаписанные данные; сначала Записать(), потом возврат ссылки

Связь между формами через оповещения

Второй сценарий: серверная процедура изменила данные, и об этом нужно сообщить уже открытым формам — например, обновить список документов после массовой обработки. Здесь открывать форму не требуется, достаточно оповещения.

После возврата на клиент вызывается Оповестить("ИмяСобытия", Параметр, Источник), а в других формах реализуется обработчик ОбработкаОповещения(ИмяСобытия, Параметр, Источник). Дополнительно полезен ОповеститьОбИзменении(Ссылка) — платформа сама обновит открытые формы списков, где выведена эта ссылка.

&НаКлиенте

Процедура ПослеМассовойОбработки(Команда)

КоличествоИзмененных = ОбработатьДокументыНаСервере();

Оповестить("ДокументыИзменены", КоличествоИзмененных, ЭтотОбъект);

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

Если нужно открыть форму и получить из неё результат обратно в вызывающий код, используйте ОписаниеОповещения с ОткрытьФорму() — форма откроется в режиме ожидания закрытия, а результат вернётся в указанную процедуру.

Длительные операции: фоновые задания и открытие формы по завершении

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

Результат фонового задания передаётся через временное хранилище: серверная процедура помещает структуру с данными по адресу ПоместитьВоВременноеХранилище(Результат, АдресХранилища), клиент после завершения задания извлекает данные по этому адресу и открывает форму.

&НаКлиенте

Процедура ПроверитьЗавершение()

Состояние = ПолучитьСостояниеЗаданияНаСервере(ИдентификаторЗадания);

Если Состояние = "Завершено" Тогда

Результат = ПолучитьИзВременногоХранилища(АдресХранилища);

ОткрытьФорму("Обработка.Результаты.Форма.ФормаРезультата",

Новый Структура("Данные", Результат));

КонецЕсли;

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

Для длительных операций в управляемых формах удобен механизм ДлительныеОперации из БСП, если она внедрена в конфигурацию: он сам управляет фоновым заданием, индикатором и возвратом результата на клиент. Изобретать собственный цикл опроса в этом случае не нужно.
ПЗ
Практическое замечание

Проверка результата и обработка ошибок

Перед открытием формы всегда проверяйте, что серверная часть отработала успешно. Если объект не создан, ссылка пустая или произошло исключение, открытие формы бессмысленно — пользователь увидит пустую форму или ошибку.

Оберните серверную логику в попытку и возвращайте структуру с признаком успеха и текстом ошибки. На клиенте при неудаче покажите сообщение через ПоказатьПредупреждение(), а не открывайте форму.

&НаСервере

Функция СоздатьДокументБезопасно()

Результат = Новый Структура("Успех, Ссылка, ТекстОшибки", Ложь, Неопределено, "");

Попытка

Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

Док.Дата = ТекущаяДатаСеанса();

Док.Записать();

Результат.Успех = Истина;

Результат.Ссылка = Док.Ссылка;

Исключение

Результат.ТекстОшибки = ОписаниеОшибки();

КонецПопытки;

Возврат Результат;

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

Контрольные точки

Как проверить результат

Возвращаемое значение серверной функции
Норма

Заполненная ссылка или структура с признаком успеха

Тревожный признак

Неопределено, пустая ссылка или текст исключения

Поведение формы после открытия
Норма

Форма открылась с ожидаемыми данными и отбором

Тревожный признак

Пустая форма, отсутствуют параметры, ошибка при создании на сервере

Журнал регистрации после массовой обработки
Норма

Нет ошибок, оповещения дошли до открытых форм

Тревожный признак

Ошибки записи объектов, списки не обновились

Выбор подхода под задачу

Конкретный способ зависит от того, что именно должно произойти после серверной обработки. Простое открытие созданного объекта — возврат ссылки и ПоказатьЗначение(). Открытие с отбором или параметрами — ОткрытьФорму() со структурой. Обновление уже открытых форм — оповещения. Длительная обработка — фоновое задание с возвратом результата через хранилище.

Маршрут решения

Как выбрать действие

Нужно показать созданный на сервере объектВерните ссылку и вызовите ПоказатьЗначение() на клиенте
Нужна форма с отбором или параметрамиСоберите структуру на сервере и откройте форму через ОткрытьФорму() на клиенте
Нужно обновить уже открытые формыИспользуйте Оповестить() или ОповеститьОбИзменении() после возврата на клиент
Серверная обработка занимает заметное времяЗапустите фоновое задание и откройте форму после его завершения, получив результат из временного хранилища
Итог

Что важно запомнить

Сервер в 1С не имеет интерфейса и не может открывать формы. Правильная схема: серверная процедура обрабатывает данные и возвращает сериализуемый результат, клиентская процедура проверяет его и вызывает ОткрытьФорму(), ПоказатьЗначение() или Оповестить(). Для долгих операций используйте фоновые задания с передачей результата через временное хранилище.

Частые вопросы

Можно ли открыть форму из процедуры с директивой &НаСервере в модуле формы?

Нет. Директива определяет контекст выполнения, и в серверном контексте интерактивные методы недоступны независимо от того, где расположен код. Перенесите вызов ОткрытьФорму() в процедуру с директивой &НаКлиенте.

Что делать, если серверная процедура находится в общем модуле?

Общий серверный модуль должен только возвращать данные. Клиентская процедура (в форме или клиентском общем модуле) вызывает серверный модуль, получает результат и открывает форму. Если нужен вызов с клиента в клиентский модуль — используйте клиентские общие модули с флагом «Клиент (управляемое приложение)».

Как открыть форму нового документа с заполнением данными с сервера?

Верните с сервера структуру с заполняемыми полями и передайте её в ОткрытьФорму() как параметр «ЗначенияЗаполнения». Либо создайте и запишите документ на сервере, верните ссылку и откройте её через ПоказатьЗначение() — тогда форма покажет уже записанный объект.

Почему при передаче структуры с сервера возникает ошибка сериализации?

В структуре есть несериализуемый тип: объект запроса, COM-объект, менеджер записи, незаписанный объект документа. Оставьте в структуре только примитивные типы, ссылки, даты, массивы и вложенные структуры из них же.

Как уведомить пользователя о завершении фонового задания без постоянного опроса?

Стандартный подход — клиентская процедура с периодической проверкой состояния задания (через ПодключитьОбработчикОжидания) или механизм длительных операций из библиотеки стандартных подсистем, если она есть в конфигурации. Полностью «серверный пуш» клиенту в классической схеме недоступен.

Можно ли обойтись без разделения на клиентскую и серверную процедуры в файловой базе?

Нет. Даже в файловом режиме тонкий клиент работает по клиент-серверной модели, и контексты компилируются раздельно. Толстый клиент в режиме обычного приложения позволяет больше, но для управляемых форм правило разделения остаётся обязательным.