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