gifts2017

Методика оптимизированного полного разворачивания и сворачивания динамических списков форм иерархических справочников отображаемых в виде дерева (управляемый интерфейс)

Опубликовал Михаил Шумский (iRounder) в раздел Программирование - Практика программирования

Не секрет, что в большинстве случаев пользователю намного удобнее использовать отображение списка иерархического справочника в виде дерева. Все бы ничего, да на полное разворачивание объемного справочника стандартными средствами 1С может уйти до нескольких минут. Моя методика позволит разворачивать и сворачивать подобные справочники в десятки раз быстрее.

Эффективность методики зависит от структуры справочника и количества записей в нем. Понятное дело - что если справочник мал, и при установке в палитре свойств таблицы формы свойства НачальноеОтображениеДерева в РаскрыватьВсеУровни он открывается за секунду, то тут эффект не будет заметен. Однако все изменяется с ростом количества элементов. Ниже приведены результаты тестирования. Помимо полного разворачивания разработана и процедура для полного сворачивания.

Для тестирования старался выбирать разноплановые справочники (разные по типу иерархии, количеству элементов и групп / родителей)

Легенда:

1 колонка - наименование справочника

2 колонка - количество элементов

3 колонка - количество групп / родителей

4 колонка - время на раскрытие методом установки в палитре свойств таблицы формы свойства НачальноеОтображениеДерева в РаскрыватьВсеУровни

5 колонка - время на раскрытие с помощью моей методики

Для клиент-серверной версии:

Справочник Элементов Групп/родителей Стандартно С оптимиз.
Контрагенты 7809 6 27 с 0,6 с
Банки 17465 78 52 с  5 с
Статьи движения ДС 124 32 3 с 2,1 с
Подразделения организаций 73 17 4 с 1,5 с

 

Повторные разворачивания всего дерева в течение сеанса работы происходит за доли секунды (если вы не закрывали окно справочника).

 

Суть оптимизации состоит в нахождении КЛЮЧЕВЫХ узлов, раскрытия которых абсолютно достаточно для полного раскрытия всего дерева. А исходя из того, что стандартным механизмом 1С раскрываются полностью все узлы, в т.ч. и подчиненные элементы, то выигрыш в количестве обращений к серверу, а соответсвенно и во времени разворачивания дерева очень существенный (особенно заметно на больших справочниках).

Скачать файлы

Наименование Файл Версия Размер
Методика (корректировка). Код и описание методики в модуле объекта обработки. 77
.epf 5,29Kb
11.10.12
77
.epf 5,29Kb Скачать

См. также

Вознаграждение за ответ
Сумма: 0 $m
Добавили:
Александр Чепелевич (ChAlex) (0.30 $m)
Подписаться Добавить вознаграждение
Комментарии
1. Евгений Ефремов (evgefremov) 08.10.12 21:47
плюсую конечно, а так хотелось бы текст методики видеть в самой статье а не скачивать отдельный файл..
2. Александр Романов (alexandr1972_1) 08.10.12 21:52
Не охота скачивать файл. Хотя бы начало в статье выложите.
3. Михаил Шумский (iRounder) 09.10.12 09:13
Коллеги - поймите - я не из жадности хочу, чтобы скачивали файл. Эту $m потом девать в общем-то и некуда. Но это дает толчок к развитию как инфостарта - так и его пользователей. Например, с чего все началось у меня? Мне очень понадобилась конкретная обработка с инфостарта. В итоге пришлось кое-какие свои наработки достать из закромов и оформить публикации, чтобы их скачали, а у меня появились $m на то, чтобы скачать целевую публикацию. В итоге оформил уже 3 публикации - и думаю хорошо ими помог нескольким десяткам пользователей инфостарта.
4. Михаил Шумский (iRounder) 09.10.12 09:15
Ну, и еще просьба. Если кто скачал и использовал методику - то было бы очень хорошо, если бы в комментах написали какой выигрыш во времени раскрытия дерева получили (или не получили). Возможно большая выборка результатов даст повод попробовать еще больше оптимизировать процесс. Хотя на первый взгляд дальше уже некуда.
5. Алексей Роза (DoctorRoza) 09.10.12 17:12
6. Андрей Казанцев (ander_) 10.10.12 08:48
(3) iRounder,
Полное отсутствие информации о методах решения задачи дает обратный эффект. Не заинтересовывает.
Хотя бы в общих чертах и сжато но описание подхода нужно.
Иначе давайте все статьи будем назвать "Кто-то сделал что-то" и прикреплять файлы. Пусть инфостарт развивается!
automax24; vital1c; Petr0v1ch; gaglo; +4 Ответить 2
7. Михаил Шумский (iRounder) 10.10.12 09:15
(6) Даже не знаю что и ответить. Подождем для начала комментариев от тех, кто воспользовался методикой. О достигнутом эффекте.
8. Борис Скворцов (gaglo) 10.10.12 09:30
Присоединяюсь к (6). В таком виде публикация выглядит как реклама от перхоти. Поделитесь хотя бы оценкой трудоемкости прививки данной методики к готовым конфигурациям. Ну что-то вроде "добавить три процедуры в общий модуль и внести их вызовы в 2315 мест в формах справочников". Суть самой методики, так и быть, не раскрывайте.
9. mxm2 mxm2 (mxm2) 10.10.12 10:03
... рискну выразится несколько резко... однако даже после скачивания файла - не совсем понятен принцип действия, тем более, что чтобы опробовать методику требуется некая доработка Вашей обработки. Если уж Вы не предоставили описание методики, выложите хотя-бы готовую обработку, которую можно было бы запустить в конфигурации без её изменения (выпустите некий "окончательный продукт", не требующий "допиливания"), понимаю, что на это потребуется чуть больше времени, но все же попробуйте, и, возможно повысите свой статус, до уровня "когда $m уже не важны" ))). Неплохо бы в общих словах и описать принцип действия.
10. Михаил Шумский (iRounder) 10.10.12 10:24
(9) Принимаю любую критику - так что не проблема
Для начала поясню - это не обработка, а процедуры и функции + пояснения по их внедрению в вашу конфигурацию. Просто для удобства и скажем так ради "боевой раскраски" они упакованы не в текстовый файл, а в общий модуль обработки.
И невозможно сделать готовую обработку (дело не во времени). В любом случае придется вносить изменения в конфигурацию. Хотя бы создать кнопки Свернуть и Развернуть...

Ну а это выдержка из текста модуля обработки:

//Создаем в любом общем модуле с установленным свойством Клиент(Управляемое приложение)
//(остальные свойства в Ложь) либо создаем свой общий модуль с описанными выше свойствами.
//В моем случае это общий модуль РазворачиваниеСворачиваниеДереваКлиент.
//В нем создаем экспортную процедуру:

Далее текст самой процедуры

//Создаем в любом общем модуле с установленным свойством Сервер
//(остальные свойства в Ложь) либо создаем свой общий модуль с описанными выше свойствами.
//В моем случае это общий модуль РазворачиваниеСворачиваниеДереваСервер.
//В нем создаем экспортную функцию:

Далее текст самой функции

//Далее в модуле управляемой формы списка целевого справочника создаем 2 процедуры и 2 функции:

Далее тексты процедур и функций

//Готово. Теперь в палитре свойств списка справочника устанавливаем Отображение = Дерево,
//НачальноеОтображениеДерева = НеРаскрывать.
//А далее по желанию либо в каком-нибудь событии формы вызывать РазвернутьВсе() или СвернутьВсе()
//либо (как это реализовано у меня) создать две соответствующие команды, разместить их
//в командной панели формы, а в их обработчиках вызывать соответствующие процедуры (РазвернутьВсе() или СвернутьВсе()).

Вот интересно - что здесь непонятно?
Ну, и заодно очевидна и "трудоемкость прививки к готовым конфигурациям" для (8).

А $m мне действительно не важны, сколько их уже есть - мне столько обработок не понадобится - факт.
Количество скачиваний файла мне пусть и субъективно но показывает количество человек кому необходима такая методика. А возможно, с некоторой скидкой, и кому в итоге помогла. Т.е. если я вижу ее не бесполезность, то тогда есть желание дальше работать в этом направлении - в том смысле, что разрабатывать нечто, что может быть полезным другим.
11. mxm2 mxm2 (mxm2) 10.10.12 11:08
(10) iRounder, Видимо я совсем не в теме... "Невозможно создать обработку" отображения списка справочника? в которой Ваши экспортные процедуры внесены в модуль объекта. Про количество заитересованных можно судить по количеству просмотров, про успешность темы по +/-
12. Михаил Шумский (iRounder) 10.10.12 11:15
(11) Каким образом для пользователя подмените стандартную форму списка на свою обработку не внося правки в конфигурацию?

Но суть даже не в этом - я нигде и не писал, что это готовая обработка. Я обозначал, что это методика. И в (10) я объяснил причину ее "упаковки" в обработку. Методика готовая к использованию. Все функции и процедуры написаны, их нужно только внедрить в свою конфигурацию.
13. mxm2 mxm2 (mxm2) 10.10.12 11:30
(12) iRounder, если "въеду" в Вашу методику, напишу такую обработку. Методика работает только в "стандартной форме списка"? По крайней мере в пределах обычных форм на форму внешней обработки можно "положить" Форму списка любого справочника.
14. Михаил Шумский (iRounder) 10.10.12 12:43
(13) Методика работает в любой форме с динамическим списком отображаемым в виде дерева. В пределах обычных форм (если Вы под обычными имеете в виду не управляемые) смысла в этой методике нет абсолютно.
И понятное дело, что в управляемых формах можно в форму обработки "положить" список любого справочника. Только как Вы будете подменять стандартную форму справочника на Вашу из обработки не влезая в конфигуратор (если у Вас конфигурация на полной поддержке)?
15. Михаил Шумский (iRounder) 10.10.12 12:49
Неверно выразился в прошлом сообщении - смысла в этой методике нет в режиме обычного приложения, она исключительно для работы в режиме управляемого приложения.
16. mxm2 mxm2 (mxm2) 10.10.12 13:15
(14) iRounder, в большинстве случаев интересно применение ускорения именно в нестандартных формах справочников, как-то например, подбор номенклатуры в УТ11 (Управляемые формы). В УТ11 "подбор в документ продажи" реализован обработкой. Я имел ввиду, что для иллюстрации выигрыша можно сделать внешнюю обработку, скажем по одному и тому-же справочнику, стандартным способом, и Вашим, возможно в одной форме по типу "Norton Commander"
17. Михаил Шумский (iRounder) 10.10.12 13:23
18. Михаил Шумский (iRounder) 10.10.12 13:24
Если что-то нужно пояснить - я готов.
19. Михаил Шумский (iRounder) 10.10.12 13:26
Ну и еще - стандартного метода раскрыть все дерева после того как форма создана и выведена на экран - нет. Во всяком случае я его не знаю. Поэтому только выставлять свойство списка НачальноеОтображение = РаскрыватьВсеУровни.
20. Михаил Шумский (iRounder) 10.10.12 13:26
21. Александр Чепелевич (ChAlex) 10.10.12 14:43
Ну вот писал, писал - все куда-то ушло в корзину. Поэтому повторю. Если вдруг появится предыдущий труд - извиняйте.

Итак попробовал данный вариант. Сначала цифры: Справочник "Материалы" - количество записей 40 093 из них 379 папок. Время разворачивания списка: 1-е 50 сек., последующие 8 сек. Время сворачивания: 4 сек. Время разворачивания справочника при открытии в режиме "Разворачивать все уровни" 4 мин. 50 сек.

Теперь по методике: ничего нового или оптимизирующего в ней нет. Единственное что для себя открыл (до этого не пробовал писать не в соответствии с документаций) так это то, что в метод Развернуть(Строка,СПодчиненными) и Свернуть(Строка) можно передать в параметр "Строка" - ссылку а не идентификатор строки, как это написано в документации:
ТаблицаФормы (FormTable)
Развернуть (Expand)
Синтаксис:

Развернуть(<ИдентификаторСтроки>, <СПодчиненными>)
Параметры:

<ИдентификаторСтроки> (обязательный)

Тип: Произвольный.
Идентификатор строки таблицы.
<СПодчиненными> (необязательный)

Считаю это недоработкой документации.

Разжую для тех кто не сразу въезжает в тонкости данной темы:

По данной методики можно только организовать полное сворачивания и разворачивания веток дерева для динамического списка (в принципе можно модифицировать для разворачивания до определенного уровня). Все делается стандартными методами объекта "ТаблицаФормы": Развернуть() и Свернуть().
С вышесказанными замечаниями относительно параметров этих методов никаких сложностей с реализацией данных действий не возникает. Для динамических списков не возможно получить строку(и) из формы, которые нужно свернуть или развернуть, как например, для дерева( методом ДанныеФормыДерево.ПолучитьЭлементы()) - и потом уж получить по этим элементам идентификатор строки, который следовало бы передавать в качестве строки в метод Развернуть(). Оказывается вместо этого можно просто передать ссылки справочника. В этом и суть всех действий, предлагаемых автором. Все остальное стандартно. Ссылки получает запросом на сервере (кстати сам текст запроса какой-то геморный, не понял зачем так делать, но об этом позже), и потом обходя полученные ссылки разворачивается или сворачивается ветка ТаблицыФормы (списка справочника) из динамического списка методом Развернуть()/Свернуть(), где в качестве ссылки передается не идентификатор строки, а сама ссылка.

Теперь по поводу начального режима дерева: стоит устанавливать "Разворачивать только верхний уровень" - на моей базе разницы во времени с режимом "Не разворачивать" вообще никакой. Но хоть что-то отображается, вместо просто наименования справочника.

Теперь по поводу запроса: зачем там такой алгоритм - не понял. Переделал на простенький вариант:

Функция ПолучитьСписокЭлементовДерева2(ИмяСправочника, Развернуть) Экспорт
Запрос = Новый Запрос();
Запрос.Текст = "ВЫБРАТЬ
| " + ИмяСправочника + ".Ссылка
|ИЗ
| Справочник." + ИмяСправочника + " КАК " + ИмяСправочника + "
|ГДЕ
| " + ИмяСправочника + ".ЭтоГруппа"+?(Развернуть,""," И "+ИмяСправочника + ".Родитель = ЗНАЧЕНИЕ(Справочник." + ИмяСправочника + ".ПустаяСсылка)");
СписокЭлементов = Новый СписокЗначений;
СписокЭлементов.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
Возврат СписокЭлементов;
КонецФункции

Некоторое пояснение: для сворачивания нет необходимости получения всех групп, достаточно свернуть только группы на верхнем уровне.

Ну и теперь размышления по поводу производительности разворачивания(сворачивание всегда идет более менее быстро). В общем-то можно организовать 2-мя способами: разворачивать только верхний уровень с подчиненными, что делать не стоит (на моей базе в этом случае время разворачивания составляет 3 мин 50 сек - то, есть тоже самое, что режим при открытии разворачивать все уровни)! или разворачивать все ветки, следует использовать данный вариант. Разница во времени показывает качество оптимизации (вернее ее полное отсутствие) для дерева в 1С.
22. Михаил Шумский (iRounder) 10.10.12 14:59
(21)Вся фишка именно в алгоритме обработки результата запроса. Какой максимальный уровень вложенности в справочнике "Материалы"?
Ну и очень интересна разница во времени разворачивания с моим "запросом и обработкой результата" и твоим.
23. Михаил Шумский (iRounder) 10.10.12 15:04
В догонку - в первом абзаце (21) написано: "50 секунд против 4 минуты 50 секунд", в последнем абзаце: "Разница во времени показывает качество оптимизации (вернее ее полное отсутствие) для дерева в 1С."
Как-то не соотносится...
24. Михаил Шумский (iRounder) 10.10.12 15:17
В запросе (21) не учтена возможность справочника с "Иерархия элементов"
25. Михаил Шумский (iRounder) 10.10.12 15:22
В общем без дополнительных пояснений видимо действительно сложно разобраться в методике.
Вся соль там в обработке результата запроса.
Исходя из запроса в (21) всегда будет разворачиваться N узлов, где N - количество групп.
В результате моей обработки результата запроса получаем КЛЮЧЕВЫЕ узлы дерева. Т.е. достаточно развернуть лишь эти узлы (без подчиненных), чтобы увидеть полностью развернутое дерево. В зависимости от структуры справочника количество ключевых узлов может быть в десятки раз меньшим чем N, а соответственно уменьшается в столько же раз количество обращений к серверу, а вместе с ним и время разворачивания.
26. Михаил Шумский (iRounder) 10.10.12 15:45
Ну, и если еще кто-нибудь один из скачавших скажет, что не понял методики. Тогда нигде не денусь - буду давать пояснения.
27. Александр Чепелевич (ChAlex) 10.10.12 16:44
(22) - уровень вложенности не ограничен - данные введены с 5-ю уровнями вложенности (4 уровня групп, на 5-м только элементы). Естественно для разных групп вложенности разные, есть и с 1-м. Смысл переписывание запроса на в скорости, а в понятности и поддержке. На моей базе даже выигрыш в 1-2 сек для разворачивания и почти в 4 сек на сворачивание (сворачивание меньше секунды, вместо 4-х).
(23) - А что не соотносится? Все просто как грабли. Быстрее развернуть все ветки по одной самому, чем разворачивать только верхний уровень с подчиненными. Между этими двумя режимами и разница в эти 4 минуты, которые 1С тратит на то чтобы развернуть подчиненные элементы. Вот такая эффективность внутренних методов 1С.
(24) - вообще-то иерархия элементов с большим объемом и уровнями вложенности - нонсенс. Но даже и если это учитывать - не проблема - получить одним запросом и все. Совсем не догоняю зачем там в обработке какие-то поиски в списке, удаления и добавления родителей и т.п. Это лишне 100%
(25) - Не догнал совсем. Что значит "..КЛЮЧЕВЫЕ узлы дерева" и как "... развернуть лишь эти узлы (без подчиненных), чтобы увидеть полностью развернутое дерево." . Одно другому противоречит: если не развернуты все узлы, то и структура не вся видна. В чем соль и смысл?
28. Михаил Шумский (iRounder) 10.10.12 16:57
А смысл "ключевых узлов" прост: если проследить за поведением дерева (я это делал с помощью программной установки свойства ТекущаяСтрока при закрытом дереве) при открытии определенной ветви, то становится очевидным, что открыв например на 4 уровне определенный узел мне не нужно затем открывать его родителей вплоть до первого уровня (это если в двух словах). Исходя из запроса в (21) будут открываться все узлы дерева. По моему методу - только определенные.

Это легко проверить - поставь мой запрос с обработкой результата и по точке останова посмотри сколько элементов эта функция возвращает, и тоже самое сделай со своим запросом. И сравни.
А затем сравни деревья в обоих случаях - они будут одинаково полностью раскрыты.
29. Dimon (klel) 10.10.12 20:44
Большое спасибо за статью так и не понял как это работает :(
30. Александр Чепелевич (ChAlex) 10.10.12 20:54
(28) Ну тогда следует разделить требования на 2 пункта: 1 - есть потребность разворачивания всей иерархии вместе с элементами, и 2 - разворачивать только структуру подчиненности (т.е. только дерево). Вы реализовывали 2-й вариант. Мне нужнее 1-й.

Ну и по поводу все-таки запроса: Я переделал (опять же с учетом подчиненности групп, при желании можно перенести на подчиненность элементов) на более эффективный

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

Процедура Рекурсивно(Выб,М)
Выборка = Выб.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией,"Ссылка");
Пока Выборка.Следующий() Цикл
Если Выборка.ТипЗаписи()=ТипЗаписиЗапроса.ИтогПоГруппировке И (ТипЗнч(Выб)=Тип("РезультатЗапроса") ИЛИ Выборка.Ссылка<>Выб.Ссылка) Тогда
М.Добавить(Выборка.Ссылка);
Иначе
Рекурсивно(Выборка,М);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
31. Александр Чепелевич (ChAlex) 10.10.12 20:56
Не сразу заметил, что можно оформить тегом :)
Функция ПолучитьСписокЭлементовДерева(ИмяСправочника, Развернуть, ДляДерева=Ложь) Экспорт 
	Запрос = Новый Запрос(); 
Если Развернуть Тогда 
	СписокЭлементов = Новый Массив; 
Если ДляДерева Тогда 
	Запрос.Текст="ВЫБРАТЬ РАЗЛИЧНЫЕ 
| Номенклатура.Ссылка.Родитель КАК Ссылка 
|ИЗ 
| Справочник.Номенклатура КАК Номенклатура 
|ГДЕ 
| Номенклатура.ЭтоГруппа 
| И Номенклатура.Ссылка.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) 
	|ИТОГИ ПО 
| Ссылка ИЕРАРХИЯ 
|АВТОУПОРЯДОЧИВАНИЕ"; 
Иначе 
	Запрос.Текст="ВЫБРАТЬ 
| Номенклатура.Ссылка КАК Ссылка 
|ИЗ 
| Справочник.Номенклатура КАК Номенклатура 
|ГДЕ 
| Номенклатура.ЭтоГруппа 
|ИТОГИ ПО 
| Ссылка ИЕРАРХИЯ 
|АВТОУПОРЯДОЧИВАНИЕ"; 
КонецЕсли; 
Рез=Запрос.Выполнить(); 
Рекурсивно(Рез,СписокЭлементов); 
Возврат СписокЭлементов; 
Иначе 
	Запрос.Текст="ВЫБРАТЬ 
| Номенклатура.Ссылка КАК Ссылка 
|ИЗ 
| Справочник.Номенклатура КАК Номенклатура 
|ГДЕ 
| Номенклатура.ЭтоГруппа 
| И Номенклатура.Ссылка.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) 
	|АВТОУПОРЯДОЧИВАНИЕ"; 
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"); 
КонецЕсли; 
КонецФункции 

Процедура Рекурсивно(Выб,М) 
Выборка = Выб.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией,"Ссылка"); 
Пока Выборка.Следующий() Цикл 
	Если Выборка.ТипЗаписи()=ТипЗаписиЗапроса.ИтогПоГруппировке И (ТипЗнч(Выб)=Тип("РезультатЗапроса") ИЛИ Выборка.Ссылка<>Выб.Ссылка) Тогда 
	М.Добавить(Выборка.Ссылка); 
Иначе 
	Рекурсивно(Выборка,М); 
КонецЕсли; 
КонецЦикла; 
КонецПроцедуры 
...Показать Скрыть
32. Михаил Шумский (iRounder) 10.10.12 21:00
(30) Не согласен.
Мой алгоритм реализует обе задачи.
Либо я не понял, что Вы имеете в виду под "1 - есть потребность разворачивания всей иерархии вместе с элементами, и 2 - разворачивать только структуру подчиненности (т.е. только дерево)"
Прошу пояснить что значит только дерево?
В моем варианте все элементы дерева и вся иерархия - видны.
33. Михаил Шумский (iRounder) 10.10.12 21:03
(31) Вы пробовали без доработок открыть дерево моим алгоритмом? Если да - то что именно не развернулось в дереве.
По поводу оптимизации запроса - там возможно и есть над чем подумать (будет время гляну). Не знаю почему - но хотелось сделать универсальный запрос: и для "Иерархия групп и элементов" и для "Иерархия элементов".
34. Александр Чепелевич (ChAlex) 10.10.12 21:16
(32) - ну тогда я не понял совсем смысла телодвижений в вашей процедуре с удалением каких то строк и поиском и добавлением чего-то. Можно развернуть иерархию дерево (элементы последнего уровня не разворачивать, ибо в них могут находится только элементы). Такое свойственно например если на форме вывести отдельно дерево справочника и отдельно список (как часто делалось в обычном интерфейсе). В таком случае нужно разворачивать не последний уровень иерархии а предпоследний. А можно разворачивать весь список, включая элементы на самом нижнем уровне. В таком случае нужно разворачивать уже самый последний уровень иерархии. Вот и все, что я имел ввиду. А по поводу производительности - да с уменьшением количества разворачиваемых элементов, время уменьшается.

(33) - пробовал я вашим запросом делать. Результат тот же (по скорости тот же порядок - однозначно не замерить, ситуация все время меняется - сервер то работает и нагрузка меняется). Я вообще-то не говорю что он не устраивает. Я говорил - что понять смысл вторичной обработки после запроса - не догоняю.
35. Михаил Шумский (iRounder) 10.10.12 21:24
(34) Да - можно сказать, что у меня разворачивается предпоследний уровень иерархии, т.е. последний, на котором могут быть родители элемента. Но... Но ведь развернув родителя на предпоследнем уровне иерархии автоматически становятся видны все его подчиненные элементы - это ли не есть развернуть ветвь дерева, когда я вижу все его элементы, вплоть до самого "глубокого"?

А вторичную обработку я сейчас поясню (не исключаю, что ее можно сделать и посредством запроса - например, вложенного). Но опять же повторюсь - делал универсальный запрос для всех типов иерархии. Возможно это и не совсем правильно.
36. Михаил Шумский (iRounder) 10.10.12 21:48
Для начала приношу извинения. В функции ПолучитьСписокЭлементовДерева(ИмяСправочника, Развернуть) в публикацию попала строка, которой там быть не должно (из старой версии). Ее нужно удалить. Хотя она и не влияла на производительность или корректность разворачивания. Именно из-за нее сворачивание происходило дольше.
Вот эта строка:
СписокЭлементов.ЗагрузитьЗначения(СписокРодители.ВыгрузитьКолонку("Родитель"));
она находится перед: Если Развернуть Тогда
10-я по счету в указанной функции.
37. Михаил Шумский (iRounder) 10.10.12 21:56
Ну и суть методики.

Запросом я выбираю всех различных родителей (здесь не важно какого типа иерархия у справочника, просто в одном случае это будет ссылка на элемент, в другом на группу).

А далее в обработке результатов запроса - это и есть суть оптимизации - я:
для сворачивания выбираю лишь родителей без родителей, т.е. фактически родителей с верхнего уровня группировки, формирую список узлов и отдаю в процедуру разворачивания/сворачивания;
для разворачивания формируется список из родителей, у которых нет в подчинении родителей (это то, что я ранее назвал КЛЮЧЕВЫМИ узлами, разворачивания которых абсолютно достаточно для отображения дерева в полностью развернутом виде), т.е. только тех родителей, у которых в подчинении только элементы, т.е. предпоследний уровень иерархии на ветви дерева, формирую список узлов и отдаю в процедуру разворачивания/сворачивания;
38. Александр Чепелевич (ChAlex) 11.10.12 11:14
(35) Вот так чаще всего (желаниям нет предела, что людей то столько правд) пользователь хочет видеть разворот справочника в варианте отображения списка в виде одного единственного дерева. В данном случае ему ВАЖНО видеть все элементы (и разворачивать дерево в данном случае нужно по узлу последнего уровня иерархии), это позволяет легче прокручивать ненужные группы и при этом быстрее ориентироваться в нахождении нужной позиции. И не убеждайте как 1С что отбор в этом случае лучше - далеко не всегда и можно об этом поспорить отдельно.

http://itmages.ru/image/view/710102/15c6ad9c

А вот так чаще всего отображается справочник с двумя списками: дерево для иерархии и список с отбором позиций по текущей строке дерева. В данном случае дерево нужно разворачивать по узлам предпоследней иерархии.

http://itmages.ru/image/view/710101/2fc58faa

Так что ваша функция с запросом оба варианта не реализовывает, как бы вы не утверждали. Я вам предложил идею простой процедуры получения предпоследнего, последнего и первого уровня иерархии запросом и рекурсивным обходом выборки, что правильнее, прозрачней, быстрей и лучше поддерживается. Чуть измените запрос и уберите отбор по группе получите универсально для иерархии элементов. А еще можно проверять вид иерархии справочника и делать разные запросы. Как душе угодно. И одним параметром можно получить сразу разный вариант разворота - хотите до кровня последних элементов (вариант 1), хотите до уровня только иерархии (вариант 2)
39. Борис Скворцов (gaglo) 11.10.12 11:19
С интересом прочитал обсуждение.
Видно, что в публикации изначально не хватало:
- указания из (15), что "смысла в этой методике нет в режиме обычного приложения"
- картинки, которая бы сразу показала вид развернутого дерева.
Теперь (наконец) стало ясно, необходима ли мне такая методика.
40. Viktor Kupko (zipik) 11.10.12 11:23
когда уже УФ доведут до ума
41. Михаил Шумский (iRounder) 11.10.12 12:13
(39) Да бросьте - изначально в заголовке публикации было указано "управляемый интерфейс" :)

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

Еще раз отмечу - что публиковалась методика, т.е. идея. А ее реализовывать можно по разному. Моя реализация - не оптимальна. И рад, что тема вызвала такое обсуждение, пусть и лишь с участием нескольких человек.

Ну и попрошу одного пояснения - у Вас все, что было Вами написано в этом обсуждении уже было реализовано до появления этой публикации или нет?
Т.е. мне интересно идея КЛЮЧЕВЫХ узлов была для Вас нова, или нет? (просто помню обсуждение подобной темы на мисте, где Вы говорили, что иерархический справочник из 5 000 строк открывался более 3 минут)
42. Александр Чепелевич (ChAlex) 11.10.12 14:51
(41) - Изначально я закинул решение этой задачи для конкретно большого справочника и просто по-умолчанию поставил режим отображения в виде иерархического дерева. + до сегодняшнего моемента все как-то не доходили руки до добавления сервиса в виде сворачивания и разворачивания деревьев в иных формах. Вообщем-то отчасти из-за того, что как то отложилось что нужно передавать иденитификатор строки (Тип Произвольный в документации для параметра никак не ассоциировался с ссылкой и к тому же в обычном дереве точно давал ошибку и требовался идентификатор строки) , а для динамического списка он отсутствует, вот и забил на это дело. Второй момент, который подсознательно давил, так это ну просто ТУПАЯ реализация стандартного поведения данного объекта в 1С. 5 минут разворачивается стандартными внутренними средствами 1С справочник в моей базе при развороте. Поэтому демонстрация того что срабатывает ссылка - решило проблемы с тем чтобы пробовать. Второй момент - честно как-то не думал раньше разворачивать не первый уровень, а последний. Почему-то тоже отложилось должно быть одно и тоже, а скорее всего просто производительность не тормозила, что бы как-то оптимизировать. Разворачивать верхний уровень с подчиненными програмно намного проще. Ко всему в обычных формах это нормально работало. Хотя стоит попробовать и там разворачивать последний уровень. Возможно поведение однотипное. В результате тестов на производительность можно однозначно сказать - оптимизации работы динамического списка нет абсолютно (как минимум в режиме дерева), поэтому если и использовать режим дерева, то разворачивать следует действительно самый нижний требуемый уровень. Разворот вниз от самого верхнего узла 1С делает аналогично тупо, как и работа с деревом. И этот вариант только может привести хоть к каким-то приемлимым цифрам по быстродействию. Хоть в целом и не фонтан, ну что тут зделаешь
43. Александр Чепелевич (ChAlex) 11.10.12 15:01
Собственно ваше решение подтолкнуло вернуться к этой проблеме. :)
44. Михаил Шумский (iRounder) 11.10.12 15:09
(42) Опять же не могу понять к чему именно относится Ваша фраза "оптимизации работы динамического списка нет абсолютно" (как минимум в режиме дерева)? Если это относится к этой публикации, то не соглашусь, т.к. она как раз и была предназначена для того, чтобы продвинуть идею разворачивания не всех, а лишь ключевых узлов, а это и есть оптимизация (и существенный выигрыш по времени, хотя как Вы выразились на выходе все равно не фонтан - это уже зависит от справочника). А если фраза относится не к публикации - тогда прошу пояснить к чему именно.
45. Александр Чепелевич (ChAlex) 11.10.12 17:06
(44) - это относится к объекту 1С - "Динамический список"
46. Михаил Шумский (iRounder) 11.10.12 17:14
(45) Спасибо за конструктивное обсуждение.
47. kiril lipatov (kilokilo) 11.10.12 17:37
Я вот не пойму - а зачем использовать динамический список, если нужно все дерево разворачивать??
48. Александр Чепелевич (ChAlex) 11.10.12 17:57
(47) - тогда подскажите каким образом можно вывести список справочника в управляемой форме кроме динамического списка. Я думаю даже 1С узнает что-то новое про свой продукт :)
49. Борис Скворцов (gaglo) 12.10.12 11:29
(41) Признаю, был неправ, не дочитал конец заголовка, а чуть ниже - многочисленные "не имеет значения" в рубрикаторе - ввели в меня заблуждение...
Но картинку все ж надо было приделать.
50. Михаил Шумский (iRounder) 12.10.12 12:37
(49) К сожалению нету рубрикатора для указания типа интерфейса или приложения.
51. Алексей Верещагин (alexware) 06.11.12 22:56
(42) ChAlex,
А меня ещё больше, чем возможность использования ссылки в качестве параметра, удивил сам результат применения метода "Раскрыть" к глубоко вложенным ветвям дерева. Никогда бы не подумал, что при этом раскроются все родительские узлы. Я считал, что в этом случае просто запомнится состояние данного узла во внутренних переменных.
И вот что в связи с этим я для себя при этом обнаружил. Если на форме размещается дерево (полученное, например, запросом), то в нём запоминается состояние "раскрыт" для дочерних узлов. Т.е. если закрыть и заново открыть родительский узел, то его дочерние узлы будут раскрыты или закрыты в зависимости от того, какими мы их оставили. А в динамическом списке в виде дерева этого нет. Хотя, если задуматься, то понятно почему.
52. Павел Иванов (blockcode) 20.03.13 09:06
Приходилось работать с отрисовкой деревьев. Принцип построения динамического дерева прост:
1) На первом этапе формируем дерево только из корневых узлов и их подчиненных, т.е. нулевой и первый уровень. Оставляем их свернутыми.
2) При разворачивании каждого узла для его дочерних улов удаляем и дорисовываем внуков при их наличии. Если внуков не удалять, то при повторном открытии они будут множиться )))
Экономия во времени получается за счет не раскрытых узлов, что для деревьев с большим количеством узлов актуально.