HelpF.pro

ДеревоЗначений в ТекстовыйДокумент

Код 1C v 8.2 УП
 // Выводит данные ДереваЗначений в ТекстовыйДокумент, пригодный к рассмотрению в отладчике, окне сообщений и показу.
//
// Параметры:
//    рВетка - дерево значений, подлежащее выводу. Может иметь почти любую глубину иерархии, количество и тип колонок. Если хватит
//        объявленных позиционных строк-заполнителей, всё поместится. Если иерархия слишком глубока, строки просто надо нарастить;
//    рТекст - на входе должен быть равен Неопределено; на выходе по окончании работы содержит результатный текстовый документ;
//    рПараметры - структура дополнительных настроек, допустимые ключи:
//        Колонки - структура колонок, которые подлежат выводу. Если пуста или имеет тип, отличный от структуры, выводятся все колонки;
//           если в ключах структуры указаны имена колонок, будут выведены только они. В значениях структуры можно передать строковое
//           представление формата, согласно которому должны будут форматироваться выводимые значения. По умолчанию формата нет;
//        ПоказыватьУровни - булево, управляет выводом №№ уровней (метод Уровень()), по умолчанию выключено;
//        ШагОтступа - число, определяющее шаг в символах, используемый для показа псевдографики иерархии веток в дереве.
//
&НаСервереБезКонтекста
Процедура ВывестиДеревоЗначенийВТекст(Знач рВетка,рТекст,Знач рПараметры=Неопределено)
Попытка
    Если рТекст=Неопределено Тогда // первая итерация, шапочный вызов исходной части
        //---------------------------------------------------------------------------------------------------------------------------
        // Разбираем входные данные
        Если ТипЗнч(рВетка)<>Тип("ДеревоЗначений") Тогда Возврат КонецЕсли;
        Если ТипЗнч(рПараметры)<>Тип("Структура") Тогда рПараметры=Новый Структура КонецЕсли;
        стрКолонок=?(рПараметры.Свойство("Колонки"),рПараметры.Колонки,Неопределено);
        Если ТипЗнч(стрКолонок)<>Тип("Структура") Тогда стрКолонок=Новый Структура КонецЕсли;
        рПоказыватьУровни=?(рПараметры.Свойство("ПоказыватьУровни"),рПараметры.ПоказыватьУровни,Ложь); // затратное дело, кстати
        рШагОтступа=?(рПараметры.Свойство("ШагОтступа"),рПараметры.ШагОтступа,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=рПодветка.Уровень();
            КонецЕсли;
            Для каждого имякол Из мИменКолонок Цикл
                рСекция.Параметры[имякол]=рПодветка[имякол];
            КонецЦикла;
            рТекст.Вывести(рСекция);
            ВывестиДеревоЗначенийВТекст(рПодветка,рТекст,пар)
        КонецЦикла;
        //
    КонецЕсли;
Исключение
    Сообщить("ВывестиДеревоЗначенийВТекст, ошибка: "+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры

Источник


Опубликовано на сайте: https://HelpF.pro
Прямая ссылка: https://HelpF.pro/faq83/view/1811.html