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

Программист 1С v8.3 (Управляемые формы)
← На главную

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

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

Разберем логику взаимодействия сервера и клиента

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

Основная идея заключается в следующем:

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

Способ №1: Использование метода ОткрытьЗначение

Это самый простой и быстрый способ. Рассмотрим его на примере преобразования кода. Допустим, у нас есть серверная процедура, которая просто записывает документ. Нам нужно превратить ее в Функцию, чтобы она могла передать результат обратно.

Проанализируем пример кода на сервере:


&НаСервере
Функция СоздатьДокументМ29НаСервере()
    
    НовыйДок = Документы.м29.СоздатьДокумент();
    НовыйДок.Дата = ТекущаяДата();
    НовыйДок.Ответственный = Пользователи.ТекущийПользователь();
    
    // Заполнение табличной части
    Для каждого Стр Из Объект.Товары Цикл
        НоваяСтрока = НовыйДок.Материалы.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр);
    КонецЦикла;
    
    НовыйДок.Записать();
    
    // Возвращаем ссылку на созданный документ
    Возврат НовыйДок.Ссылка;
    
КонецФункции

Теперь посмотрим, как это вызвать на клиенте в обработчике команды:


&НаКлиенте
Процедура СоздатьИОткрыть(Команда)
    
    // Вызываем серверную функцию и получаем ссылку
    СсылкаНаНовыйДокумент = СоздатьДокументМ29НаСервере();
    
    // Проверяем, что ссылка не пустая и открываем её
    Если Не СсылкаНаНовыйДокумент.Пустая() Тогда
        ОткрытьЗначение(СсылкаНаНовыйДокумент);
    КонецЕсли;
    
КонецПроцедуры

Метод ОткрытьЗначение является универсальным. Платформа сама определяет, какая основная форма назначена для данного типа объекта, и открывает её в режиме просмотра или редактирования.

Способ №2: Использование метода ОткрытьФорму (рекомендуемый)

Если нам нужно не просто "открыть что-нибудь", а программно управлять параметрами открываемой формы (например, открыть конкретную форму или передать в неё дополнительные данные), следует использовать метод ОткрытьФорму. Это более гибкий и профессиональный подход.

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


&НаКлиенте
Процедура СоздатьИОткрытьРасширенный(Команда)
    
    СсылкаНаДок = СоздатьДокументМ29НаСервере();
    
    Если ЗначениеЗаполнено(СсылкаНаДок) Тогда
        
        // Формируем структуру параметров для открытия формы
        ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДок);
        
        // Открываем основную форму документа
        ОткрытьФорму("Документ.м29.ФормаОбъекта", ПараметрыФормы);
        
    КонецЕсли;
    
КонецПроцедуры

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

Разберем причину ошибки "Переменная не определена"

Часто программисты допускают ошибку, как в сообщении №12 обсуждения. Они пишут ОткрытьЗначение(СсылкаНаДокумент), но при этом забывают присвоить результат выполнения серверной функции этой самой переменной.

Выясним причину: в 1С переменные имеют область видимости. Если вы внутри серверной функции назвали переменную НовыйДок, то на клиенте она не будет видна. Вам нужно обязательно поймать возвращаемое значение функции в новую переменную на клиенте. Правильный шаблон выглядит так: ИмяПеременнойНаКлиенте = ИмяФункцииНаСервере();.

Современный подход: Асинхронное открытие через ПоказатьЗначение

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

Рассмотрим пример:


&НаКлиенте
Процедура ЗавершениеСоздания(РезультатВопроса, ДополнительныеПараметры) Экспорт
    
    Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
        
        СсылкаДок = СоздатьДокументМ29НаСервере();
        ПоказатьЗначение(Неопределено, СсылкаДок);
        
    КонецЕсли;
    
КонецПроцедуры

Этот метод работает более плавно в браузере и соответствует стандартам разработки современных интерфейсов 1С.

Продвинутая техника: Открытие формы нового документа без предварительной записи

Иногда пользователю удобнее сначала увидеть заполненный документ, проверить его, а уже потом нажать кнопку "Записать". В этом случае нам не нужно создавать и записывать объект на сервере заранее.

Мы можем подготовить структуру данных и передать её в параметр ЗначенияЗаполнения метода ОткрытьФорму. Проанализируем, как это реализовать:


&НаКлиенте
Процедура ОткрытьНовыйЗаполненный(Команда)
    
    ДанныеЗаполнения = Новый Структура;
    ДанныеЗаполнения.Вставить("Дата", Объект.Дата);
    ДанныеЗаполнения.Вставить("Ответственный", Объект.Ответственный);
    
    // Если нужно передать таблицу, её лучше подготовить на сервере в виде Массива Структур
    
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ДанныеЗаполнения);
    
    ОткрытьФорму("Документ.м29.ФормаОбъекта", ПараметрыФормы);
    
КонецПроцедуры

В этом случае документ откроется со статусом "Объект не найден" (так как он еще не в базе), но все поля уже будут заполнены вашими данными. Это значительно улучшает UX (пользовательский опыт), так как исключает появление "мусорных" или ошибочно созданных документов в базе данных.

Оповещение системы об изменениях

Когда мы создаем документ программно "за спиной" у интерфейса, другие открытые формы (например, списки документов) могут не узнать о появлении новой записи. Чтобы список обновился автоматически, после создания документа полезно вызвать метод оповещения:

ОповеститьОбИзменении(Тип("ДокументСсылка.м29"));

Это заставит все динамические списки данного типа перечитать данные из базы и отобразить ваш новый документ без ручного нажатия кнопки "Обновить".

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

← На главную