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