К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как программно обновить форму в 1С 8.3

Способы программного обновления формы в 1С 8.3: ОбновитьОтображениеДанных, Прочитать, оповещения. Примеры кода, типичные ошибки и проверка результата.

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

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

Ошибка в выборе метода приводит либо к лишним обращениям к базе данных и падению производительности, либо к обратной проблеме — форма выглядит обновлённой, но данные в ней устарели. Ниже разобраны все основные способы с примерами кода, условиями выбора и способами проверки результата.

Чем отличаются способы обновления формы

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

Сравнение способов обновления

ОбновитьОтображениеДанных()

Только перерисовывает элементы формы по текущим данным в памяти. Не читает базу. Подходит после программного изменения реквизитов формы.

Прочитать()

Заново загружает объект из базы в форму, затирая несохранённые изменения. Подходит, когда объект изменён другим сеансом или фоновым заданием.

ОповеститьОбИзменении()

Сообщает всем открытым формам, что объект записан. Формы списков и связанные формы обновятся сами. Вызывается после записи.

Элементы.Список.Обновить()

Перевыполняет запрос динамического списка. Нужен, когда изменились данные, отображаемые списком, но сам объект формы не затронут.

Оповестить() с обработчиком

Гибкий механизм: одна форма шлёт событие, другая реагирует в ОбработкаОповещения. Требует ручной реализации на принимающей стороне.

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

ОбновитьОтображениеДанных: перерисовка без чтения базы

Метод ОбновитьОтображениеДанных() вызывается у формы и заставляет платформу заново вывести значения в элементы управления. Это самый лёгкий способ обновления: обращения к базе данных не происходит, поэтому метод безопасно вызывать часто.

&НаКлиенте

Процедура ПересчитатьИтоги(Команда)

// Меняем реквизиты формы программно

Объект.Сумма = Объект.Количество * Объект.Цена;

// Перерисовываем элементы формы

ЭтаФорма.ОбновитьОтображениеДанных();

КонецПроцедуры

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

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

Перечитывание объекта через Прочитать

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

&НаСервере

Процедура ПеречитатьОбъектНаСервере()

// Перечитываем объект из базы в данные формы

ЭтаФорма.Прочитать();

КонецПроцедуры

&НаКлиенте

Процедура ОбновитьИзБазы(Команда)

Если Объект.Модифицированность Тогда

ПоказатьПредупреждение(, "Сначала запишите изменения — они будут потеряны");

Возврат;

КонецЕсли;

ПеречитатьОбъектНаСервере();

КонецПроцедуры

Есть и альтернативный путь через ЗначениеВРеквизитФормы: получить объект методом РеквизитФормыВЗначение("Объект"), вызвать у него Прочитать() и вернуть обратно. Такой подход нужен редко — в основном когда требуется дополнительная логика с объектом до отображения, например заполнение дополнительных реквизитов формы по данным объекта.

Обновление динамического списка

Формы списков документов, справочников и регистров построены на динамических списках. Они не обновляются от ОбновитьОтображениеДанных() — нужен перезапуск запроса, который лежит в основе списка.

&НаКлиенте

Процедура ОбновитьСписок(Команда)

Элементы.Список.Обновить();

КонецПроцедуры

Обратите внимание: метод Обновить() вызывается у элемента формы (таблицы, связанной со списком), а не у самой формы. Если элемент называется иначе, подставьте его имя. После вызова платформа заново выполнит запрос динамического списка с текущими отборами и настройками.

Если список должен обновляться при записи элементов из других форм, ручной вызов не нужен — достаточно, чтобы в форме элемента после записи вызывался ОповеститьОбИзменении() (платформа делает это автоматически при стандартной записи). Тогда все открытые списки, отображающие этот тип данных, обновятся сами.

Оповещения: обновление других форм

Когда изменения сделаны в одной форме, а отобразить их нужно в другой, работает система оповещений. Базовый вариант — ОповеститьОбИзменении(), который принимает ссылку на изменённый объект:

&НаКлиенте

Процедура ПослеЗаписиФоновогоИзменения()

// Сообщаем всем открытым формам, что объект изменился

ОповеститьОбИзменении(Объект.Ссылка);

КонецПроцедуры

Этот вызов заставит формы списков обновить соответствующие строки, а открытые формы того же объекта — перечитать данные. Платформа обрабатывает такое оповещение стандартно, дополнительный код на принимающей стороне не нужен.

Для нестандартных сценариев используется пара Оповестить() и обработчик ОбработкаОповещения в принимающей форме:

// В форме-источнике:

Оповестить("ИзмененыЦены", Новый Структура("Номенклатура, Цена", Товар, Цена), ЭтаФорма);

// В принимающей форме:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ИзмененыЦены" Тогда

ОбновитьСтрокуЦены(Параметр.Номенклатура, Параметр.Цена);

КонецЕсли;

КонецПроцедуры

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

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

Автоматическое обновление по таймеру

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

&НаКлиенте

Процедура ПриОткрытии(Отказ)

// Обновление списка каждые 30 секунд

ПодключитьОбработчикОжидания("ОбновитьДанныеПериодически", 30);

КонецПроцедуры

&НаКлиенте

Процедура ОбновитьДанныеПериодически()

Элементы.Список.Обновить();

КонецПроцедуры

&НаКлиенте

Процедура ПриЗакрытии(ЗавершениеРаботы)

ОтключитьОбработчикОжидания("ОбновитьДанныеПериодически");

КонецПроцедуры

Обязательно отключайте обработчик при закрытии формы — иначе платформа продолжит вызывать процедуру, что приведёт к ошибкам и лишней нагрузке. Интервал выбирайте исходя из реальной потребности: для оперативного монитора достаточно 30–60 секунд, более частые опросы редко оправданы и заметно нагружают сервер.

Более современная альтернатива таймеру — механизм системы взаимодействия и оповещения пользователей, когда обновление инициируется сервером по факту изменения данных. Но он требует настройки и оправдан не в каждой конфигурации; для большинства задач периодический опрос проще и предсказуемее.

Проверка результата и типичные ошибки

Контрольные точки

Как проверить, что обновление сработало

Значения в полях формы
Норма

После вызова метода поля показывают актуальные данные из базы

Тревожный признак

Поля не изменились — вероятно, вызван ОбновитьОтображениеДанных вместо Прочитать

Динамический список
Норма

Новая запись появилась в списке без переоткрытия формы

Тревожный признак

Запись не видна — не вызван Элементы.Список.Обновить() или не отправлено оповещение об изменении

Модифицированность
Норма

Признак модифицированности не сброшен ошибочно и изменения пользователя сохранены

Тревожный признак

Несохранённые данные пропали — Прочитать() вызван без проверки Модифицированность

Нагрузка
Норма

Обновление происходит мгновенно, интерфейс не подвисает

Тревожный признак

Форма дёргается или тормозит — слишком частый таймер или обновление в цикле

Типичные ошибки
01
Вызов ОбновитьОтображениеДанных() в ожидании свежих данных из базы — метод не читает базу, нужен Прочитать()
02
Попытка обновить динамический список через ОбновитьОтображениеДанных() — список обновляется только через Элементы.Список.Обновить()
03
Прочитать() без проверки модифицированности — несохранённые изменения пользователя теряются
04
Отсутствие ОтключитьОбработчикОжидания при закрытии формы — ошибки вызова и утечка ресурсов
05
Оповещение без уникального имени события — чужие формы реагируют на непредназначенные им события
06
Серверный вызов Прочитать() в клиентском контексте без директивы &НаСервере — ошибка компиляции или выполнения

Отдельно стоит упомянуть контекст вызова. Работа с объектом через Прочитать() — серверная операция. Если обработчик выполняется на клиенте, перенесите перечитывание в серверную процедуру, как показано в примерах выше. Смешение контекстов — одна из самых частых причин ошибок «Метод объекта не обнаружен» у начинающих разработчиков.

Итог

Что важно запомнить

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

Частые вопросы

Почему ОбновитьОтображениеДанных не показывает новые данные из базы?

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

Как обновить форму списка после записи элемента программно?

Если запись выполняется стандартно, платформа сама рассылает оповещение об изменении. При программной записи объекта в обход формы вызовите ОповеститьОбИзменении(Ссылка) на клиенте — все открытые списки этого типа обновятся автоматически. Либо обновите конкретный список: Элементы.Список.Обновить().

Можно ли обновить форму из фонового задания напрямую?

Нет, фоновое задание выполняется на сервере и не имеет доступа к клиентской форме. Схема такая: фоновое задание завершается, клиент получает результат через механизм длительных операций или по таймеру проверяет состояние, после чего обновляет форму на клиенте — перечитывает объект или обновляет список.

Чем отличается Оповестить от ОповеститьОбИзменении?

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

Как обновить только одну таблицу на форме, не трогая остальное?

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

Что делать, если обновление по таймеру тормозит работу пользователей?

Увеличьте интервал опроса до 30–60 секунд, обновляйте не всю форму, а только нужный список или элемент, и убедитесь, что обработчик отключается при закрытии формы. Если требуется мгновенная реакция на изменения, рассмотрите оповещения вместо постоянного опроса базы.