В разработке на платформе 1С:Предприятие 8.3 динамический список является одним из самых часто используемых элементов интерфейса. Однако разработчики часто сталкиваются с классической проблемой: как отобразить пользователю общее количество строк в этом списке? Динамический список по своей природе работает порционно, подгружая данные по мере прокрутки, и «не знает» общего количества записей, удовлетворяющих условиям, пока не просканирует всю выборку. Разберем детально, как решить эту задачу максимально эффективно.
Прежде чем переходить к коду, проанализируем ситуацию. Динамический список оптимизирован для работы с огромными массивами данных. Если в таблице миллионы записей, выполнение запроса COUNT(*) при каждом открытии формы или изменении отбора может существенно замедлить работу системы. Платформа намеренно ограничивает доступ к общему количеству, чтобы избежать «фризов» интерфейса. Тем не менее, если бизнес-логика требует вывода этой цифры, нам придется реализовать механизм подсчета самостоятельно.
Наиболее правильным и современным способом является получение текущих настроек списка, которые применил пользователь (включая поиск и встроенные фильтры), и выполнение на их основе отдельного запроса. Начиная с версии платформы 8.3.6, у таблицы формы, связанной с динамическим списком, появились мощные методы для решения этой задачи.
Рассмотрим пошаговый алгоритм реализации этого метода:
Разберем пример кода, который выполняет эти действия:
&НаСервере
Функция ПолучитьКоличествоЭлементовСписка() Экспорт
// Получаем схему и настройки динамического списка
Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
// Создаем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
// Выполняем запрос с помощью процессора компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Мы можем выгрузить результат в таблицу или просто посчитать количество
// Но эффективнее изменить сам текст запроса в схеме на COUNT(*)
// Для простоты примера посчитаем количество строк в выгрузке (подходит для небольших выборок)
ДанныеРезультата = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДанныеРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Возврат ДанныеРезультата.Количество();
КонецФункции
Важный нюанс: метод ПолучитьИсполняемыеНастройкиКомпоновкиДанных() уникален тем, что он «видит» строку поиска, введенную пользователем в стандартное поле поиска 1С, в то время как обычный КомпоновщикНастроек списка может содержать только пустые отборы.
Если предполагается, что список может содержать сотни тысяч или миллионы записей, выполнение вышеуказанного кода в основном потоке приведет к тому, что форма будет «зависать» при каждом изменении поиска. В таком случае проанализируем использование фоновых заданий.
Схема работы будет следующей:
ВЫБРАТЬ КОЛИЧЕСТВО(*) с учетом переданных настроек.Выясним причину, по которой многие разработчики заходят в тупик: у динамического списка нет события ПослеИзмененияОтбора. Рассмотрим, какие обработчики можно задействовать для обновления цифры количества:
ПодключитьОбработчикОжидания. Мы можем раз в 2-3 секунды проверять, не изменились ли настройки компоновки данных (сравнивая их с предыдущим сохраненным состоянием), и если изменились — запускать пересчет.Проанализируем ситуацию с полнотекстовым поиском. Если пользователь использует поиск по части слова во всех колонках, стандартные методы СКД могут работать не всегда корректно или возвращать неполные данные, так как полнотекстовый поиск — это отдельный механизм движка 1С. В таких случаях рекомендуется использовать методы ПолучитьИсполняемуюСхемуКомпоновкиДанных() именно версии 8.3.10 и выше, так как в них была значительно улучшена поддержка трансляции поиска в запросы.
Хорошим тоном в разработке считается использование пороговых значений. Вместо того чтобы заставлять сервер считать 5 432 211 записей, можно ограничить запрос:
// В тексте запроса для подсчета
ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ 1001 ..."
Если запрос вернул 1001 запись, мы выводим пользователю надпись "Более 1000". Это стандартный паттерн проектирования интерфейсов (как в поиске Google или крупных интернет-магазинах), который экономит ресурсы сервера и дает пользователю достаточное представление о масштабе данных.
Мы разобрали, что «приготовить» количество элементов в динамическом списке можно несколькими способами. Выбор зависит от объема данных и требований к отзывчивости интерфейса. Для небольших справочников идеально подходит использование ПолучитьИсполняемыеНастройкиКомпоновкиДанных в связке с простым запросом. Для высоконагруженных систем предпочтительнее асинхронный подсчет через фоновые задания или использование пороговых ограничений.