Разработка и Конфигурация · 14 мин
1С: как с сервера открыть форму
Разбираем, почему в 1С нельзя напрямую открыть форму с сервера, и какие механизмы использовать: ОткрытьФорму на клиенте, оповещения, обработчики ожидания и параметры формы.
Вопрос «как с сервера открыть форму» возникает у разработчиков 1С регулярно: логика выполняется в серверной процедуре, и кажется естественным оттуда же показать пользователю форму документа, отчёта или обработки. Однако архитектура платформы 1С:Предприятие 8 устроена иначе: серверный код не имеет доступа к интерфейсу пользователя и не может открывать формы напрямую. Попытка вызвать ОткрытьФорму() в серверном контексте завершится ошибкой компиляции или выполнения.
Это ограничение не случайность, а следствие клиент-серверной модели: серверный код может выполняться в фоновом задании, в веб-сервисе, по регламенту — в ситуациях, где интерактивного сеанса пользователя просто нет. Поэтому платформа требует, чтобы любое открытие форм инициировалось только на клиенте. Правильный подход — передать данные с сервера на клиент и уже там открыть нужную форму, либо использовать механизмы оповещений и обработчиков ожидания.
Ниже разобраны рабочие способы решить задачу: открытие формы из клиентской процедуры после серверного вызова, передача параметров, открытие формы «по событию» с сервера через оповещения, а также типичные ошибки и ограничения каждого подхода.
Почему серверный код не может открывать формы
В управляемом приложении 1С код явно разделён директивами компиляции: &НаСервере, &НаКлиенте, &НаСервереБезКонтекста. Клиентские методы интерактивного интерфейса — ОткрытьФорму(), ПолучитьФорму(), ОткрытьЗначение(), ПоказатьВопрос() — доступны только в контексте &НаКлиенте. Серверная процедура физически выполняется на сервере приложений, где нет ни экрана, ни сеанса тонкого клиента в привычном смысле.
Если попробовать вызвать ОткрытьФорму() внутри серверной процедуры, конфигуратор при проверке модуля выдаст ошибку вида «Процедура или функция с указанным именем не определена» либо ошибка возникнет в момент исполнения. Это защита платформы от логически невозможной операции: сервер может обслуживать десятки сеансов одновременно, и у него нет способа понять, на чей экран выводить форму.
Базовый способ: серверная логика плюс открытие формы на клиенте
Стандартный паттерн выглядит так: клиентская процедура вызывает серверную, та выполняет вычисления или создаёт объект, возвращает результат (ссылку, структуру параметров), после чего клиент открывает форму. Важно, что серверный вызов и открытие формы — два отдельных шага в одном клиентском обработчике.
// Клиентская процедура в форме или общем модуле
&НаКлиенте
Процедура СоздатьИОткрытьДокумент(Команда)
НоваяСсылка = СоздатьДокументНаСервере();
Если ЗначениеЗаполнено(НоваяСсылка) Тогда
ОткрытьЗначение(НоваяСсылка);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция СоздатьДокументНаСервере()
Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
Док.Дата = ТекущаяДатаСеанса();
Док.Заполнить(Неопределено);
Док.Записать();
Возврат Док.Ссылка;
КонецФункции
Обратите внимание на нюансы. Серверная функция помечена &НаСервереБезКонтекста — это ускоряет вызов, так как не сериализуются данные формы. Возвращать можно только сериализуемые типы: ссылки, примитивы, структуры, массивы. Объекты типа ДокументОбъект с сервера на клиент передать нельзя — только ссылку или данные для заполнения.
Если документ записывать на сервере раньше времени нежелательно (пользователь может отказаться от сохранения), лучше открывать форму с параметрами заполнения: создаётся структура с реквизитами, передаётся в ОткрытьФорму(), а документ записывается уже в форме по решению пользователя.
&НаКлиенте
Процедура ОткрытьСЗаполнением(Команда)
ПараметрыЗаполнения = Новый Структура("Основание", ПолучитьДанныеОснования());
ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыЗаполнения);
КонецПроцедурыОткрытие формы с параметрами, подготовленными на сервере
Частая задача — открыть форму списка с отбором или форму объекта с предзаполненными реквизитами, где данные для отбора вычисляются запросом на сервере. Схема та же: серверная функция возвращает структуру, клиент передаёт её как параметры формы.
&НаКлиенте
Процедура ПоказатьПросроченныеЗаказы(Команда)
Отбор = СформироватьОтборНаСервере();
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Отбор);
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
ОткрытьФорму("Документ.ЗаказПокупателя.ФормаСписка", ПараметрыФормы);
КонецПроцедуры
Параметр СформироватьПриОткрытии актуален для форм отчётов: он заставляет отчёт выполниться сразу при открытии, без нажатия кнопки «Сформировать». Для форм списков достаточно передать структуру Отбор — платформа сама применит его к динамическому списку, если поля отбора доступны.
Учтите ограничение: в параметры формы можно передавать только сериализуемые значения. Нельзя передать, например, РезультатЗапроса или временную таблицу — их нужно преобразовать в массив структур или таблицу значений (таблица значений сериализуется и может быть параметром формы, если параметр объявлен в форме соответствующим образом).
Открытие формы «по событию с сервера»: оповещения и обработчики ожидания
Иногда требуется обратная инициатива: событие произошло на сервере (завершилось фоновое задание, изменились данные), и форма должна открыться или обновиться у пользователя. Прямого канала «сервер → клиент» в платформе нет, поэтому используются два механизма.
Оповещения между открытыми формами
Метод Оповестить() вызывается на клиенте и рассылает сообщение всем открытым формам, подписанным через обработчик ОбработкаОповещения. Типичный сценарий: форма А выполнила серверную операцию и оповещает форму Б, которая по этому сигналу открывает третью форму или обновляет список. Само по себе оповещение не «пробивает» границу сервер-клиент — оно работает только внутри клиентского сеанса.
Обработчик ожидания для проверки фоновых заданий
Если на сервере запущено длительное фоновое задание и по его завершении нужно открыть форму результата, используется ПодключитьОбработчикОжидания(). Клиент периодически (например, раз в 2–5 секунд) вызывает серверную функцию, проверяющую состояние задания по его уникальному идентификатору. Когда задание завершено, клиент получает результат из временного хранилища и открывает форму.
&НаКлиенте
Процедура ПроверитьЗавершениеЗадания()
Результат = ПроверитьЗаданиеНаСервере(ИдентификаторЗадания);
Если Результат.Завершено Тогда
ОтключитьОбработчикОжидания("ПроверитьЗавершениеЗадания");
ОткрытьФорму("Обработка.РезультатыЗагрузки.Форма.Результат",
Новый Структура("АдресРезультата", Результат.АдресХранилища));
КонецЕсли;
КонецПроцедуры
- 1На клиенте запустите фоновое задание через серверный вызов (ДлительныеОперации.ВыполнитьВФоне в БСП или ФоновыеЗадания.Выполнить)
- 2Сохраните идентификатор задания и адрес временного хранилища результата
- 3Подключите обработчик ожидания с разумным интервалом (2–5 секунд)
- 4В обработчике проверяйте состояние задания серверным вызовом
- 5При завершении отключите обработчик, получите результат и откройте форму на клиенте
Открытие форм из внешних источников: HTTP-сервисы, регламентные задания, COM
Отдельный класс задач — когда «сервером» называют не серверный контекст кода, а вообще серверный процесс: регламентное задание, HTTP-сервис, обмен данными. Здесь принципиально то же ограничение: ни регламентное задание, ни веб-сервис не могут открыть форму у пользователя, потому что выполняются в собственных сеансах без интерфейса.
Практические альтернативы:
- Запись события в базу. Регламентное задание сохраняет информацию (например, в регистр сведений «УведомленияПользователей»), а клиентские сеансы периодически проверяют её обработчиком ожидания и открывают форму при появлении новых записей.
- Система взаимодействия. Встроенный механизм обсуждений и уведомлений позволяет отправить пользователю сообщение с навигационной ссылкой — по клику откроется нужная форма или объект.
- Навигационные ссылки. Метод
ПолучитьНавигационнуюСсылку()формирует ссылку видаe1cib/data/..., которую можно отправить пользователю любым способом; при переходе по ней в сеансе 1С откроется форма объекта.
Если требуется открыть форму на стороне COM-соединения или внешнего соединения — это возможно только если внешнее приложение само является клиентом 1С (например, через Automation-сервер с видимостью). В тонком и веб-клиенте такой сценарий недоступен и считается устаревшей практикой.
Сравнение подходов и выбор под задачу
Выбор способа зависит от того, где возникает потребность открыть форму и есть ли активный клиентский сеанс. Таблица помогает сопоставить условия.
| Сценарий | Механизм | Ограничения |
|---|---|---|
| Кнопка в форме, нужна серверная логика перед открытием | Серверный вызов + ОткрытьФорму на клиенте | Два вызова, но работает везде |
| Открытие формы по завершении фонового задания | Обработчик ожидания + проверка состояния | Задержка до интервала опроса |
| Событие от регламентного задания или обмена | Регистр уведомлений / система взаимодействия | Нет гарантии мгновенной доставки |
| Переход к объекту из письма или внешней системы | Навигационная ссылка e1cib | Требует запущенного сеанса 1С |
| Связь между двумя открытыми формами | Оповестить + ОбработкаОповещения | Работает только внутри одного сеанса |
Сравнение вариантов
Универсальный и предсказуемый вариант; подходит для любых интерактивных сценариев, но требует разделения кода на два метода
Единственный способ реагировать на серверные события в активном сеансе; минус — лишние серверные вызовы и задержка реакции
Подходит для асинхронных уведомлений без активного ожидания; требует настройки и не даёт мгновенного открытия формы
Типичные ошибки и как их избежать
Первая и самая частая ошибка — попытка вызвать ОткрытьФорму() или Предупреждение() внутри серверной процедуры «для проверки». Даже если код иногда «работает» в файловом варианте при толстом клиенте, в клиент-серверном режиме и веб-клиенте он гарантированно сломается. Проверку модулей с разными режимами компиляции стоит включать в конфигураторе при разработке.
Вторая ошибка — передача несериализуемых объектов с сервера на клиент: ДокументОбъект, Запрос, РезультатЗапроса. Это вызывает ошибку «Ошибка передачи данных между клиентом и сервером». Решение — возвращать ссылки, структуры, массивы и таблицы значений.
Третья группа проблем — с обработчиками ожидания: слишком маленький интервал (доли секунды) перегружает сервер лишними вызовами, а забытый ОтключитьОбработчикОжидания приводит к тому, что проверка продолжает выполняться после закрытия формы и вызывает ошибки. Всегда отключайте обработчик при получении результата и в обработчике ПриЗакрытии формы.
Проверка результата и диагностика
После внедрения выбранного механизма проверьте его в условиях, близких к рабочим: в клиент-серверном режиме (если он используется), в тонком и веб-клиенте, под пользователем с ограниченными правами. Ошибки контекста часто всплывают только в веб-клиенте, где недоступны многие возможности толстого клиента.
Для сценариев с фоновыми заданиями полезно логировать состояние задания в журнал регистрации: запись о запуске, завершении и ошибках позволяет быстро понять, на каком этапе цепочка «задание → проверка → открытие формы» оборвалась. Если форма не открывается, проверьте: завершилось ли задание, вернула ли серверная функция ожидаемое значение, не отклонил ли вызов ОткрытьФорму обработчик ОбработкаЗаполнения или права доступа к объекту.
Как проверить результат
Форма открылась с переданными параметрами и отбором
Ошибка контекста или пустая форма без параметров
Возвращает ссылку или структуру простых типов
Ошибка сериализации при возврате объекта
Срабатывает с заданным интервалом и отключается после результата
Продолжает срабатывать после закрытия формы
Форма открывается под целевой ролью
Нарушение прав доступа при открытии
Часто задаваемые вопросы
Можно ли открыть форму прямо из процедуры &НаСервере?
Нет. Методы интерактивного интерфейса недоступны в серверном контексте по архитектурным причинам. Нужно вернуть данные на клиент и вызвать ОткрытьФорму() в клиентской процедуре.
Как открыть форму нового документа, заполнив его на сервере, но не записывая?
Передайте с сервера структуру с данными заполнения и откройте форму с параметром ЗначенияЗаполнения, либо обработайте параметры в ПриСозданииНаСервере формы объекта. Документ будет записан только при нажатии «Записать» или «Провести».
Как узнать на клиенте, что фоновое задание завершилось?
Подключите обработчик ожидания и периодически вызывайте серверную функцию, проверяющую задание по уникальному идентификатору (в БСП — механизм ДлительныеОперации). После завершения заберите результат из временного хранилища и отключите обработчик.
Может ли регламентное задание показать пользователю форму?
Напрямую нет — у регламентного задания нет пользовательского сеанса. Варианты: записать уведомление в базу и проверять его обработчиком ожидания на клиенте, либо отправить сообщение через систему взаимодействия с навигационной ссылкой.
Почему код с ОткрытьФорму работает в файловой базе, но падает на сервере?
В файловом режиме на толстом клиенте границы контекстов размыты, и некоторые вызовы ошибочно выполняются. В клиент-серверном режиме и веб-клиенте разделение строгое, поэтому ошибочный код проявляется. Включайте проверку модулей для всех режимов в конфигураторе.
Что важно запомнить
Сервер в 1С не открывает формы — это делает только клиент. Правильная схема: серверная процедура готовит данные, клиент вызывает ОткрытьФорму с параметрами. Для реакции на серверные события используются обработчики ожидания, оповещения, регистры уведомлений и навигационные ссылки.