Разработка и Конфигурация · 12 мин
Как программно обновить форму в 1С 8.3
Способы программного обновления формы в 1С 8.3: ОбновитьОтображениеДанных, Прочитать, оповещения. Примеры кода, типичные ошибки и проверка результата.
Задача обновить форму программно возникает всякий раз, когда данные на сервере изменились, а открытая форма продолжает показывать устаревшие значения. Типичные ситуации: фоновое задание записало документ, обработка изменила регистр сведений, внешняя система обновила справочник, а пользователь видит старые данные до тех пор, пока не закроет и не откроет форму заново.
В платформе 1С:Предприятие 8.3 есть несколько принципиально разных механизмов обновления: метод ОбновитьОтображениеДанных(), повторное чтение объекта через Прочитать(), система оповещений Оповестить() и ОповеститьОбИзменении(), а также перечитывание динамических списков. Они не взаимозаменяемы: один метод перерисовывает интерфейс, другой заново загружает данные из базы, третий сообщает другим формам, что объект изменился.
Ошибка в выборе метода приводит либо к лишним обращениям к базе данных и падению производительности, либо к обратной проблеме — форма выглядит обновлённой, но данные в ней устарели. Ниже разобраны все основные способы с примерами кода, условиями выбора и способами проверки результата.
Чем отличаются способы обновления формы
Прежде чем писать код, нужно понять, какой именно слой требуется обновить. В управляемой форме 1С есть три уровня: отображение (как элементы выглядят на экране), данные формы (реквизиты и объект в памяти) и данные в информационной базе. Разные методы работают на разных уровнях.
Сравнение способов обновления
Только перерисовывает элементы формы по текущим данным в памяти. Не читает базу. Подходит после программного изменения реквизитов формы.
Заново загружает объект из базы в форму, затирая несохранённые изменения. Подходит, когда объект изменён другим сеансом или фоновым заданием.
Сообщает всем открытым формам, что объект записан. Формы списков и связанные формы обновятся сами. Вызывается после записи.
Перевыполняет запрос динамического списка. Нужен, когда изменились данные, отображаемые списком, но сам объект формы не затронут.
Гибкий механизм: одна форма шлёт событие, другая реагирует в ОбработкаОповещения. Требует ручной реализации на принимающей стороне.
Частая ошибка — вызывать ОбновитьОтображениеДанных() и ждать, что форма покажет свежие данные из базы. Этот метод работает только с тем, что уже загружено в память формы. Если запись в базе изменил другой сеанс, сначала нужно перечитать объект, и только потом обновлять отображение.
ОбновитьОтображениеДанных: перерисовка без чтения базы
Метод ОбновитьОтображениеДанных() вызывается у формы и заставляет платформу заново вывести значения в элементы управления. Это самый лёгкий способ обновления: обращения к базе данных не происходит, поэтому метод безопасно вызывать часто.
&НаКлиенте
Процедура ПересчитатьИтоги(Команда)
// Меняем реквизиты формы программно
Объект.Сумма = Объект.Количество * Объект.Цена;
// Перерисовываем элементы формы
ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры
Методу можно передать конкретный элемент формы — тогда обновится только он: ЭтаФорма.ОбновитьОтображениеДанных(Элементы.СписокТоваров). Это полезно в формах с большим числом элементов, где полная перерисовка заметна по времени.
Типичный сценарий применения — программное заполнение табличной части или реквизитов в обработчике на клиенте. Платформа в ряде случаев обновляет отображение сама, но при массовых изменениях в цикле или после обработки результата фонового задания явный вызов гарантирует, что пользователь увидит актуальные значения.
Перечитывание объекта через Прочитать
Если данные объекта изменились в базе — например, фоновое задание дозаполнило документ или другой пользователь записал новую версию — нужен метод Прочитать(). В модуле формы объекта доступен вызов ЭтаФорма.Прочитать() (для основного реквизита формы) либо работа через объект на сервере.
&НаСервере
Процедура ПеречитатьОбъектНаСервере()
// Перечитываем объект из базы в данные формы
ЭтаФорма.Прочитать();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьИзБазы(Команда)
Если Объект.Модифицированность Тогда
ПоказатьПредупреждение(, "Сначала запишите изменения — они будут потеряны");
Возврат;
КонецЕсли;
ПеречитатьОбъектНаСервере();
КонецПроцедуры
Есть и альтернативный путь через ЗначениеВРеквизитФормы: получить объект методом РеквизитФормыВЗначение("Объект"), вызвать у него Прочитать() и вернуть обратно. Такой подход нужен редко — в основном когда требуется дополнительная логика с объектом до отображения, например заполнение дополнительных реквизитов формы по данным объекта.
Обновление динамического списка
Формы списков документов, справочников и регистров построены на динамических списках. Они не обновляются от ОбновитьОтображениеДанных() — нужен перезапуск запроса, который лежит в основе списка.
&НаКлиенте
Процедура ОбновитьСписок(Команда)
Элементы.Список.Обновить();
КонецПроцедуры
Обратите внимание: метод Обновить() вызывается у элемента формы (таблицы, связанной со списком), а не у самой формы. Если элемент называется иначе, подставьте его имя. После вызова платформа заново выполнит запрос динамического списка с текущими отборами и настройками.
Если список должен обновляться при записи элементов из других форм, ручной вызов не нужен — достаточно, чтобы в форме элемента после записи вызывался ОповеститьОбИзменении() (платформа делает это автоматически при стандартной записи). Тогда все открытые списки, отображающие этот тип данных, обновятся сами.
Оповещения: обновление других форм
Когда изменения сделаны в одной форме, а отобразить их нужно в другой, работает система оповещений. Базовый вариант — ОповеститьОбИзменении(), который принимает ссылку на изменённый объект:
&НаКлиенте
Процедура ПослеЗаписиФоновогоИзменения()
// Сообщаем всем открытым формам, что объект изменился
ОповеститьОбИзменении(Объект.Ссылка);
КонецПроцедуры
Этот вызов заставит формы списков обновить соответствующие строки, а открытые формы того же объекта — перечитать данные. Платформа обрабатывает такое оповещение стандартно, дополнительный код на принимающей стороне не нужен.
Для нестандартных сценариев используется пара Оповестить() и обработчик ОбработкаОповещения в принимающей форме:
// В форме-источнике:
Оповестить("ИзмененыЦены", Новый Структура("Номенклатура, Цена", Товар, Цена), ЭтаФорма);
// В принимающей форме:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ИзмененыЦены" Тогда
ОбновитьСтрокуЦены(Параметр.Номенклатура, Параметр.Цена);
КонецЕсли;
КонецПроцедуры
Имя события — произвольная строка. Рекомендуется давать осмысленные уникальные имена, чтобы разные механизмы не пересекались, и проверять параметр Источник, если форма должна реагировать только на конкретного отправителя.
- 1В форме-источнике после изменения данных вызовите Оповестить() с уникальным именем события
- 2Передайте в параметре структуру с данными, нужными принимающей форме
- 3В принимающей форме создайте обработчик ОбработкаОповещения
- 4Проверьте ИмяСобытия и при совпадении выполните обновление данных или списка
- 5Откройте обе формы и проверьте, что изменение в одной отражается в другой
Автоматическое обновление по таймеру
Для мониторов и рабочих мест, где данные должны обновляться без действий пользователя, применяется ПодключитьОбработчикОжидания(). Обработчик подключается на клиенте и вызывается с заданной периодичностью:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Обновление списка каждые 30 секунд
ПодключитьОбработчикОжидания("ОбновитьДанныеПериодически", 30);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДанныеПериодически()
Элементы.Список.Обновить();
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
ОтключитьОбработчикОжидания("ОбновитьДанныеПериодически");
КонецПроцедуры
Обязательно отключайте обработчик при закрытии формы — иначе платформа продолжит вызывать процедуру, что приведёт к ошибкам и лишней нагрузке. Интервал выбирайте исходя из реальной потребности: для оперативного монитора достаточно 30–60 секунд, более частые опросы редко оправданы и заметно нагружают сервер.
Более современная альтернатива таймеру — механизм системы взаимодействия и оповещения пользователей, когда обновление инициируется сервером по факту изменения данных. Но он требует настройки и оправдан не в каждой конфигурации; для большинства задач периодический опрос проще и предсказуемее.
Проверка результата и типичные ошибки
Как проверить, что обновление сработало
После вызова метода поля показывают актуальные данные из базы
Поля не изменились — вероятно, вызван ОбновитьОтображениеДанных вместо Прочитать
Новая запись появилась в списке без переоткрытия формы
Запись не видна — не вызван Элементы.Список.Обновить() или не отправлено оповещение об изменении
Признак модифицированности не сброшен ошибочно и изменения пользователя сохранены
Несохранённые данные пропали — Прочитать() вызван без проверки Модифицированность
Обновление происходит мгновенно, интерфейс не подвисает
Форма дёргается или тормозит — слишком частый таймер или обновление в цикле
Отдельно стоит упомянуть контекст вызова. Работа с объектом через Прочитать() — серверная операция. Если обработчик выполняется на клиенте, перенесите перечитывание в серверную процедуру, как показано в примерах выше. Смешение контекстов — одна из самых частых причин ошибок «Метод объекта не обнаружен» у начинающих разработчиков.
Что важно запомнить
Выбирайте метод по слою обновления: ОбновитьОтображениеДанных — для перерисовки, Прочитать — для данных из базы (с проверкой модифицированности), Элементы.Список.Обновить — для динамических списков, ОповеститьОбИзменении и Оповестить — для обновления других открытых форм. Для периодического обновления используйте обработчик ожидания с отключением при закрытии формы.
Частые вопросы
Почему ОбновитьОтображениеДанных не показывает новые данные из базы?
Метод работает только с данными, уже загруженными в память формы, и не обращается к базе. Если объект изменён другим сеансом или фоновым заданием, сначала вызовите ЭтаФорма.Прочитать() на сервере, а затем при необходимости обновите отображение.
Как обновить форму списка после записи элемента программно?
Если запись выполняется стандартно, платформа сама рассылает оповещение об изменении. При программной записи объекта в обход формы вызовите ОповеститьОбИзменении(Ссылка) на клиенте — все открытые списки этого типа обновятся автоматически. Либо обновите конкретный список: Элементы.Список.Обновить().
Можно ли обновить форму из фонового задания напрямую?
Нет, фоновое задание выполняется на сервере и не имеет доступа к клиентской форме. Схема такая: фоновое задание завершается, клиент получает результат через механизм длительных операций или по таймеру проверяет состояние, после чего обновляет форму на клиенте — перечитывает объект или обновляет список.
Чем отличается Оповестить от ОповеститьОбИзменении?
ОповеститьОбИзменении — стандартный сигнал о записи объекта, платформа сама реагирует на него в формах списков и связанных формах. Оповестить — произвольное событие с вашим именем и параметрами; принимающая форма должна сама реализовать обработчик ОбработкаОповещения и решить, как реагировать.
Как обновить только одну таблицу на форме, не трогая остальное?
Передайте элемент в ОбновитьОтображениеДанных: ЭтаФорма.ОбновитьОтображениеДанных(Элементы.Товары). Для таблицы, связанной с динамическим списком, вызовите Обновить() именно у этого элемента. Это снижает нагрузку по сравнению с полной перерисовкой формы.
Что делать, если обновление по таймеру тормозит работу пользователей?
Увеличьте интервал опроса до 30–60 секунд, обновляйте не всю форму, а только нужный список или элемент, и убедитесь, что обработчик отключается при закрытии формы. Если требуется мгновенная реакция на изменения, рассмотрите оповещения вместо постоянного опроса базы.