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

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

Как программно обновить динамический список в 1С 8

Как программно обновить динамический список в 1С 8.3: метод Обновить(), Элементы.Список.Обновить, обновление из формы и внешней обработки, типовые ошибки.

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

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

Ниже разобраны рабочие приёмы с примерами кода, условия их применения, ограничения платформы и типичные ошибки, из-за которых список «не обновляется», хотя код выполняется без сообщений об ошибках.

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

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

&НаКлиенте

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

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

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

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

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

bsl
&НаКлиенте
Процедура ОбновитьСписок(Команда)
	Элементы.Список.Обновить();
КонецПроцедуры

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

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

&НаСервере

Процедура УстановитьПериодНаСервере()

Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", НачалоДня(ТекущаяДатаСеанса()));

Список.Параметры.УстановитьЗначениеПараметра("КонецПериода", КонецДня(ТекущаяДатаСеанса()));

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

Здесь Список — реквизит формы типа «ДинамическийСписок». Само по себе изменение параметра заставляет платформу перевыполнить запрос, отдельный вызов Обновить() обычно не требуется. Это важное отличие: при смене параметра список перечитывается автоматически.

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

Как обновить список из другой формы через оповещения

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

&НаКлиенте

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

ОповеститьОбИзменении(Тип("ДокументСсылка.РеализацияТоваровУслуг"));

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

Все открытые динамические списки, основная таблица которых соответствует указанному типу, получат оповещение и перечитают данные. Это штатный механизм платформы: именно так формы объектов уведомляют списки при интерактивной записи.

Второй вариант — метод Оповестить() с произвольным именем события. Форма списка подписывается на событие в обработчике ОбработкаОповещения и выполняет обновление:

// В форме, инициирующей обновление:

Оповестить("ИзмененыДанныеРегистраОстатков");

// В форме списка:

&НаКлиенте

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

Если ИмяСобытия = "ИзмененыДанныеРегистраОстатков" Тогда

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

КонецЕсли;

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

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

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

Обновление после фонового задания и длительной операции

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

Решение — вернуть из фонового задания признак завершения (в типовых механизмах БСП это длительные операции с обработчиком ожидания) и в клиентском обработчике завершения вызвать обновление списка:

&НаКлиенте

Процедура ОбработатьЗавершениеФоновогоЗадания(Результат, ДополнительныеПараметры) Экспорт

Если Результат <> Неопределено Тогда

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

КонецЕсли;

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

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

Почему список не обновляется: типичные причины

Наиболее частая причина «неработающего» обновления — обращение не к тому имени. Элементы.Список — это элемент формы, а Список без Элементы — реквизит формы. У реквизита нет метода Обновить(); попытка вызвать Список.Обновить() приведёт к ошибке. Проверьте в конфигураторе фактическое имя таблицы формы.

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

Третья причина — список с произвольным запросом и собственной настройкой отбора, который перекрывает новые строки. Данные в базе есть, запрос перечитывается, но новая строка не попадает под условия отбора. Проверяйте Список.Отбор и пользовательские настройки, прежде чем искать ошибку в коде обновления.

Типичные ошибки
01
Вызов Список.Обновить() у реквизита формы вместо Элементы.Список.Обновить() — ошибка выполнения или отсутствие эффекта.
02
Ожидание, что ОповеститьОбИзменении() обновит список на произвольном запросе — платформа не связывает тип данных с таким источником, нужно Оповестить() с обработчиком.
03
Обновление списка в цикле после записи каждого объекта — десятки лишних запросов к базе; обновляйте один раз после цикла.
04
Изменение ТекстЗапроса при каждом обновлении — сброс динамического считывания и деградация производительности.

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

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

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

На практике эти приёмы комбинируются: например, после записи объекта вызывается ОповеститьОбИзменении(), а форма списка с произвольным запросом дополнительно подписана на пользовательское событие.

Сравнение вариантов

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

Подходит для обновления из модуля самой формы. Не работает из других форм и внешних обработок без доступа к форме.

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

Штатный способ уведомить все открытые списки по типу данных. Не срабатывает для списков на произвольных запросах.

Оповестить() с событием

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

Установка параметров

Нужна при изменении условий выборки. Перечитывает список автоматически, но требует параметров в тексте запроса.

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

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

Для оповещений полезно временно добавить в обработчик ОбработкаОповещения вывод сообщения с именем события: так видно, доходит ли оповещение до формы вообще. Если событие приходит, а список не меняется — проблема в отборе или в тексте запроса, а не в механизме обновления.

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

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

Вызов Обновить() выполняется без ошибок
Норма

Строки списка перечитываются, изменённые данные видны сразу

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

Ошибка 'Метод не обнаружен' — обращение идёт к реквизиту, а не к элементу формы

Оповещение доходит до формы списка
Норма

ОбработкаОповещения срабатывает, список обновляется

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

Обработчик не вызывается — имя события не совпадает или форма закрыта

Новая строка видна после обновления
Норма

Строка появляется в списке

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

Строка в базе есть, но не видна — её отсекает отбор или условие произвольного запроса

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

Можно ли обновить динамический список из внешней обработки?

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

Почему список обновляется сам, а иногда нет?

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

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

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

Как обновить список периодически, например раз в минуту?

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

Обновление сбрасывает текущую строку списка. Как этого избежать?

Перед обновлением сохраните текущую ссылку: ТекущаяСсылка = Элементы.Список.ТекущаяСтрока. После Обновить() восстановите позиционирование: Элементы.Список.ТекущаяСтрока = ТекущаяСсылка. Это работает, если строка не была удалена из выборки.

Нужно ли обновлять список после изменения его параметров?

Нет. Установка значения параметра через Список.Параметры.УстановитьЗначениеПараметра() сама инициирует перевыполнение запроса. Дополнительный вызов Обновить() приведёт к повторному обращению к базе без пользы.

Итог

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

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