Как получить количество строк в списке 1С 8.3 с учетом наложенного отбора?

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

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

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

Способ 1. Получение исполняемой схемы компоновки данных (для управляемых форм)

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

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

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

Посмотрим на пример реализации серверной функции:


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

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

Способ 2. Использование Построителя отчета или Построителя запроса (для обычных форм)

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


// Пример переноса отбора строк таблицы или списка в ПостроительОтчета
ТекОтбор = ЭлементыФормы.ТаблицаЗначенийНужная.ОтборСтрок;

Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаЗначенийНужная);

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

РезультатЗапроса = Построитель.Результат;
Выборка = РезультатЗапроса.Выбрать();
КоличествоСтрок = РезультатЗапроса.Выгрузить().Количество();

Способ 3. Прямой запрос к таблице базы данных с подсчетом агрегата КОЛИЧЕСТВО(*)

Если структура фильтров фиксирована или известна заранее, наиболее производительным решением будет выполнение прямого запроса к таблице базы данных с использованием агрегатной функции КОЛИЧЕСТВО(*). Это исключает передачу больших массивов строк по сети и расчет выполняется на стороне СУБД:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КОЛИЧЕСТВО(СправочникТаблица.Ссылка) КАК ВсегоСтрок
    |ИЗ
    |	Справочник.Номенклатура КАК СправочникТаблица
    |ГДЕ
    |	НЕ СправочникТаблица.ПометкаУдаления
    |	И СправочникТаблица.ВидНоменклатуры = &ВидНоменклатуры";

Запрос.УстановитьПараметр("ВидНоменклатуры", ВыбранныйВид);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
    ВсегоЭлементов = Выборка.ВсегоСтрок;
КонецЕсли;

Ограничения и рекомендации по оптимизации

При реализации подсчета количества строк обратим внимание на ключевые технические нюансы:

  1. Нагрузка на СУБД: Полный подсчет записей в больших таблицах (сотни тысяч или миллионы строк) требует выполнения сканирования выборки. Если фильтрация осуществляется по неиндексированным реквизитам, операция может вызывать заметные задержки.
  2. Места вызова: Не размещайте процедуры подсчета количества в часто вызываемых событиях интерфейса, таких как ПриАктивизацииСтроки или ПриИзмененииВыделения. Оптимально вычислять значение по отдельной кнопке пользователя или при непосредственном изменении параметров отбора.
← На главную