Подсчет количества элементов в списке иерархического справочника, при изменении отбора

07.10.15

База данных - Статистика базы данных

Допустим, у вас появилась хотелка: знать точное количество элементов справочника в группах (папках).
С чего начать? Конечно, запрос, но не простой! Будем использовать построитель запроса и, мало того, с ним будет использоваться динамический отбор!

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Решение
.txt 4,71Kb
4
4 Скачать (1 SM) Купить за 1 850 руб.

Что было:

А. База на платформе 8.3.5.1248 обычные формы.

Б. В базе список справочника "Номенклатура" иерархический.

Что нужно:

Подсчет количества элементов в списке справочника "Номенклатура", при изменении отбора.

Решение:

Для решения нам понадобится:

1. В список справочника "Номенклатура" добавить колонку "КоличествоЭлементов" (вы можете назвать её как вам нужно, но не забудьте потом изменить код).

2. Для элемента формы "Список" определить процедуру:

 

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

3. Осталось посчитать в функции количество самих элементов:

 

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

    КоличествоЭлементов = Выборка.Количество();      
    
    Возврат КоличествоЭлементов;
    
КонецФункции

Результат:

Код написали. Отбор работает. Результат производительности при открытии одно из папок: 0,360265.

Казалось бы, отлично, задача решена! Но это решение можно оптимизировать!

И сейчас я покажу, как улучшить результат в разы!

 

Решение2:

1. Без изменений.

2. Допишем условие, чтобы код работал только тогда, когда колонка "КоличествоЭлементоввидима:

 

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

3. Оптимизируем запрос, уменьшив количество обращений к базе (обратите внимание на условие в запросе и путь к данным для отбора):

 

Функция ПолучитьКоличествоЭлементов(ГруппаНоменклатуры)      
    
    КоличествоЭлементов = 0;
    
    Построитель = Новый ПостроительЗапроса;
    Построитель.Текст = "ВЫБРАТЬ
                        |    КОЛИЧЕСТВО(*) КАК Количество
                        |ИЗ
                        |    Справочник.Номенклатура КАК Номенклатура
                        |ГДЕ
                        |    Номенклатура.ЭтоГруппа = ЛОЖЬ
                        |    И Номенклатура.Родитель = &ГруппаНоменклатуры
                        |{ГДЕ
                        |    Номенклатура.Ссылка.*}";     
    Построитель.Параметры.Вставить("ГруппаНоменклатуры",ГруппаНоменклатуры);
    Построитель.ЗаполнитьНастройки();    
    
    //Установка отбора в построителе
    Для Каждого ЭлементОтбора Из Список.Отбор Цикл         
        Если ЭлементОтбора.Использование Тогда              
            Если Построитель.Отбор.Найти(ЭлементОтбора.ПутьКДанным) = Неопределено Тогда                 
                ЭлементОтбораВПостроителе               = Построитель.Отбор.Добавить("Ссылка." + ЭлементОтбора.ПутьКДанным);
                ЭлементОтбораВПостроителе.ВидСравнения  = ЭлементОтбора.ВидСравнения;
                ЭлементОтбораВПостроителе.Значение      = ЭлементОтбора.Значение;
                ЭлементОтбораВПостроителе.ЗначениеС     = ЭлементОтбора.ЗначениеС; 
                ЭлементОтбораВПостроителе.ЗначениеПо    = ЭлементОтбора.ЗначениеПо;
                ЭлементОтбораВПостроителе.Использование = Истина;                
            КонецЕсли                   
        КонецЕсли;          
    КонецЦикла;     
    
    //Получение результатов
    Построитель.Выполнить();
    
    Выборка = Построитель.Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        КоличествоЭлементов  = Выборка.Количество;    
    КонецЦикла;
    
    Возврат КоличествоЭлементов;
    
КонецФункции

 

Результат2:

Теперь наш код стал оптимальнее. Отбор работает, как и должен. А вот результат производительности: 0,113300.

Нам удалось улучшить результат в разы, и это отлично! 

Задача решена на 100%!

Благодарности:

Исходный код был подсмотрен тут. В оптимизации решения помог Молодов Алексей!

Добавил текстовый файл с кодом двух решений! Всем удачи!

Практика программирования Задача

См. также

Статистика базы данных Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка позволяет посмотреть количество данных в системе по каждому объекту (количество документов, справочников, и т.д.). Информация также дополняется данными из журнала регистрации по дате последнего изменения.

1 стартмани

19.12.2024    349    5    smirnov0ser    0    

4

Статистика базы данных Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ количества записей регистров/документов/справочников, в том числе в динамике.

13.11.2024    821    88    evgeni-red    2    

7

Статистика базы данных Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

«Навигатор метаданных» поможет изучать структуру данных конфигурации, переходить по связям между объектами конфигурации.Для аналитиков и разработчиков.

1 стартмани

11.09.2024    1288    17    m_kislyak    3    

9

Статистика базы данных Программист Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Абонемент ($m)

Сбор статистики информационной базы в виде отчета - наименование конфигурации, версия, количество записей документов, регистров сведений, справочников, обменов.

1 стартмани

10.09.2024    3590    46    pahno    8    

7

Статистика базы данных Программист Платформа 1С v8.3 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Данная обработка - алгоритм предлагает оценку вашей базы на количество тех или иных типов документов с их реквизитами.

6 стартмани

12.08.2024    873    0    aximo    2    

3

Статистика базы данных Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Объединен, унифицирован и значительно улучшен функционал двух исходных обработок для контроля размеров таблиц хранения 1С в серверных базах: https://infostart.ru/1c/tools/128362/ (для MS SQL) и https://infostart.ru/1c/tools/978816/ (для PG SQL).

1 стартмани

16.05.2024    1952    49    yuraos    4    

12

Статистика базы данных Инструментарий разработчика Тестирование QA Программист Платформа 1С v8.3 1С:Управление торговлей 10 1С:Управление производственным предприятием Абонемент ($m)

Внешняя обработка "Анализ документов и регистров" - можно использовать для детального изучения документов базы, связанных регистров (накопления и сведений). Предварительный анализ документов обычно требуется перед проведением свертки остатков базы, перед обновлением типовых релизов сильно измененной конфигурации, перед переходом на новую программу.

1 стартмани

29.12.2023    2335    14    RustIG    5    

9
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Serj1C 483 08.10.15 12:26 Сейчас в теме
> Казалось бы, отлично, задача решена! Но это решение можно оптимизировать!
Запрос в цикле - это ужасно.
Необходимо собрать все видимые группы, выполнить один запрос по этим группам и потом заполнять колонку.
2. Xershi 1557 08.10.15 13:29 Сейчас в теме
(1) Serj1C, поделитесь, как вы этот список будете получать?
3. gubanoff 63 06.11.15 14:32 Сейчас в теме
(2) заполняете массив, перебрав все строки в событии ПриПолученииДанных в цикле
Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
. Потом этот массив передаете в функцию для подсчета. Потом еще раз проходите в цикле
Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
и выводите значения. Сам запрос и его текст закешируйте в переменную и инициализируйте один раз при открытии. Построитель запроса тоже не надо, он потяжелее будет, чем просто запрос. Плюс все это дело можно делать, только если пользователь установил видимость колонки, т.к. это может быть не всем нужно. Не благодарите.
4. Xershi 1557 06.11.15 14:39 Сейчас в теме
(3) gubanoff, да уже давно подметил что "ОформленияСтрок" это обычная коллекция, которая и содержит нужный список.
Построитель запроса не просто так использовался, так что тут только ускорение получится на массиве. Видимость колонки и так в условии стоит, это вы похоже тоже пропустили.
Может сделаю 2 вариант уже с массивом. Правда пока вопрос не очень актуален.
5. Xershi 1557 02.12.15 10:20 Сейчас в теме
(3) gubanoff, провел исследование http://forum.infostart.ru/forum86/topic142222/. Результат поразил запрос не оптимален! И 43 (оптимальных) запроса выполняются быстрее 3(не оптимальных) при прочих равных условиях!
Оставьте свое сообщение