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

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

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

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

Способ 1. Принудительное обновление через метод Прочитать()

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

Разберем пример кода, который можно использовать в модуле формы внешней обработки на клиенте. Мы будем использовать перебор открытых окон для поиска нужной формы:


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

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

Способ 2. Обновление без записи объекта через КопироватьДанныеФормы

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

Для реализации этого метода обработка должна быть открыта с указанием владельца (формы документа). Рассмотрим алгоритм действий:

  1. В обработке на сервере подготавливаем измененные данные в виде структуры или объекта.
  2. На клиенте используем глобальный метод КопироватьДанныеФормы().

Пример реализации в форме внешней обработки:


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

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

Способ 3. Элегантное получение формы через Ключ

Если мы не хотим перебирать все окна через ПолучитьОкна(), существует более "чистый" способ получить ссылку на уже открытую форму конкретного объекта. Система 1С позволяет получить форму, передав в параметрах Ключ (ссылку на объект). Если форма этого объекта уже открыта, платформа вернет именно её, а не создаст новую.

Проанализируем этот подход:


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

Почему ОповеститьОбИзменении() не работает?

Выясним причину, по которой стандартное оповещение часто оказывается бесполезным в данной задаче. Метод ОповеститьОбИзменении(Ссылка) предназначен для уведомления системы о том, что данные в базе данных изменились. Его основная роль:

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

Особенности для конфигураций на базе БСП (ЗУП 3, ERP, КА)

В современных конфигурациях (например, ЗУП 3.1 КОРП), внешние обработки заполнения обычно подключаются через механизм Дополнительных отчетов и обработок. В этом случае взаимодействие происходит через стандартные интерфейсы БСП.

Если обработка запускается с типом "ВызовКлиентскогоМетода", в процедуру ВыполнитьКоманду передается параметр ПараметрыВыполнения. Рассмотрим, как обратиться к форме из этого контекста:


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

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

← На главную