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

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

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

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

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

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

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

Метод Обновить() элемента формы — простой способ

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

&НаКлиенте

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

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

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

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

Метод заставляет платформу заново выполнить запрос динамического списка и перечитать видимую порцию данных. Это удобно после программной записи объекта в той же форме или после обработки, которая меняла данные через серверный вызов.

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

Порядок действий
  1. 1
    Найдите имя таблицы формы, связанной с динамическим списком (дерево элементов формы)
  2. 2
    В клиентской процедуре вызовите Элементы.ИмяТаблицы.Обновить()
  3. 3
    Если данные менялись на сервере — вызывайте Обновить() после возврата из серверного вызова
  4. 4
    Проверьте, что список показывает новые или изменённые записи

ОповеститьОбИзменении — обновление всех списков нужного типа

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

&НаКлиенте

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

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

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

Можно передать не только тип, но и конкретную ссылку на изменённый объект — тогда платформа обновит данные точечнее, а заодно формы объектов, отображающие эту ссылку:

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

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

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

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

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

&НаСервере

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

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

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

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

Если вы меняете настройки через компоновщик настроек списка (Список.КомпоновщикНастроек), убедитесь, что изменённые элементы отбора включены (Использование = Истина) — отключённый элемент отбора не влияет на запрос, и список визуально «не реагирует».

ЭлементОтбора = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(

Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Склад");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = ВыбранныйСклад;

ЭлементОтбора.Использование = Истина;

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

У динамического списка есть встроенный механизм периодического обновления. В свойствах реквизита списка (в конфигураторе или программно) доступны настройки Автообновление и ПериодАвтообновления (в секундах).

&НаСервере

Процедура ВключитьАвтообновление()

Список.Автообновление = Истина;

Список.ПериодАвтообновления = 60;

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

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

Не ставьте слишком маленький период для тяжёлых запросов: каждое автообновление — это обращение к СУБД. На больших таблицах с частым обновлением это заметно нагружает сервер и может вызывать блокировки при конкурентной работе.

Обновление из фонового задания и между сеансами

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

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

Для оповещения между сеансами разных пользователей встроенного простого механизма нет. Практические варианты: автообновление списка с разумным периодом, ручное обновление пользователем (кнопка F5/«Обновить») или долгие опросы через механизмы взаимодействия, если они внедрены в прикладном решении.

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

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

Точечное обновление одной таблицы на текущей форме. Только на клиенте, не действует на другие формы.

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

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

Автообновление списка

Периодическое обновление без кода. Подходит для мониторинга, но нагружает СУБД при малом периоде.

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

Список перевыполняет запрос сам. Используется, когда меняется не только данные, но и условия выборки.

Типичные ошибки и как их диагностировать

Самая частая жалоба — «вызываю обновление, а список не меняется». Причины обычно одни и те же, и их легко проверить по шагам.

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

Вторая причина — обновляется не тот элемент. На форме может быть несколько таблиц, и Элементы.Список — не всегда нужная. Проверьте имя элемента в дереве формы и его свойство «ПутьКДанным».

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

Типичные ошибки
01
Вызов Обновить() на сервере — метод недоступен вне клиентского контекста, код падает или молча не работает при обёртке в попытку
02
Обновление до завершения записи данных — список перечитывает старое состояние
03
Ожидание, что ОповеститьОбИзменении обновит списки других пользователей — метод работает только в текущем сеансе
04
Изменение отбора компоновщика без Использование = Истина — отбор не применяется, список выглядит необновлённым
05
Слишком частое автообновление тяжёлого запроса — рост нагрузки на СУБД и блокировки

Проверка результата и оптимизация

После внедрения обновления проверьте три вещи: список действительно показывает новые данные, текущая строка не «слетает» без необходимости и форма не начала тормозить.

При полном перевыполнении запроса текущая позиция списка может сбрасываться. Если это критично, перед обновлением запомните текущую ссылку (Элементы.Список.ТекущаяСтрока) и восстановите её после обновления.

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

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

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

Новые данные в списке
Норма

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

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

Записи появляются только после закрытия и открытия формы

Позиция курсора
Норма

Текущая строка сохраняется или осознанно сбрасывается

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

Курсор каждый раз прыгает в начало списка

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

Запрос списка выполняется не чаще, чем нужно по логике задачи

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

Запрос выполняется в цикле или каждые несколько секунд без необходимости

Итог

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

На форме используйте Элементы.ИмяТаблицы.Обновить(), после программной записи данных — ОповеститьОбИзменении(Тип или ссылка), для постоянного мониторинга — автообновление с разумным периодом. Все визуальные обновления работают только на клиенте и в рамках текущего сеанса.

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

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

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

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

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

Как обновить список у другого пользователя?

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

Чем отличается Обновить() от ОповеститьОбИзменении?

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

Как сохранить текущую строку при обновлении списка?

Перед обновлением сохраните значение Элементы.Список.ТекущаяСтрока (это ссылка или ключ записи), а после обновления присвойте его обратно. Если запись всё ещё попадает под отбор списка, курсор вернётся на неё.

Влияет ли автообновление на производительность?

Да. Каждое срабатывание — это выполнение запроса на СУБД у каждого пользователя с открытой формой. Для списков с произвольным запросом, соединениями и большими таблицами выбирайте период в десятки секунд и выше, а при возможности заменяйте автообновление событийной логикой через ОповеститьОбИзменении.