Был у меня процесс, выдававший очень неслабый текст протокола действий, под 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. Можно и без дерева значений, но оно мне тоже было нужно.