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

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

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

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

Выясним причину ошибки «Метод не обнаружен (ПолучитьФорму)»

Проанализируем частую ошибку разработчиков. В управляемом приложении при обращении к реквизиту формы Объект через владельца формы:


Док = ЭтаФорма.ВладелецФормы.Объект;
ФормаДок = Док.ПолучитьФорму("ФормаДокумента"); // Ошибка!

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

Способ 1. Прямое заполнение данных формы без записи в базу данных

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

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


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

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

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

Способ 2. Обновление формы, если данные записаны в базу данных

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

Разберем по шагам два варианта обновления:

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

Способ 3. Поиск открытой формы документа через окна приложения

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

В этом случае найти открытую форму нужного документа можно перебором открытых окон клиентского приложения:


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

Способ 4. Использование стандарта БСП (Библиотеки Стандартных Подсистем)

Если конфигурация разработана на базе БСП, создавать отдельную форму обработки для заполнения документов не требуется. Рекомендуется регистрировать обработку через механизм Дополнительные отчеты и обработки с видом команды ЗаполнениеОбъекта.

В этом случае подсистема БСП автоматически передает контекст открытой формы в процедуру выполнения команды (через параметр ПараметрыВыполненияКоманды.ЭтаФорма), что позволяет заполнять реквизиты объекта без ручного поиска окон и без модификации типовой конфигурации.

← На главную