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