При разработке интерфейсов форм списков справочников или документов часто возникает задача отобразить общее количество элементов, удовлетворяющих установленным фильтрам. В отличие от обычной таблицы значений, у объекта ДинамическийСписок в управляемых формах отсутствует прямое свойство или метод Количество(). Это связано с тем, что динамический список загружает данные порциями (страницами) по мере прокрутки списка пользователем.
Разберем подробнее, какими способами можно программно вычислить точное количество записей с учетом всех примененных пользователем отборов как для управляемых, так и для обычных форм платформы «1С:Предприятие 8.3».
Начиная с платформы 8.3, в управляемых формах для элементов, связанных с динамическими списками, доступны специализированные методы: ПолучитьИсполняемуюСхемуКомпоновкиДанных() и ПолучитьИсполняемыеНастройкиКомпоновкиДанных(). Эти методы формируют готовую схему и настройки СКД, куда уже включены системные отборы, пользовательские настройки, поиск по строке и режим отображения иерархии.
Рассмотрим алгоритм действий по шагам:
Посмотрим на пример реализации серверной функции:
&НаСервере
Функция ПолучитьКоличествоСтрокСпискаНаСервере()
// Получаем схему и настройки непосредственно из элемента динамического списка на форме
СхемаКД = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
НастройкиКД = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКД, НастройкиКД,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ТаблицаРезультата = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Возврат ТаблицаРезультата.Количество();
КонецФункции
Важное преимущество данного подхода: при формировании запроса через компоновщик схемы динамического списка корректно учитываются не только пользовательские фильтры, но и ограничения прав доступа на уровне записей (RLS).
В обычных формах объект СправочникСписок или таблица значений с отбором строк позволяет передать наложенные фильтры в ПостроительОтчета или ПостроительЗапроса. Проанализируем пример переноса элементов отбора в построитель для получения итоговой выборки:
// Пример переноса отбора строк таблицы или списка в ПостроительОтчета
ТекОтбор = ЭлементыФормы.ТаблицаЗначенийНужная.ОтборСтрок;
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаЗначенийНужная);
Для Каждого ЭлементОтбора Из ТекОтбор Цикл
Если ЭлементОтбора.Использование Тогда
НовыйЭлемент = Построитель.Отбор.Добавить(ЭлементОтбора.ПутьКДанным, ЭлементОтбора.Имя, ЭлементОтбора.Представление);
НовыйЭлемент.ВидСравнения = ЭлементОтбора.ВидСравнения;
НовыйЭлемент.Значение = ЭлементОтбора.Значение;
НовыйЭлемент.ЗначениеС = ЭлементОтбора.ЗначениеС;
НовыйЭлемент.ЗначениеПо = ЭлементОтбора.ЗначениеПо;
НовыйЭлемент.Использование = Истина;
КонецЕсли;
КонецЦикла;
РезультатЗапроса = Построитель.Результат;
Выборка = РезультатЗапроса.Выбрать();
КоличествоСтрок = РезультатЗапроса.Выгрузить().Количество();
Если структура фильтров фиксирована или известна заранее, наиболее производительным решением будет выполнение прямого запроса к таблице базы данных с использованием агрегатной функции КОЛИЧЕСТВО(*). Это исключает передачу больших массивов строк по сети и расчет выполняется на стороне СУБД:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(СправочникТаблица.Ссылка) КАК ВсегоСтрок
|ИЗ
| Справочник.Номенклатура КАК СправочникТаблица
|ГДЕ
| НЕ СправочникТаблица.ПометкаУдаления
| И СправочникТаблица.ВидНоменклатуры = &ВидНоменклатуры";
Запрос.УстановитьПараметр("ВидНоменклатуры", ВыбранныйВид);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
ВсегоЭлементов = Выборка.ВсегоСтрок;
КонецЕсли;
При реализации подсчета количества строк обратим внимание на ключевые технические нюансы:
ПриАктивизацииСтроки или ПриИзмененииВыделения. Оптимально вычислять значение по отдельной кнопке пользователя или при непосредственном изменении параметров отбора.