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

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

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

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

Проблема отсутствия прямой связи «Сервер -> Клиент»

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

Рассмотрим основные стратегии решения этой задачи: от классических оповещений до современной Системы взаимодействия.

Решение 1: Использование события ПриЧтенииНаСервере и ОповеститьОбИзменении

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

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

Шаг 2. Используем стандартное событие формы ПриЧтенииНаСервере. Оно срабатывает каждый раз, когда форма перечитывает данные из базы данных.


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

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


// В модуле документа-источника (например, Взаиморасчеты)
НовыйДокумент = Документы.Доход.СоздатьДокумент();
// ... заполнение ...
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);

// Сигнализируем системе об изменениях
ОповеститьОбИзменении(НовыйДокумент.Ссылка);

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

Решение 2: Система взаимодействия (современный метод)

Начиная с версии 8.3.10, в 1С доступна Система взаимодействия. Это мощный инструмент, который позволяет серверу отправить адресное сообщение клиенту.

Разберем по шагам, как это работает:

  1. В модуле объекта при записи мы создаем сообщение системы взаимодействия.
  2. В сообщении мы можем передать структуру данных или просто сигнал «Обновись».
  3. В управляемой форме мы подключаем обработчик сообщений, который при получении сигнала вызовет метод Прочитать() или обновит конкретные элементы.

Пример отправки сообщения из модуля объекта:


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

В форме документа Доход в обработчике ПриОткрытии подписываемся на сообщения:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    СистемаВзаимодействия.ПодключитьОбработчикПолученияСообщения(Новый ОписаниеОповещения("ОбработкаСообщения", ЭтотОбъект));
КонецПроцедуры

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

Решение 3: Обработчик ожидания (Polling)

Если Система взаимодействия не настроена, а архитектура не позволяет использовать стандартные оповещения, можно прибегнуть к методу периодического опроса. Рассмотрим, как реализовать «проверку флага».

Проанализируем ситуацию: форма раз в несколько секунд спрашивает сервер: «Нет ли для меня новостей?». Чтобы это работало, в объекте или в специальном регистре сведений нужно фиксировать факт изменения.

  1. В форме подключаем обработчик ожидания: ПодключитьОбработчикОжидания("ПроверитьОбновлениеДанных", 5); (каждые 5 секунд).
  2. В процедуре ПроверитьОбновлениеДанных делаем легкий серверный вызов, проверяя дату изменения документа или специальный реквизит-версию.
  3. Если версия изменилась — вызываем ЭтаФорма.Прочитать().

Важное замечание: Этот метод создает дополнительную нагрузку на сервер БД, поэтому используйте его только в крайнем случае для критически важных интерфейсов.

Решение 4: Дополнительные свойства и временное хранилище

Если форма инициирует процесс в модуле объекта (например, через вызов метода объекта), мы можем передать в объект УникальныйИдентификатор формы через ДополнительныеСвойства.

Посмотрим на пример кода:


// В коде формы документа "Взаиморасчеты"
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.ДополнительныеСвойства.Вставить("ИдентификаторФормы", ЭтаФорма.УникальныйИдентификатор);
ДокОбъект.Записать();

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

Резюме и рекомендации

Подведем итог нашему анализу:

Соблюдение этих правил сделает ваш код надежным, а интерфейс — отзывчивым для пользователя.

← На главную