Сортируем ДанныеФормыДерево на клиенте

Публикация № 1078137

Программирование - Практика программирования

УФ Сортировка Дерево ДанныеФормыДерево

33
Иногда так хочется, но нечем...

 

У ДанныеФормыКоллекция для сортировки есть специальный метод Сортировать(). Он доступен на клиенте и, хоть и делает вызов сервера, но, по понятным причинам, срабатывает крайне быстро.

 

А вот ДанныеФормыДерево платформа обделила такой возможностью. Вместо этого программисты обычно переходят «на сервер», преобразуют ДанныеФормыДерево в полноценное ДеревоЗначений, сортируют и преобразуют обратно.

 

ДеревоЗначений    = ДанныеФормыВЗначение(ДанныеФормыДерево, Тип("ДеревоЗначений")); 
ДеревоЗначений.Строки.Сортировать("КолонкиСортировки", Истина); 
ЗначениеВДанныеФормы(ДанныеФормыДерево, ДеревоЗначений);

 

А ведь существуют ситуации, когда перебрасывать данные всей формы «на сервер» значительно затратнее, чем, оставаясь «на клиенте», отсортировать десяток строчек.

 

Для реализации Менеджер открытых форм опробовал разные алгоритмы сортировки ДанныеФормыДерево, доступные на клиенте. В результате, остановился на этом, что помогло ускорить открытие формы обработки в 2,5 раза.

 

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

 

 

P.S.: Есть альтернативные варианты процедуры? Выкладывайте в комментариях. Если наберётся достаточное количество интересных методов, то после можем провести нагрузочное тестирование, выложить результаты сравнения и выбрать процедуру-победитель.

 

 

 

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыДерево(КоллекцияСортировки, КолонкаСортировки, ВключатьПодчиненные = Ложь)
 
        КоллекцияСтрок  = КоллекцияСортировки.ПолучитьЭлементы();
 
        СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки);
 
        Если ВключатьПодчиненные Тогда
                Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
                        СортироватьДанныеФормыДерево(ТекущаяСтрока, КолонкаСортировки, ВключатьПодчиненные);
                КонецЦикла;
        КонецЕсли;
 
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки)
 
        ПараметрыЗначений               = Новый Соответствие;
        СортированныеЗначения   = Новый СписокЗначений;
 
        Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
 
                ТекущееЗначение = ТекущаяСтрока[КолонкаСортировки];
 
                ПараметрыЗначения       = ПараметрыЗначений.Получить(ТекущееЗначение);
                Если ПараметрыЗначения = Неопределено Тогда
                        ПараметрыЗначения       = Новый Массив;
                        ПараметрыЗначений.Вставить(ТекущееЗначение, ПараметрыЗначения);
                        СортированныеЗначения.Добавить(ТекущееЗначение);
                КонецЕсли;
 
                ПараметрыЗначения.Добавить(ТекущаяСтрока);
 
        КонецЦикла;
 
        СортированныеЗначения.СортироватьПоЗначению(НаправлениеСортировки.Возр);
 
 
        НовыйИндекс     = 0;
        Для Каждого ТекущееЗначение Из СортированныеЗначения Цикл
 
                МассивСтрок     = ПараметрыЗначений.Получить(ТекущееЗначение.Значение);
                Для Каждого ТекущаяСтрока Из МассивСтрок Цикл
 
                        ТекущийИндекс   = КоллекцияСтрок.Индекс(ТекущаяСтрока);
                        ШагСдвига               = НовыйИндекс - ТекущийИндекс;
                        Если НЕ ШагСдвига = 0 Тогда
                                КоллекцияСтрок.Сдвинуть(ТекущийИндекс, ШагСдвига);
                        КонецЕсли;
 
                        НовыйИндекс     = НовыйИндекс + 1;
 
                КонецЦикла;
 
        КонецЦикла;
 
КонецПроцедуры



 

 

33

См. также

Специальные предложения

Вознаграждение за ответ
Показать полностью
Комментарии
Избранное Подписка Сортировка: Древо
1. alex15650 134 18.06.19 10:57 Сейчас в теме
ДанныеФормыДерево вообще обделили, и поиск тоже хочется..
2. SeiOkami 1013 18.06.19 10:58 Сейчас в теме
(1) хорошая идея, добавлю в заметки
3. karpik666 2497 18.06.19 11:00 Сейчас в теме
На каком количестве элементов проверялась сортировка? 1С при этом не формирует неявных серверных вызовов?
4. SeiOkami 1013 18.06.19 11:25 Сейчас в теме
(3) боялись серверных вызовов, ибо используется метод Сдвинуть(), но не обнаружили ни по счётчику вызовов, ни по замеру производительности.

Проверяли так - генерили примитивную таблицу формы из рандомных чисел, а потом сортировали. Перебирали разные алгоритмы. Этим добились того, что 1000 элементов таблицы с рандомными числами диапазоном до 1000 сортируются меньше секунды. 10 000 строк с рандомом до 10 000 тратит время на сортировку ≈ 3 секунды.

Этой скорости нам достаточно для реализации механизма, где не будет больших объемов строк. Если же дерево более большое, то тут есть много факторов. Скорость клиентской машины, объём других данных на форме (помимо дерева) и так далее.

+ заметили в некоторых ситуациях такую вещь, что перепрыгивание на сервер иногда занимает совершенно неразумное время. Доходило до абсурдного, что для редактирования таблицы данных на сервере, приходилось использовать бесконтекстный вызов сервера, а передавать туда массив со структурами, обрабатывать там в ТЗ, корректировать,обратно превращать в массив со структурами, возвращать как результат функции, а далее уже на клиенте содержимое помещать в таблицу формы. Костыль редкостный, но увеличивал скорость работы в несколько раз.

Попробуем проанализировать ситуацию, если что-то интересное - будет статья.
5. karpik666 2497 18.06.19 11:28 Сейчас в теме
(4) то есть использовались только числа? Попробуйте такое же количество, но ссылочных элементов, очень интересно как отработает Обработка представления для этих элементов без серверных вызовов, и кэширует ли 1С все представления на клиенте для такого количества элементов
7. SeiOkami 1013 18.06.19 11:36 Сейчас в теме
(5)
Да, скорее всего не так классно будет.

Просто в разработке сортировок по ссылке стараемся максимально избегать. Даже уже привык сортировать по примитивным типам, которые заранее готовятся специально.

Однако, в данном алгоритме именно сортировка используется только один раз на уровень дерева - СортироватьПоЗначению(). Метод платформенный, никаких "ручных" сравнений нет. Но потестировать нужно, интересно
8. karpik666 2497 18.06.19 11:42 Сейчас в теме
(7) это понятно, но ваш пример далек от реальности, так как вы используйте примитивные типы, то неявных серверных вызовов и не будет, но мне больше кажется, что такой вариант будет все равно вызывать метод сервера. Сам ранее пытался писать код, который максимально бы работал на клиенте, но все старания разбивались о работу самой 1С, которая фоном делала серверные вызовы для кода. которая в теории должен был исполняться только на клиенте.
9. SeiOkami 1013 18.06.19 11:47 Сейчас в теме
(8) пока что в этом алгоритме не замечено было, но Вы правы - нужно проверить на ссылочных типах.
11. SeiOkami 1013 18.06.19 12:12 Сейчас в теме
(9)
(8)
Проверил на ссылке. Добавил ссылочную колонку в таблицу формы. Заполнил таблицу ссылками на существующие документы (выбрал первые 10 000 документов и разбросал рандомно по таблице). Сортировка заняла 4 секунды и счётчик вызовов не показал.

Скорее всего СписокЗначений.СортироватьПоЗначению() использует ГУИДы, а не представления, поэтому обращений на сервер и не требовалось
Alogy; karpik666; +2 Ответить
13. karpik666 2497 18.06.19 12:18 Сейчас в теме
(11) проблема не в самом методе сортировки, а в выводе дерева на экран, так как в ссылочном поле происходит северная обработка представления, потому и было интересно как поведет себя 1с. Спасибо, будет желание еще сам проверю работу этого метода
6. karpik666 2497 18.06.19 11:30 Сейчас в теме
(4) при личной проверке довольно часто выходит, что безконтекстная передача таблицы формы может быть дольше, чем контекстный серверный вызов, все зависит от того, какой объем информации содержится в остальных элементах, если по сравнениню с таблицей их пренебрежительно мало, то лучше контекстный вызов.
10. Evg-Lylyk 2574 18.06.19 12:12 Сейчас в теме
(0) Сталкивался с подобной проблемой, чуток анализировал вопрос понял что для большого количества строк на сервере быстрее
Описанный вариант кажется не оптимальным создает массив сдвигает, быструю сортировку пробовали?
12. SeiOkami 1013 18.06.19 12:16 Сейчас в теме
(10) пробовали с десяток разных алгоритмов, уже и не вспомню. Но остановились на этом. И заполнение списка значений здесь привело хороший прирост. Этот объект быстро сортирует.

Если у вас есть процедура быстрее, то выкладывайте. Хочется найти "самую-самую" и закрепить в статье.

Когда появится время, сделаю специальный инструмент для удобного тестирования методов сортировки. Чтобы можно было свою процедуру легко вставить и гонять по скорости
14. Infector 130 18.06.19 15:19 Сейчас в теме
Есть стандартные команды сортировки для элементов форм. Чаще всего проще обратить на них внимание пользователей и как-то закрепить на командных панелях. Если же сортировать нужно, но без участия пользователей скорее всего этот объект использован не в тему.
15. starik-2005 1864 20.06.19 12:30 Сейчас в теме
А не пробовали сортировать "нативно"? Тем же квиксортом?
16. AlexBober78 21.06.19 18:46 Сейчас в теме
Что-то не выкладывают альтернативные варианты)
Вообще, какой-нибудь конкурс устроить. Пусть и символический.
И обработку общую сделать. Для теста с генерацией данных.
Оставьте свое сообщение