Как правильно получить количество элементов в динамическом списке с учетом всех отборов?

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

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

Анализ проблемы: почему нет простого свойства «Количество»?

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

Решение 1: Использование методов исполняемой схемы компоновки данных

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

Рассмотрим пошаговый алгоритм реализации этого метода:

  1. Получим исполняемую схему компоновки данных (СКД) динамического списка.
  2. Получим исполняемые настройки, которые учитывают все пользовательские действия: поиск, отборы, группировки.
  3. Программно модифицируем схему, чтобы она возвращала только количество записей.
  4. Выполним расчет на сервере.

Разберем пример кода, который выполняет эти действия:


&НаСервере
Функция ПолучитьКоличествоЭлементовСписка() Экспорт
    
    // Получаем схему и настройки динамического списка
    Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
    Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
    
    // Создаем макет компоновки
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    // Выполняем запрос с помощью процессора компоновки
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
    
    // Мы можем выгрузить результат в таблицу или просто посчитать количество
    // Но эффективнее изменить сам текст запроса в схеме на COUNT(*)
    // Для простоты примера посчитаем количество строк в выгрузке (подходит для небольших выборок)
    ДанныеРезультата = Новый ТаблицаЗначений;
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ПроцессорВывода.УстановитьОбъект(ДанныеРезультата);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    Возврат ДанныеРезультата.Количество();
    
КонецФункции

Важный нюанс: метод ПолучитьИсполняемыеНастройкиКомпоновкиДанных() уникален тем, что он «видит» строку поиска, введенную пользователем в стандартное поле поиска 1С, в то время как обычный КомпоновщикНастроек списка может содержать только пустые отборы.

Решение 2: Подсчет через фоновое задание для тяжелых списков

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

Схема работы будет следующей:

  1. При изменении отборов в списке мы запускаем фоновое задание на сервере.
  2. Фоновое задание выполняет запрос ВЫБРАТЬ КОЛИЧЕСТВО(*) с учетом переданных настроек.
  3. По завершении задания форма получает результат и обновляет декорацию (надпись) с количеством.
  4. Пока задание выполняется, пользователь видит надпись «Считаю...» или анимированную картинку, при этом интерфейс остается отзывчивым.

Решение 3: Выбор правильного обработчика события

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

Проблема полнотекстового поиска

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

Оптимизация: Пороговые значения (1000+)

Хорошим тоном в разработке считается использование пороговых значений. Вместо того чтобы заставлять сервер считать 5 432 211 записей, можно ограничить запрос:


// В тексте запроса для подсчета
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1001 ..."

Если запрос вернул 1001 запись, мы выводим пользователю надпись "Более 1000". Это стандартный паттерн проектирования интерфейсов (как в поиске Google или крупных интернет-магазинах), который экономит ресурсы сервера и дает пользователю достаточное представление о масштабе данных.

Резюме

Мы разобрали, что «приготовить» количество элементов в динамическом списке можно несколькими способами. Выбор зависит от объема данных и требований к отзывчивости интерфейса. Для небольших справочников идеально подходит использование ПолучитьИсполняемыеНастройкиКомпоновкиДанных в связке с простым запросом. Для высоконагруженных систем предпочтительнее асинхронный подсчет через фоновые задания или использование пороговых ограничений.

← На главную