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

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

Как программно обновить данные формы в 1С

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

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

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

Материал ориентирован на управляемые формы (так называемый такси-интерфейс), где действует разделение на клиентский и серверный контекст. Часть методов выполняется только на сервере, часть — только на клиенте, и путаница между ними — главный источник ошибок.

Какие данные формы нужно обновить: определяем тип задачи

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

Основной реквизит формы (например, Объект в форме документа или справочника) — это данные редактируемого объекта, загруженные при открытии формы. Динамический список — это данные запроса, отображаемые в таблице формы списка. Реквизиты формы произвольного типа — вспомогательные данные, которые вы добавили сами. Наконец, есть просто визуальное отображение элементов, которое иногда отстаёт от реальных данных.

Маршрут решения

Как выбрать метод обновления

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

Перечитывание объекта из базы: метод Прочитать()

Метод Прочитать() у формы объекта заново загружает данные из информационной базы в основной реквизит формы. Это серверный метод — вызывать его нужно в контексте &НаСервере. Типичный сценарий — данные объекта изменил другой пользователь, фоновое задание или обмен, и нужно показать актуальные значения.

&НаСервере

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

Прочитать();

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

&НаКлиенте

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

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

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

Важное ограничение: Прочитать() затирает все несохранённые изменения, внесённые пользователем в форму. Если пользователь редактировал поля, а вы вызвали перечитывание — его правки будут потеряны без предупреждения. Безопасный шаблон — проверять свойство Модифицированность и при необходимости задавать вопрос пользователю.

Если объект был изменён в базе после того, как форма его прочитала, при попытке записи возникнет ошибка «Данные были изменены другим пользователем». В этом случае Прочитать() — единственный способ синхронизировать форму с базой, но потерянные правки придётся вводить заново.

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

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

&НаКлиенте

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

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

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

Если список настроен с произвольным запросом и параметрами, простого Обновить() может быть недостаточно — проверьте, что параметры запроса установлены корректно. Изменение параметров динамического списка выполняется через Список.Параметры.УстановитьЗначениеПараметра(), после чего список обновляется автоматически.

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

ОбновитьОтображениеДанных: когда данные верны, а экран устарел

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

&НаКлиенте

Процедура ПослеИзмененияРеквизита()

Объект.СуммаДокумента = Объект.Товары.Итог("Сумма");

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

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

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

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

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

Оповещения между формами: Оповестить и ОповеститьОбИзменении

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

&НаКлиенте

Процедура ПослеЗаписи(ПараметрыЗаписи)

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

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

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

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

&НаКлиенте

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

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

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

КонецЕсли;

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

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

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

Обновление после фоновых операций и обмена данными

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

Обработчик ожидания подключается на клиенте и вызывает указанную процедуру с заданным интервалом. Не ставьте слишком маленький интервал: каждое срабатывание — это обращение к серверу и нагрузка на базу. Для большинства сценариев разумный интервал — от 15–30 секунд и выше, а лучше обновлять только при активности пользователя.

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

Если форма списка не обновляется после записи элемента, сначала проверьте, не отключено ли у динамического списка свойство «Автоматическое обновление» и не переопределён ли запрос списка с жёстким отбором, который исключает новую запись.
ПЗ
Практическое замечание

Проверка результата и границы безопасной работы

После внедрения обновления проверьте три вещи: форма показывает актуальные данные, несохранённые правки пользователя не теряются, интерфейс не начал подтормаживать из-за лишних обращений к серверу. Все три пункта проверяются вручную за несколько минут.

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

Как проверить результат

Актуальность данных
Норма

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

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

Форма показывает старые значения до ручного закрытия и открытия

Сохранность правок
Норма

При обновлении несохранённые изменения пользователя сохраняются или выдаётся вопрос

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

Введённые пользователем данные молча затираются

Производительность
Норма

Обновление происходит по событию или с разумным интервалом

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

Список дёргается каждые секунды, интерфейс тормозит, растёт нагрузка на сервер

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

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

Чем отличается Прочитать() от ОбновитьОтображениеДанных()?

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

Почему Элементы.Список.Обновить() выдаёт ошибку?

Чаще всего метод вызван в серверном контексте — он доступен только на клиенте. Вторая причина: у формы нет элемента с именем «Список» — проверьте фактическое имя таблицы динамического списка в дереве элементов формы.

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

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

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

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

Форма списка не обновляется сама после записи — в чём причина?

Проверьте свойство «Автоматическое обновление» динамического списка, произвольный запрос с отбором, исключающим новые записи, и установленные параметры списка. Также убедитесь, что запись объекта завершилась успешно и не была отменена в обработчиках ПередЗаписью или ПриЗаписи.

Как обновить только одно поле формы, а не всё целиком?

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

Итог

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

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