Каталог решений - Дерево значений, которое негде посмотреть

Дерево значений, которое негде посмотреть

Дерево значений, которое негде посмотреть

В наличии

Метод "ВыбратьСтроку" остался в золотом веке толстого клиента, но необходимость окинуть одним взглядом всё дерево порой возникает. Предлагаю простое решение в виде одной функции — вывода в текстовое представление.

Категория:

Описание

Да, мы все понимаем, что модальные окна это плохо, а дерево значений не живёт на клиенте и не может быть отображено, но очень хочется следить за внешним видом и наполнением наших переменных хотя бы с целью отладки. Собственно, как раз для отладки «ВыбратьСтроку» у таблицы и дерева был незаменимым методом. Но, если таблицу значений можно более-менее адекватно увидеть в отладчике, то для иерархии дерева это совсем не вариант. Отладчик показывает содержимое крайне неудобно с точки зрения «единого просмотра».

Поэтому сделаем текстовое представление. Его можно выводить в окне сообщений и оттуда копировать, его можно сохранять в файл, его можно более-менее удобно посмотреть в отладчике. Разумеется, шрифт в том месте, где смотрите, должен быть моноширинным.

Никаких особых хитростей нет, кроме разве что одного места — определения максимального количества уровней в дереве. Признаю, что сделал это не самым оптимальным образом, через сериализацию (да ещё и всего дерева, когда хватило бы одной колонки) — можно и иначе, желающие да обрящут. Вот //sale.itcity.ru/profile/28527/ наверняка придумал бы иной способ, верю.

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

Используется вывод в текстовый документ с помощью текстового же макета:

// Выводит данные ДереваЗначений в ТекстовыйДокумент, пригодный к рассмотрению в отладчике, окне сообщений и показу.
//
// Параметры:
//    рВетка — дерево значений, подлежащее выводу. Может иметь почти любую глубину иерархии, количество и тип колонок. Если хватит
//        объявленных позиционных строк-заполнителей, всё поместится. Если иерархия слишком глубока, строки просто надо нарастить;
//    рТекст — на входе должен быть равен Неопределено; на выходе по окончании работы содержит результатный текстовый документ;
//    рПараметры — структура дополнительных настроек, допустимые ключи:
//        Колонки — структура колонок, которые подлежат выводу. Если пуста или имеет тип, отличный от структуры, выводятся все колонки;
//           если в ключах структуры указаны имена колонок, будут выведены только они. В значениях структуры можно передать строковое
//           представление формата, согласно которому должны будут форматироваться выводимые значения. По умолчанию формата нет;
//        ПоказыватьУровни — булево, управляет выводом №№ уровней (метод Уровень()), по умолчанию выключено;
//        ШагОтступа — число, определяющее шаг в символах, используемый для показа псевдографики иерархии веток в дереве.
//
&НаСервереБезКонтекста
Процедура ВывестиДеревоЗначенийВТекст(Знач рВетка,рТекст,Знач рПараметры=Неопределено)
Попытка
    Если
рТекст=Неопределено Тогда // первая итерация, шапочный вызов исходной части
        //—————————————————————————————————————————
        // Разбираем входные данные
       
Если ТипЗнч(рВетка)<>Тип(«ДеревоЗначений») Тогда Возврат КонецЕсли;
        Если
ТипЗнч(рПараметры)<>Тип(«Структура») Тогда рПараметры=Новый Структура КонецЕсли;
       
стрКолонок=?(рПараметры.Свойство(«Колонки»),рПараметры.Колонки,Неопределено);
        Если
ТипЗнч(стрКолонок)<>Тип(«Структура») Тогда стрКолонок=Новый Структура КонецЕсли;
       
рПоказыватьУровни=?(рПараметры.Свойство(«ПоказыватьУровни»),рПараметры.ПоказыватьУровни,Ложь); // затратное дело, кстати
       
рШагОтступа=?(рПараметры.Свойство(«ШагОтступа»),рПараметры.ШагОтступа,2); // для отображения отступа в колонке иерархии

        //—————————————————————————————————————————
        // Определяем максимальное количество уровней
        // Также можно получить максимальный уровень, «плоско» перебрав все строки (например, получив их через НайтиСтроки)
        // и в цикле для каждой вызывая Уровень() и определяя максимум.
        // Вариант через СКД и служебное поле «Уровень» ни на одной известной мне платформе не работоспособен (нехватка памяти).
        //
        //
        //рДеревоДляТеста=КакНибудьСкопироватьДерево(рВетка);
        //рДеревоДляТеста.Колонки.Вставить(0,»_Level»,Новый ОписаниеТипов(«Булево»)); // самый экономный вариант, с сохранением иерархии
        //мНенужных=Новый Массив;
        //Для й=1 По рДеревоДляТеста.Колонки.Количество()-1 Цикл
        //  мНенужных.Добавить(рДеревоДляТеста.Колонки[й]);
        //КонецЦикла;
        //Для каждого кол Из мНенужных Цикл
        //  рДеревоДляТеста.Колонки.Удалить(кол);
        //КонецЦикла;
        //
        рДеревоДляТеста=рВетка; // пока сериализуем прямо всё дерево (неоптимально, но…)
       
рЗапись=Новый ЗаписьXML;
       
рЗапись.УстановитьСтроку();
       
СериализаторXDTO.ЗаписатьXML(рЗапись,рДеревоДляТеста);
       
стро=рЗапись.Закрыть();
       
//
       
стро=СтрЗаменить(стро,«xmlns=»,«xmlns:myns1C=»); // иначе не будет работать XPath
        //
       
рЧтение=Новый ЧтениеXML;
       
рЧтение.УстановитьСтроку(стро);
       
постр=Новый ПостроительDOM;
       
рДокументДОМ=постр.Прочитать(рЧтение);

        рВыражение=«/ValueTree/row»; максКолвоУровней=1;
       
рРазыменователь=Новый РазыменовательПространствИменDOM(рДокументДОМ);
        Пока Истина Цикл
           
#Если Клиент Тогда
               
ОбработкаПрерыванияПользователя();
           
#КонецЕсли
           
рРезультат=рДокументДОМ.ВычислитьВыражениеXPath(рВыражение,рДокументДОМ,рРазыменователь,ТипРезультатаDOMXPath.Любой);
            Если
рРезультат.ПолучитьСледующий()=Неопределено Тогда Прервать КонецЕсли;
           
рВыражение=рВыражение+«/row»;
           
максКолвоУровней=максКолвоУровней+1;
        КонецЦикла;
       
максКолвоУровней=максКолвоУровней1; // можно и так: СтрЧислоВхождений(рВыражение,»/row»)-1;

        //—————————————————————————————————————————
        // готовим исходный макет вывода
        строПробелы=»                                                                                                                                                                                                                 «;
       
строРазделители=«===============================================================================================»;
       
строОтступы=«___________________________________________________________________________________________»; // тут нужны чуть для другого
        //
       
секШапка1=«|[_HCS»+Лев(строПробелы,максКолвоУровней*рШагОтступа)+«]|»; // HierarchyColumnShow
       
секГорРазделитель1=«|»+Лев(строОтступы,максКолвоУровней*рШагОтступа+6)+«|»; // здесь именно Отступы!
       
рШиринаКолонкиИерархии=СтрДлина(секШапка1)-2;
       
строПолейШапки=«#Поле _HCS
        |   #Выравнивание Центр»
;
       
строПолейЗаписи=«»;
       
//
       
Если рПоказыватьУровни Тогда
           
секШапка1=секШапка1+«[_Level]|»;
           
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,8)+«|»;
           
строПолейШапки=строПолейШапки+«
            |#Поле _Level
            |   #Выравнивание Центр»
;
           
строПолейЗаписи=«#Поле _Level
            |   #Выравнивание Центр
            |   #Забивать Истина»
;
        КонецЕсли;
       
//
       
мИменКолонок=Новый Массив;
        Для каждого
кол Из рВетка.Колонки Цикл
            Если
стрКолонок.Количество()<>0 и не стрКолонок.Свойство(кол.Имя) Тогда Продолжить КонецЕсли; // чётко указаны конкретные колонки
           
рДлинаИмениКолонки=СтрДлина(кол.Имя);
           
рНужнаяШирина=Макс(?(кол.Ширина<3,10,кол.Ширина),рДлинаИмениКолонки);
           
// к сожалению, ключевое слово «#Поля» неприменимо — платформа падает — поэтому делаем всё сами
           
секШапка1=секШапка1+«[«+кол.Имя+Лев(строПробелы,рНужнаяШиринарДлинаИмениКолонки)+«]|»;
           
секГорРазделитель1=секГорРазделитель1+Лев(строРазделители,рНужнаяШирина+1)+«=|»;
           
строПолейШапки=строПолейШапки+«
            |#Поле «
+кол.Имя+«
            |   #Выравнивание Центр»
;
           
рОписТипов=кол.ТипЗначения;
            Если
рОписТипов.Типы().Количество()=1 и рОписТипов.СодержитТип(Тип(«Булево»)) Тогда
               
рВыравнивание=«Центр»;
            ИначеЕсли
рОписТипов.СодержитТип(Тип(«Число»)) Тогда
               
рВыравнивание=«Право»;
            ИначеЕсли
рОписТипов.СодержитТип(Тип(«Строка»)) и рОписТипов.КвалификаторыСтроки.Длина=0 Тогда
               
рВыравнивание=«ПоШирине»;
            Иначе
               
рВыравнивание=«Лево»;
            КонецЕсли;
           
строПолейЗаписи=строПолейЗаписи+?(ПустаяСтрока(строПолейЗаписи),«»,Символы.ПС)+«#Поле «+кол.Имя+«
            |   #Выравнивание «
+рВыравнивание;
            Попытка
                Если
ЗначениеЗаполнено(стрКолонок[кол.Имя]) Тогда // указан формат, уточняющий показ колонки
                   
строПолейЗаписи=строПолейЗаписи+«
                    |   #Формат «»»
+СокрЛП(стрКолонок[кол.Имя])+«»»»;
                КонецЕсли;
            Исключение
            КонецПопытки;
           
мИменКолонок.Добавить(кол.Имя);
        КонецЦикла;
       
секШапка2=СтрЗаменить(СтрЗаменить(секШапка1,«[«,«<«),«]»,«>»);
       
секЗапись1=секШапка1; секЗапись2=секШапка2; // пусть они по дизайну пока не отличаются
       
секГорРазделитель2=СтрЗаменить(СтрЗаменить(секГорРазделитель1,«=»,«-«),«|»,«+»);
       
// обработаем нормальное обрамление шапки колонки иерархии
       
секГорРазделитель1=СтрЗаменить(секГорРазделитель1,«_»,«=»);
       
секГорРазделитель2=СтрЗаменить(секГорРазделитель2,«_»,» «);
       
//
       
тМакет=Новый ТекстовыйДокумент;
       
тМакет.ДобавитьСтроку(«#Область Шапка»);
       
тМакет.ДобавитьСтроку(строПолейШапки);
       
тМакет.ДобавитьСтроку(секГорРазделитель1);
       
тМакет.ДобавитьСтроку(секШапка1);
       
тМакет.ДобавитьСтроку(секШапка2);
       
тМакет.ДобавитьСтроку(секГорРазделитель1);
       
тМакет.ДобавитьСтроку(«#КонецОбласти»);
       
тМакет.ДобавитьСтроку(«»);
       
тМакет.ДобавитьСтроку(«#Область Запись»);
       
тМакет.ДобавитьСтроку(строПолейЗаписи);
       
тМакет.ДобавитьСтроку(секЗапись1);
       
тМакет.ДобавитьСтроку(секЗапись2);
       
тМакет.ДобавитьСтроку(секГорРазделитель2);
       
тМакет.ДобавитьСтроку(«#КонецОбласти»);
       
рПараметры.Вставить(«ИсходныйМакет»,тМакет); // пусть будет

        //—————————————————————————————————————————
        // Запускаем вывод в итоговый документ
        рТекст=Новый ТекстовыйДокумент;
       
сек=тМакет.ПолучитьОбласть(«Шапка»);
       
сек.Параметры._HCS=«Иерархия»;
        Для каждого
имякол Из мИменКолонок Цикл
           
кол=рВетка.Колонки[имякол];
           
сек.Параметры[кол.Имя]=?(ПустаяСтрока(кол.Заголовок),кол.Имя,кол.Заголовок);
        КонецЦикла;
       
рТекст.Вывести(сек);
       
//
       
пар=Новый Структура;
       
пар.Вставить(«МассивИмёнКолонок»,мИменКолонок);
       
пар.Вставить(«ТекущаяСекция»,тМакет.ПолучитьОбласть(«Запись»));
       
пар.Вставить(«ШиринаКолонкиИерархии»,рШиринаКолонкиИерархии);
       
пар.Вставить(«ПоказыватьУровни»,рПоказыватьУровни);
       
пар.Вставить(«Отступ»,0);
       
пар.Вставить(«ШагОтступа»,рШагОтступа);
       
ВывестиДеревоЗначенийВТекст(рВетка,рТекст,пар);

    Иначе
        // очередная итерация, вывод в текстовый документ
       
мИменКолонок=рПараметры.МассивИмёнКолонок;
       
рСекция=рПараметры.ТекущаяСекция;
       
рОтступ=рПараметры.Отступ;
       
рШиринаКолонкиИерархии=рПараметры.ШиринаКолонкиИерархии;
       
рПоказыватьУровни=рПараметры.ПоказыватьУровни;
       
//
       
строОтступы=«_________________________________________________________________________________________________________»;
       
строПробелы=»                                                                                                                                                                                                                 «;
       
//
       
пар=Новый Структура;
       
пар.Вставить(«МассивИмёнКолонок»,мИменКолонок);
       
пар.Вставить(«ТекущаяСекция»,рПараметры.ТекущаяСекция);
       
пар.Вставить(«ШиринаКолонкиИерархии»,рШиринаКолонкиИерархии);
       
пар.Вставить(«ПоказыватьУровни»,рПоказыватьУровни);
       
пар.Вставить(«ШагОтступа»,рПараметры.ШагОтступа);
       
пар.Вставить(«Отступ»,рОтступ+рПараметры.ШагОтступа);
       
//
       
Для каждого рПодветка Из рВетка.Строки Цикл
           
рСекция.Параметры._HCS=Лев(строПробелы,рОтступ)+«\»+Лев(строОтступы,рШиринаКолонкиИерархиирОтступ1);
            Если
рПоказыватьУровни Тогда
               
рСекция.Параметры._Level=рПодветка.Уровень();
            КонецЕсли;
            Для каждого
имякол Из мИменКолонок Цикл
               
рСекция.Параметры[имякол]=рПодветка[имякол];
            КонецЦикла;
           
рТекст.Вывести(рСекция);
           
ВывестиДеревоЗначенийВТекст(рПодветка,рТекст,пар)
        КонецЦикла;
       
//
   
КонецЕсли;
Исключение
   
Сообщить(«ВывестиДеревоЗначенийВТекст, ошибка: «+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры

Надеюсь, пригодится и упростит жизнь) 

has been added to your cart:
Оформление заказа