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