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

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

Как в 1С открыть форму документа на сервере: реальные способы и ограничения

Как открыть форму документа в 1С с сервера: почему интерактивные методы недоступны в серверном контексте и какие обходные решения использовать на практике.

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

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

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

Почему сервер не может открыть форму: суть ограничения

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

Если вызвать ОткрытьФорму() внутри процедуры с директивой &НаСервере, платформа выдаст ошибку вида «Процедура или функция с указанным именем не определена» либо сообщение о недоступности метода в данном контексте. Тот же эффект будет в общих модулях с флагом «Сервер» без флага «Клиент», в фоновых заданиях и в регламентных операциях.

Отдельный случай — директива &НаСервереБезКонтекста. Здесь недоступен даже объект Форма и её реквизиты, поэтому любые попытки работы с формой исключены по определению. Если логика требует и данных формы, и серверного вызова, используйте &НаСервере с передачей нужных значений параметрами.

Рабочая схема: сервер готовит данные, клиент открывает форму

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

Пример типовой реализации. Клиентская процедура:

&НаКлиенте

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

СсылкаНаДокумент = НайтиДокументНаСервере(НомерДокумента);

Если ЗначениеЗаполнено(СсылкаНаДокумент) Тогда

ОткрытьЗначение(СсылкаНаДокумент);

Иначе

ПоказатьПредупреждение(, "Документ не найден");

КонецЕсли;

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

Серверная процедура в том же модуле формы:

&НаСервере

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

Запрос = Новый Запрос(

"ВЫБРАТЬ ПЕРВЫЕ 1 РеализацияТоваровУслуг.Ссылка

|ИЗ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ РеализацияТоваровУслуг.Номер = &Номер");

Запрос.УстановитьПараметр("Номер", НомерДокумента);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

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

КонецЕсли;

Возврат Неопределено;

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

Метод ОткрытьЗначение() сам определяет, какую форму использовать для объекта: для ссылки на документ откроется его основная форма документа. Если нужна конкретная форма или нестандартные параметры, вместо него используется ОткрытьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента", ПараметрыФормы) — тоже на клиенте.

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

Создание документа на сервере и открытие его формы

Частая задача — по кнопке создать новый документ на основании текущего и сразу показать его пользователю. Здесь два варианта, и выбор зависит от того, нужно ли записывать документ до открытия.

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

&НаКлиенте

Процедура СоздатьНаОсновании(Команда)

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

ОткрытьФорму("Документ.СчетНаОплатуПокупателю.ФормаОбъекта",

ПараметрыФормы);

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

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

Сравнение вариантов

ОткрытьЗначение(Ссылка)

Подходит для существующего документа. Платформа сама выбирает форму объекта. Не позволяет передать дополнительные параметры.

ОткрытьФорму() с параметрами

Позволяет указать конкретную форму, ключ записи, основание, значения заполнения. Требует точного имени формы.

Программное создание без открытия

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

Открытие формы из фонового задания и регламентных операций

Фоновые задания и регламентные процедуры выполняются на сервере без привязки к сеансу пользователя, поэтому открыть форму из них невозможно даже через обходные вызовы — клиентского контекста просто не существует. Попытки передать «команду на открытие» через внешние события или файлы-посредники являются ненадёжными костылями.

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

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

Передача параметров при открытии и получение формы объекта

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

&НаКлиенте

Процедура ОткрытьТолькоПросмотр(Команда)

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Ключ", Объект.Ссылка);

ПараметрыФормы.Вставить("ТолькоПросмотр", Истина);

ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта",

ПараметрыФормы);

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

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

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

Типичные ошибки
01
Вызов ОткрытьФорму внутри &НаСервере — ошибка компиляции или выполнения, код не работает ни в одном клиенте
02
Серверная процедура возвращает объект ДокументОбъект вместо ссылки — передача объекта на клиент невозможна, возвращайте ДокументСсылка
03
Множественные серверные вызовы в цикле с открытием форм — каждый вызов это обращение к серверу, группируйте данные в одну функцию
04
Игнорирование проверки ЗначениеЗаполнено(Ссылка) — при пустой ссылке ОткрытьЗначение молча ничего не покажет или откроет пустую форму
05
Попытка открыть форму из фонового задания — задание не имеет сеанса пользователя, используйте длительные операции с оповещением

Проверка результата и диагностика проблем

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

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

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

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

Ссылка, возвращённая с сервера
Норма

Ссылка заполнена, тип соответствует нужному виду документа

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

Неопределено или пустая ссылка — документ не найден или не записан

Открытая форма
Норма

Форма документа открылась, данные соответствуют записи в базе

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

Открылась пустая форма нового документа — передан неверный Ключ

Права пользователя
Норма

Документ открывается под рабочей учётной записью

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

Под администратором работает, под пользователем нет — проверьте роли

Повторное открытие
Норма

Открывается то же окно или корректное новое

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

Плодятся дубликаты окон — используйте уникальность формы по ключу

FAQ

Можно ли открыть форму документа из общего серверного модуля?

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

Почему ОткрытьЗначение не открывает документ и не выдаёт ошибку?

Чаще всего передана пустая ссылка или значение Неопределено — метод в этом случае просто ничего не делает. Добавьте проверку ЗначениеЗаполнено() перед вызовом. Также проверьте права пользователя на чтение документа и не удалён ли объект из базы.

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

Серверная функция собирает данные в структуру и возвращает её клиенту. Клиент вызывает ОткрытьФорму() с параметром ЗначенияЗаполнения или Основание. Документ при этом не записывается — пользователь сам решает, сохранять его или нет.

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

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

Работает ли эта схема в веб-клиенте?

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

Что делать, если документ нужно только создать, а показывать не обязательно?

Тогда форма вообще не нужна: серверная процедура создаёт объект через Документы.ВидДокумента.СоздатьДокумент(), заполняет реквизиты и вызывает Записать(). Это быстрее и надёжнее интерактивного сценария, особенно при пакетной обработке.

Итог

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

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