В разработке на платформе 1С:Предприятие 8.3 (особенно в конфигурациях на управляемых формах, таких как УТ 11, ERP или КА) часто возникает задача: программно создать документ на сервере и тут же открыть его форму пользователю для дальнейшего редактирования. Основная сложность здесь заключается в строгом разделении контекстов выполнения кода: сервер отвечает за данные и проведение, а клиент — за интерфейс и открытие окон.
В этой статье мы подробно разберем, почему нельзя открыть форму напрямую из серверного кода (например, из процедуры ОбработкаПроведения), и рассмотрим правильные архитектурные подходы для решения этой задачи.
Проанализируем ситуацию, с которой столкнулся автор темы. Попытка вызвать метод открытия формы непосредственно в момент проведения другого документа обречена на провал. Это связано с двумя фундаментальными ограничениями платформы:
ОткрытьФорму) являются исключительно клиентскими методами. Сервер не имеет доступа к графическому интерфейсу пользователя.Следовательно, нам нужно сначала создать документ на сервере, вернуть его ссылку на клиент и только потом инициировать открытие формы. Рассмотрим, как это реализовать пошагово.
Рассмотрим наиболее универсальный алгоритм. Мы создаем функцию на сервере, которая выполняет всю «черную» работу по заполнению и записи объекта, а затем возвращает готовую ссылку. На клиенте мы принимаем эту ссылку и используем стандартный метод ОткрытьФорму.
Разберем пример кода для реализации этой логики:
&НаКлиенте
Процедура СоздатьИОткрытьДокумент()
// Вызываем серверную функцию для создания объекта
СсылкаНаНовыйДокумент = СоздатьДокументНаСервере();
// Проверяем, что ссылка получена и не является пустой
Если Не СсылкаНаНовыйДокумент.Пустая() Тогда
// Формируем параметры для открытия формы.
// Ключ — это стандартный параметр, по которому система понимает, какой объект открыть.
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаНовыйДокумент);
// Открываем основную форму документа
ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция СоздатьДокументНаСервере()
НовыйОбъект = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйОбъект.Дата = ТекущаяДатаСеанса();
// ... здесь заполняем остальные реквизиты ...
Попытка
НовыйОбъект.Записать(РежимЗаписиДокумента.Запись);
Возврат НовыйОбъект.Ссылка;
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(КраткоеОписаниеОшибки());
Возврат Документы.РеализацияТоваровУслуг.ПустаяСсылка();
КонецПопытки;
КонецФункции
В данном примере мы используем параметр Ключ. Это критически важный момент: если его не передать в структуру параметров, система попытается открыть форму для создания нового (пустого) объекта, а не того, который мы только что сохранили в базе.
Если создание подчиненного документа (например, Реализации на основании Заказа) должно происходить автоматически при записи основного документа, лучше всего использовать клиентское событие формы ПослеЗаписи. Это гарантирует, что транзакция основного документа уже завершена, и база данных готова к новым операциям.
Рассмотрим ситуацию, когда ссылка на созданный документ временно хранится в дополнительном реквизите или получается через серверный вызов:
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
// Если в логике проведения было заложено создание РТУ,
// мы можем получить его ссылку через серверный вызов
СсылкаНаРТУ = ПолучитьСозданнуюРеализацию(Объект.Ссылка);
Если ЗначениеЗаполнено(СсылкаНаРТУ) Тогда
ПараметрыОткрытия = Новый Структура("Ключ", СсылкаНаРТУ);
ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыОткрытия);
КонецЕсли;
КонецПроцедуры
Этот метод хорош тем, что он не блокирует работу пользователя во время проведения, так как форма открывается уже после того, как основное окно «разблокировалось».
В современных конфигурациях, таких как Управление торговлей 11, программисты стараются не использовать «сырые» методы платформы, если есть готовые функции БСП. Проанализируем возможности программного интерфейса БСП, который делает код более стабильным и безопасным.
Для открытия формы объекта рекомендуется использовать модуль ОбщегоНазначенияКлиент. Метод ОткрытьФормуОбъекта автоматически проверяет права доступа текущего пользователя и корректно обрабатывает специфические настройки интерфейса (например, работу в веб-клиенте).
Пример использования БСП:
// Вместо стандартного ОткрытьФорму используем метод БСП
ОбщегоНазначенияКлиент.ОткрытьФормуОбъекта(СсылкаНаДокумент);
Преимущества этого подхода:
В обсуждении упоминалось, что метод ОткрытьЗначение может «ругаться» на режим модальности. Выясним причину: в современном 1С использование модальных окон (которые полностью блокируют интерфейс до их закрытия) считается плохой практикой и часто запрещено в настройках конфигурации.
Вместо устаревшего ОткрытьЗначение следует использовать метод ПоказатьЗначение. Рассмотрим его синтаксис:
// Описание оповещения — это процедура, которая выполнится ПОСЛЕ закрытия открытого окна
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормыРТУ", ЭтаФорма);
// Метод не блокирует выполнение кода дальше, он работает асинхронно
ПоказатьЗначение(ОписаниеОповещения, СсылкаНаДокумент);
Это особенно важно, если ваше решение должно работать в веб-клиенте (через браузер), где модальные окна физически не поддерживаются большинством современных браузеров.
Иногда документ создается в одной форме, а открыть его нужно из другой, или вовсе обновить списки документов по всей системе. В этом случае на помощь приходит метод Оповестить. Рассмотрим сценарий совместной работы:
Оповестить("ЗаписанНовыйДокументРТУ", СсылкаНаРТУ, ЭтаФорма);ОбработкаОповещения.Это позволяет системе динамически реагировать на изменения, внесенные программно, обеспечивая актуальность данных на экранах всех пользователей без принудительного обновления страниц.
Для успешного решения задачи программного открытия формы запомним основные правила:
во-первых, создание и заполнение объекта всегда переносим на сервер;
во-вторых, команду на открытие формы (ОткрытьФорму или ПоказатьЗначение) подаем строго на клиенте после выхода из серверного контекста;
в-третьих, всегда передаем структуру с ключом ссылки, чтобы открыть конкретный экземпляр документа.
Соблюдение этих принципов позволит создавать гибкие и отказоустойчивые интерфейсы, которые будут одинаково стабильно работать как на локальных компьютерах, так и в облачных сервисах через браузер.