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

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

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

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

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

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

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

Почему форму нельзя получить на сервере

Управляемая форма в 1С — это клиентский интерфейсный объект. Она строится на клиенте, отображает данные пользователю и обрабатывает его действия. Сервер приложений хранит и обрабатывает только данные: объекты базы, запросы, вычисления. Директивы компиляции &НаСервере и &НаКлиенте в модуле формы явно показывают это разделение.

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

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

Метод ПолучитьФорму: где работает и где нет

Метод ПолучитьФорму() возвращает объект управляемой формы и доступен только в клиентском контексте. Типичный вызов выглядит так:

&НаКлиенте

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

ПараметрыФормы = Новый Структура("Ключ", ДокументСсылка);

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

Форма.Открыть();

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

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

Вызов ПолучитьФорму в процедуре с директивой &НаСервере приведёт к ошибке компиляции или выполнения — метод просто отсутствует в серверном контексте. То же относится к ОткрытьФорму и ОткрытьФормуМодально. Если в серверном коде вам «нужна форма», это признак того, что задача сформулирована неверно и её надо переформулировать через данные.

Работа с объектом документа на сервере

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

&НаСервере

Процедура ОбработатьДокументНаСервере(ДокументСсылка)

ДокументОбъект = ДокументСсылка.ПолучитьОбъект();

ДокументОбъект.Комментарий = "Обработан серверной процедурой";

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

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

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

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

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

Получение данных формы на сервере при серверном вызове

Когда серверная процедура вызывается из модуля формы, ей доступны данные этой формы. В контексте формы на сервере работают методы РеквизитФормыВЗначение и ДанныеФормыВЗначение, которые преобразуют данные формы в прикладной объект:

&НаСервере

Процедура ЗаполнитьНаСервере()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

ДокументОбъект.ЗаполнитьТабличнуюЧасть();

ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

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

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

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

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

Открытие формы по итогам серверной логики

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

&НаКлиенте

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

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

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

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

КонецЕсли;

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

&НаСервере

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

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

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

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

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

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

Метод ОткрытьЗначение() открывает для ссылки форму по умолчанию. Если нужна конкретная форма или особые параметры, используйте ОткрытьФорму с полным именем формы и структурой параметров. Также учитывайте, что серверная функция не может вернуть «тяжёлые» объекты — только сериализуемые типы: ссылки, структуры, массивы, примитивы. Вернуть ДокументОбъект на клиент нельзя.

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

Сравнение подходов и ограничения

Выбор способа зависит от того, где выполняется код и что требуется получить. Таблица помогает сориентироваться:

ЗадачаКонтекстСпособ
Открыть форму документа пользователюКлиентОткрытьФорму или ОткрытьЗначение
Получить форму для программного обращенияКлиентПолучитьФорму с ключом уникальности
Изменить документ программноСерверСсылка.ПолучитьОбъект() и Записать()
Обработать данные открытой формыСервер (из модуля формы)РеквизитФормыВЗначение / ЗначениеВРеквизитФормы
Массовая обработка без интерфейсаСервер, фоновое заданиеЗапрос + ПолучитьОбъект()

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

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

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

Код компилируется
Норма

Нет ошибок о недоступности метода в контексте

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

Ошибка «Процедура или функция с указанным именем не определена (ПолучитьФорму)»

Документ записан
Норма

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

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

Ссылка пустая или исключение при Записать()

Форма обновилась после серверного вызова
Норма

Реквизиты на форме показывают новые данные

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

Данные изменились в базе, но форма показывает старые — забыли ЗначениеВРеквизитФормы

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

Можно ли вызвать ПолучитьФорму в фоновом задании?

Нет. Фоновое задание выполняется на сервере без клиентского сеанса, поэтому интерфейсные методы там недоступны. В фоновом задании работайте с объектами и запросами, а результат возвращайте на клиент через ДлительныеОперации или сообщения пользователю.

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

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

Чем ПолучитьФорму отличается от ОткрытьФорму?

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

Почему РеквизитФормыВЗначение недоступен в моей процедуре?

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

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

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

Итог

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

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