Как открыть форму незаписанного объекта документа

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

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

Основные подходы к решению задачи

Прежде всего, проанализируем разницу между новым и существующим документом. Для нового документа платформа предоставляет штатные механизмы заполнения «на лету». Для существующего документа задача усложняется тем, что форма при открытии по умолчанию считывает данные из базы данных по ссылке. Наша цель — подменить эти данные своими до того, как пользователь их увидит.

Решение 1: Открытие формы нового незаписанного документа

Рассмотрим ситуацию, когда нам нужно создать новый документ, заполнить его реквизиты программно и открыть форму, чтобы пользователь мог проверить данные и нажать кнопку «Записать». Самый правильный и надежный метод — использование параметра ЗначенияЗаполнения или работа с ДанныеФормы.

Разберем пример кода, который часто используется в обработках:


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

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

В этом примере мы используем ПолучитьФорму, что позволяет нам до вызова Открыть() манипулировать данными. Метод КопироватьДанныеФормы гарантирует, что измененная структура данных корректно отобразится в интерфейсе.

Решение 2: Изменение данных существующего документа без записи

Выясним причину, по которой обычное открытие формы существующего документа не подходит: если мы просто вызовем ОткрытьФорму с ключом ссылки, 1С обратится к таблицам СУБД и проигнорирует наши программные правки. Чтобы показать «измененную, но не сохраненную» версию существующего документа, мы должны следовать алгоритму:

  1. Получить форму существующего документа по его ссылке (параметр Ключ).
  2. Программно изменить Объект формы на сервере.
  3. Обновить данные формы на клиенте.
  4. Открыть окно.

Проанализируем пример реализации:


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

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

Важный нюанс: при таком подходе у пользователя в заголовке формы появится символ «*» (звездочка), указывающий на то, что объект модифицирован. Если пользователь закроет форму без сохранения, база данных останется в исходном состоянии.

Сложные ситуации: Рисуемые формы (Табели, Установка цен)

Рассмотрим подробнее ситуацию, упомянутую в обсуждении: документы типа «Табель учета рабочего времени» или «Установка цен номенклатуры». В таких формах табличные части часто не являются прямым отображением данных объекта. Они строятся динамически в событии ПриСозданииНаСервере или ПриЧтенииНаСервере на основе сложных расчетов.

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

Чтобы решить эту проблему, рассмотрим несколько шагов:

  1. Использование расширений: Если конфигурация типовая, можно создать расширение для формы документа. В расширении нужно вынести логику построения интерфейса в экспортную процедуру.
  2. Эмуляция перечитывания: Мы можем добавить в форму метод, который принудительно вызовет логику инициализации интерфейса после того, как мы подменили Объект.

Пример вызова обновления интерфейса через расширение:


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

Использование временного хранилища

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

Разберем логику:

  1. На сервере создаем и заполняем ДокументОбъект.
  2. Вызываем ПоместитьВоВременноеХранилище(НашОбъект).
  3. Передаем адрес в ОткрытьФорму.
  4. В самой форме в событии ПриСозданииНаСервере проверяем наличие адреса в параметрах и выполняем ЗначениеВДанныеФормы(ПолучитьИзВременногоХранилища(Адрес), Объект).

Этот метод считается наиболее «чистым», так как он разделяет логику подготовки данных и логику их визуализации. Однако он требует возможности редактирования кода формы документа (или использования расширения).

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

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

Резюме

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

← На главную