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