В многопользовательских решениях на платформе 1С:Предприятие 8 часто возникает задача оперативного отображения новых документов. Представим рабочее место оператора, диспетчера или менеджера по продажам: в систему постоянно поступают новые заказы, заявки или обращения. Для удобства в форме списка настраивают автообновление (например, каждые 15 секунд). Однако пользователи сталкиваются со следующей проблемой: новые документы добавляются в самый конец списка, и чтобы их увидеть, приходится постоянно прокручивать список колесиком мыши или перетаскивать бегунок скролла вниз.
В этой статье мы подробно разберем, почему стандартная прокрутка «вниз до упора» на клиенте программными методами — это не лучший путь, проанализируем особенности работы динамического списка платформы 1С и рассмотрим наиболее эффективные, проверенные на практике способы решения этой задачи.
Прежде чем переходить к коду и настройкам, давайте выясним техническую причину проблемы. Динамический список (объект ДинамическийСписок) в 1С устроен по принципу порционного считывания данных из базы данных. Платформа запрашивает с сервера СУБД ровно столько строк, сколько физически помещается на экране пользователя, плюс небольшой технологический запас.
На стороне клиента система изначально не знает общего количества записей в таблице и не хранит их в оперативной памяти. Когда пользователь начинает крутить скролл, платформа «на лету» подтягивает новые порции данных. Именно поэтому у динамического списка нет фиксированной шкалы прокрутки, а бегунок скролла может визуально менять свой размер. Программно симулировать нажатие клавиши «Page Down» или «End» до самого упора в таком списке без явного указания конкретной строки невозможно — платформа просто не поймет, к какому конечному индексу нужно обратиться.
Давайте рассмотрим 5 практических сценариев, как элегантно обойти это ограничение платформы и сделать работу пользователей комфортной.
Зададимся вопросом: зачем заставлять пользователя листать список вниз, если можно сделать так, чтобы новые документы всегда появлялись в самом верху? Это стандартное и наиболее эргономичное решение.
Для реализации этого подхода настроим сортировку динамического списка:
ДинамическийСписок (обычно он называется Список).Дата (или Ссылка) в значение Убывание (Убыв).В результате при автоматическом обновлении формы (даже раз в 15 секунд) новые документы будут мгновенно появляться на первой строчке экрана. Пользователю не придется делать никаких лишних движений.
Если специфика бизнес-процесса жестко требует сортировки по возрастанию (когда старые документы должны быть сверху, а новые снизу), мы можем управлять поведением списка при его открытии или принудительном программном обновлении.
У элемента формы типа «Таблица», который отображает динамический список, есть полезное свойство — Начальное отображение списка. По умолчанию оно установлено в значение Авто или В начале списка. Изменим его:
Теперь при каждом открытии формы курсор и область видимости будут автоматически позиционироваться на самом последнем документе. Однако помните, что при обычном циклическом автообновлении по таймеру фокус на клиенте сохраняется на текущей строке пользователя, чтобы не сбивать его работу.
Что делать, если сортировку менять нельзя, а автообновление происходит регулярно, и нам нужно «подсвечивать» новые документы? Мы можем использовать программную установку фокуса через свойство таблицы ТекущаяСтрока.
Важное предупреждение: Делать жесткое принудительное переключение фокуса каждые 15 секунд крайне не рекомендуется! Представьте ситуацию: пользователь изучает данные в середине списка, читает комментарий к документу двухдневной давности, и вдруг система сбрасывает его фокус и «уносит» экран вниз к только что созданному документу. Это вызовет только раздражение.
Поэтому программное позиционирование нужно делать аккуратно, например, только при открытии формы или по нажатию специальной кнопки «Перейти к новым». Рассмотрим пример программного кода для позиционирования на самом свежем документе:
&НаСервереБезКонтекста
Функция ПолучитьСсылкаНаПоследнийДокумент()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ЗаказКлиента.Ссылка КАК Ссылка
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
|УПОРЯДОЧИТЬ ПО
| ЗаказКлиента.Дата УБЫВ";
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
&НаКлиенте
Процедура ПерейтиКПоследнемуДокументу()
ПоследнийДокумент = ПолучитьСсылкаНаПоследнийДокумент();
Если ЗначениеЗаполнено(ПоследнийДокумент) Тогда
// Позиционируем динамический список на найденном документе
Элементы.Список.ТекущаяСтрока = ПоследнийДокумент;
КонецЕсли;
КонецПроцедуры
Давайте проанализируем ситуацию с точки зрения методологии разработки. Зачем пользователю видеть весь огромный массив документов в одной таблице и постоянно скроллить его? Как правило, менеджеру или оператору нужны только те документы, которые требуют его внимания прямо сейчас.
Лучшее решение этой проблемы — создание специализированного интерфейса АРМ. Разберем по шагам его концепцию:
СтатусОбработки (значения: Новый, ВРаботе, Выполнен).ВРаботе, и документ мгновенно исчезает из списка при следующем автообновлении.При таком подходе в списке всегда будет находиться минимальное количество строк (обычно не более одного экрана). Скроллбар исчезнет за ненадобностью, а новые документы будут сразу появляться перед глазами.
Если мы не хотим принудительно двигать экран пользователя, но обязаны сообщить ему о появлении важного документа, задействуем механизмы push-уведомлений платформы.
Для этих целей отлично подходит Система взаимодействия (начиная с версии платформы 8.3.16) или метод всплывающих окон ПоказатьОповещениеПользователя(). Настроим периодическую проверку базы данных в фоновом режиме на клиенте через обработчик ожидания:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем проверку раз в 30 секунд
ПодключитьОбработчикОжидания("ПроверитьНовыеДокументы", 30);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьНовыеДокументы()
НовыйДокумент = ПроверитьНаличиеНовыхДокументовНаСервере(ПоследняяЗаписаннаяДата);
Если ЗначениеЗаполнено(НовыйДокумент) Тогда
// Запоминаем дату последней проверки
ПоследняяЗаписаннаяДата = ТекущаяДата();
// Показываем красивое всплывающее окно в углу экрана
ПоказатьОповещениеПользователя(
"Добавлен новый документ!",
ПолучитьНавигационнуюСсылку(НовыйДокумент),
"Нажмите, чтобы открыть или спозиционироваться",
БиблиотекаКартинок.Информация
);
КонецЕсли;
КонецПроцедуры
При нажатии на такое оповещение пользователь сможет моментально открыть новый документ в отдельном окне или перенаправить фокус динамического списка на него, не нарушая текущую работу с интерфейсом.