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