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

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

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

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

Почему событие Открытие не решает задачу?

Разберем ситуацию: у элемента формы (реквизита типа ДокументСсылка) есть событие Открытие. Начинающие разработчики часто пытаются использовать его для обновления данных. Однако важно понимать механику работы платформы: событие Открытие срабатывает в момент нажатия на кнопку открытия (лупу) или при двойном клике, до того, как форма документа фактически появилась на экране. В этот момент данные в базе еще не изменены. Когда пользователь закончит редактирование и закроет документ, управление просто вернется в форму обработки, но никакие стандартные события «активизации» окна в управляемом приложении не сработают так, чтобы запустить программный код обновления.

Решение 1: Программное открытие формы с обработчиком оповещения

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

Во-первых, нам необходимо создать обработчик события Открытие для нашего реквизита на форме обработки. В этом обработчике мы должны установить параметр СтандартнаяОбработка = Ложь, чтобы платформа не открывала форму самостоятельно по стандартному алгоритму.

Во-вторых, мы подготовим структуру параметров и вызовем метод ОткрытьФорму, передав в него описание процедуры, которая должна выполниться после закрытия формы документа. Посмотрим на пример реализации:


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

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


&НаКлиенте
Процедура ПослеЗакрытияФормыДокумента(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
    
    // В этот момент пользователь уже закрыл документ. 
    // Нам нужно обновить данные на форме обработки.
    ОбновитьДанныеДокументаНаСервере();
    
КонецПроцедуры

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

Решение 2: Использование глобального события Оповестить

Метод с ОписаниеОповещения отлично работает, если вам нужно обновить данные только после закрытия формы. Но что если пользователь нажал кнопку «Записать» в документе, не закрывая его, и переключился обратно в вашу обработку (например, используя панель открытых окон)? В этом случае оповещение о закрытии не сработает.

Для таких случаев в 1С предусмотрен механизм Оповестить и ОбработкаОповещения. Рассмотрим, как это применить без изменения конфигурации (используя Расширения).

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

Проанализируем пример кода для формы обработки:


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

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

Решение 3: Подписка на событие формы через УстановитьДействие

Рассмотрим еще один интересный способ, который упоминался в обсуждении. Если вы открываете форму программно, вы можете попробовать динамически назначить ей обработчик события ПослеЗаписи. Это позволяет избежать изменений в самой форме документа даже через расширения.

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

Как гарантировать обновление данных без запроса к базе?

Если вы хотите избежать лишнего серверного вызова для чтения данных, вы можете передать измененные данные прямо в параметре закрытия формы. Для этого в форме документа при закрытии нужно заполнить параметр Результат. Но это опять же требует вмешательства в код формы документа. Для внешней обработки самым чистым решением будет именно повторное чтение реквизитов ссылки на сервере в момент возврата фокуса или закрытия вспомогательного окна.

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

Подведем итог: для того чтобы ваша внешняя обработка всегда отображала актуальные данные, откажитесь от стандартного открытия документов. Используйте связку ОткрытьФорму + ОписаниеОповещения, и вы получите полный контроль над жизненным циклом окон в вашем приложении.

← На главную