Как реализовать автоматический переход к новым записям в списке регистра сведений 1С

Программист 1С v8.3 (Управляемые формы)
← На главную

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

В этой статье мы подробно разберем, почему так происходит, и проанализируем программные способы заставить список всегда отображать самые актуальные данные.

Выясним причину: почему стандартное автообновление «не двигает» список

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

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

Способ 1. Использование программного обработчика ожидания

Для решения задачи нам придется отказаться от стандартного флажка в свойствах и перейти к программному управлению. Разберем по шагам, как это реализовать.

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


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Интервал обновления в секундах, например, 5 секунд
    ПодключитьОбработчикОжидания("ОбновитьСписокИПерейтиВНачало", 5);
КонецПроцедуры

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


&НаКлиенте
Процедура ОбновитьСписокИПерейтиВНачало()
    // Обновляем данные в динамическом списке
    Элементы.Список.Обновить();
    
    // Пытаемся получить ключ самой первой записи в списке
    // Для этого можно использовать данные самого списка, если они уже подгружены
    МассивСтрок = Элементы.Список.ДанныеПросмотра.ПолучитьЭлементы();
    Если МассивСтрок.Количество() > 0 Тогда
        // Устанавливаем фокус на самую первую (верхнюю) строку
        Элементы.Список.ТекущаяСтрока = МассивСтрок[0].ПолучитьИдентификатор();
    КонецЕсли;
КонецПроцедуры

Способ 2. Управление фокусом через получение ключа записи

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

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


&НаСервереБезКонтекста
Функция ПолучитьКлючСамойСвежейЗаписи()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |   Регистр.Период,
        |   Регистр.Регистратор,
        |   Регистр.НомерСтроки
        |ИЗ
        |   РегистрСведений.ИмяВашегоРегистра КАК Регистр
        |УПОРЯДОЧИТЬ ПО
        |   Регистр.Период УБЫВ";
    
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        
        // Формируем структуру ключа записи (зависит от состава измерений)
        СтруктураКлюча = Новый Структура("Период", Выборка.Период);
        Возврат РегистрыСведений.ИмяВашегоРегистра.СоздатьКлючЗаписи(СтруктураКлюча);
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Затем в обработчике ожидания на клиенте мы используем этот ключ:


&НаКлиенте
Процедура ОбновитьСписокИПерейтиВНачало()
    Элементы.Список.Обновить();
    СвежийКлюч = ПолучитьКлючСамойСвежейЗаписи();
    Если СвежийКлюч <> Неопределено Тогда
        Элементы.Список.ТекущаяСтрока = СвежийКлюч;
    КонецЕсли;
КонецПроцедуры

Важные нюансы и ограничения

При реализации подобного функционала следует помнить о нескольких критически важных моментах:

  1. Нагрузка на сервер: Слишком частые запросы (раз в 1-2 секунды) могут существенно нагрузить систему, особенно если в списке много пользователей. Оптимальный интервал — от 5 до 30 секунд.
  2. Прерывание работы пользователя: Если пользователь начал что-то писать в строке поиска или пытается вручную просмотреть старые записи, программный «прыжок» вверх прервет его действия. Рекомендуется добавлять на форму флаг (чек-бокс) Режим мониторинга, чтобы пользователь сам решал, нужно ли ему автоматическое перемещение курсора.
  3. Особенности отрисовки: В управляемом приложении установка ТекущаяСтрока заставляет платформу сфокусироваться на элементе, но визуально прокрутка может сработать с небольшой задержкой.
  4. Сброс выделения: Если вы хотите, чтобы список просто «подтянулся» вверх, не обязательно всегда жестко фиксировать курсор. Иногда достаточно вызвать метод ОповеститьОбИзменении(Тип("РегистрСведенийЗапись.ИмяВашегоРегистра")), если запись данных происходит в этой же сессии.

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

← На главную