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