Каталог решений - Группировка текста

Группировка текста

Группировка текста

В наличии

Большой текст с многочисленными отступами… Сделаем группировки по этим отступам и свернём их для удобства чтения!

Категория:

Описание

Был у меня процесс, выдававший очень неслабый текст протокола действий, под 400 тыщ строк. И смотреть его глазками стало невыносимо, а иной анализ результата не давал. И решил я сгруппировать текст, просто по отступам, которые, вдобавок, имели свой смысл и логику. Что позволяет свернуть группировки? Да, обычный моксель. Результатом стала функция, превращающая текст в табличный документ, где все имеющиеся отступы сгруппированы. Функция портируемая; под УФ не проверял, но должна пойти. 

Функция СгруппироватьТекст(Знач рТекстИлиСтрока,рСохранятьОтступы=Истина,дТекста=Неопределено)
   
дТекста=Новый ДеревоЗначений;
   
дТекста.Колонки.Добавить(«Отступ»,Новый ОписаниеТипов(«Число»,Новый КвалификаторыЧисла(3,0)));
   
дТекста.Колонки.Добавить(«Текст»,Новый ОписаниеТипов(«Строка»,,Новый КвалификаторыСтроки(0)));
   
дТекста.Колонки.Добавить(«Единица»,Новый ОписаниеТипов(«Число»,Новый КвалификаторыЧисла(1,0)));
   
//
   
Если ТипЗнч(рТекстИлиСтрока)=Тип(«Строка») Тогда
       
рТекст=Новый ТекстовыйДокумент;
       
рТекст.УстановитьТекст(рТекстИлиСтрока);
    КонецЕсли;

    рТекущаяВетка=дТекста.Строки.Добавить(); // корневая
   
квостр=рТекст.КоличествоСтрок();
   
квоиз=» из «+СокрЛП(квостр);
    Для
й=1 По квостр Цикл
       
#Если Клиент Тогда
           
ОбработкаПрерыванияПользователя();
           
Состояние(«Подготовка: строка «+Строка(й)+квоиз);
       
#КонецЕсли
       
стро=рТекст.ПолучитьСтроку(й);
        Если
ПустаяСтрока(стро) Тогда
           
рРодитель=рТекущаяВетка.Родитель; // пишем на тот же уровень
           
рОтступ=рТекущаяВетка.Отступ; строБезОтступа=«»;
        Иначе
           
рОтступ=0; строБезОтступа=«»;
            Для
ы=1 По СтрДлина(стро) Цикл
               
сим=Сред(стро,ы,1);
                Если
сим=» » или сим=Символы.НПП или сим=Символы.Таб Тогда
                   
рОтступ=рОтступ+1;
                Иначе
                   
строБезОтступа=Сред(стро,ы); Прервать;
                КонецЕсли;
            КонецЦикла;
           
// ищем ветку с подходящим числом отступов
           
Пока Истина Цикл
               
#Если Клиент Тогда
                   
ОбработкаПрерыванияПользователя();
               
#КонецЕсли
               
Если рТекущаяВетка.Отступ=рОтступ Тогда // стыкуемся к её родителю
                   
рРодитель=рТекущаяВетка.Родитель; Прервать;
                ИначеЕсли
рТекущаяВетка.Отступ<рОтступ Тогда // стыкуемся к ней
                   
рРодитель=рТекущаяВетка; Прервать;
                Иначе
// идём выше
                   
рТекущаяВетка=рТекущаяВетка.Родитель;
                    Если
рТекущаяВетка=Неопределено Тогда Прервать КонецЕсли;
                КонецЕсли;
            КонецЦикла;
            Если не
ЗначениеЗаполнено(рРодитель) Тогда
               
рРодитель=дТекста.Строки.Получить(0);
            КонецЕсли;
        КонецЕсли;
       
// добавляем
       
рВетка=рРодитель.Строки.Добавить();
       
рВетка.Отступ=рОтступ;
       
рВетка.Текст=строБезОтступа;
       
рВетка.Единица=1;
       
рТекущаяВетка=рВетка;
    КонецЦикла;
   
//
   
рТекст.Очистить(); // а чтоб оперативку не занимал
   
рТекст=«»; рТекстИлиСтрока=«»;

    тд=Новый ТабличныйДокумент;

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

    тд.Область(1,1,тд.ВысотаТаблицы,1).ШиринаКолонки=100;
   
тд.ОтображатьГруппировки=Истина;
   
тд.ОтображатьСетку=Ложь;
   
// а всякое раскрытие группировок — уже при показе, если будет надо
   
Возврат тд;
КонецФункции

Напоминает всем нам известный редактор модулей 1С по эффекту работы))).  Кому сгодится — будет хорошо)

P.S. Можно и без дерева значений, но оно мне тоже было нужно.

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