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