Пример замены запросов на выгрузку итогов регистра в универсальных отчетах с группировками а также пример работы с индексированной таблицей значений.

Часто в отчетах типовых конфигураций (будем рассматривать на примере ТиС) вместо временного расчета регистра и выгрузки его итогов используются запросы.

Такая методика встречается в отчетах: «Остатки ТМЦ», «График платежей» и многих самописных отчетах.

Почему? Ведь это же отнимает гораздо больше времени (особенно если установить большое количество группировок).
Думаю из-за того, что достаточно просто можно применять условия (в т.ч. условия множественного фильтра) и получать сгруппированную информацию.

Кратко опишу что можно сделать для ускорения.
1. Установить необходимые фильтры для регистров (все свести к спискам значений).
2. При необходимости произвести временный расчет участвующих в отчете регистров.
3. Выгрузить итоги в таблицу значений.
4. Обработать таблицу (если необходимо убрать ненужный блок, посчитать, заполнить недостающие колонки, сгруппировать и т.п.).
5. Вывести результат.

1. Часто требуется установить фильтр по фирме, юр. лицу, упр. аналитике. Рассмотрим именно эти условия.

Это можно свести к получению списка нужных фирм, а в каждом регистре, как правило, есть измерение фирма, т.е. задача решается достаточно просто.

Запрос = СоздатьОбъект("Запрос");
ТекстЗапросаФ = "
|Фирма = Справочник.Фирмы.ТекущийЭлемент;
|ЮрЛицо = Справочник.Фирмы.ЮрЛицо;
|УпрАналитика = Справочник.Фирмы.УпрАналитика;
|Группировка Фирма без упорядочивания;
|Без итогов;
|";

//Используем стандартные условия множественного фильтра к нашему маленькому запросу
НетОш = 1;
Если ВидРазделителя = 1 Тогда
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "Фирма",ВыбРазделитель1,"ВыбРазделитель1",
    ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "ЮрЛицо",,,ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "УпрАналитика",,,ТекстЗапросаФ,Загол);
ИначеЕсли ВидРазделителя = 2 Тогда                                                      
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "ЮрЛицо",ВыбРазделитель2,"ВыбРазделитель2",
    ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "Фирма",,,ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "УпрАналитика",,,ТекстЗапросаФ,Загол);
ИначеЕсли ВидРазделителя = 3 Тогда                                                       
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "УпрАналитика",ВыбРазделитель3,"ВыбРазделитель3",
    ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "Фирма",,,ТекстЗапросаФ,Загол);
    НетОш = НетОш * глФильтрПоПеременнойЗапроса(ТаблицаМФ, "ЮрЛицо",,,ТекстЗапросаФ,Загол);
КонецЕсли;

Если НетОш = 0 Тогда
    Возврат;
КонецЕсли;

Если Запрос.Выполнить(ТекстЗапросаФ) = 0 Тогда
    Возврат;
КонецЕсли;

ТЗФирм = СоздатьОбъект("ТаблицаЗначений");
СписокФирм = СоздатьОбъект("СписокЗначений");
Запрос.Выгрузить(ТЗФирм);
ТЗФирм.Выгрузить(СписокФирм,,,"Фирма");

//Теперь можно устанавливать фильтр по списку фирм
ВремПокупатели.УстановитьЗначениеФильтра("Фирма", СписокФирм, 2);

2. Временный расчет регистров, еще проще:

Если ДатаНачала < ПолучитьДатуТА() Тогда
    Если ВидОтчета = 1 Тогда
        ВремПокупатели.ВременныйРасчет();
    ИначеЕсли ВидОтчета = 2 Тогда
        ВремПоставщики.ВременныйРасчет();
    Иначе
        ВремПокупатели.ВременныйРасчет();
        ВремПоставщики.ВременныйРасчет();
    КонецЕсли;
    ВремРег.РассчитатьРегистрыПо(ДатаНачала);
КонецЕсли; 

3, 4. Теперь таблицу нужно сгруппировать, чтобы получить итоги по указанным в отчете группировкам либо по группам контрагентов, ТМЦ и т.п.

Можно пользоваться различными решениями, в т.ч. и приведенными здесь, но я предпочитаю использовать Индексированную таблицу значений (далее ИТЗ), 1С++

Приведу примерный код вывода отчета.

ИТЗ = СоздатьОбъект("ИндексированнаяТаблица");
ИТЗ.Загрузить(ТЗ);
СтрокаГруппировки = СформироватьСтрокуГруппировки();
Если ПустаяСтрока(СтрокаГруппировки) = 0 Тогда
    ИТЗ.Группировать(СтрокаГруппировки, "Приход, Расход", 0);
КонецЕсли;

5. Выводим результат рекурсивно, как и в типовых отчетах

ВывестиГруппировку(ИТЗ,1);

Вот и все, теперь использованные функции и процедуры

Функция СформироватьСтрокуГруппировки()
    СтрокаГруппировок	= "";
    //Список группировок – полный аналог списку из типовых отчетов ТиС
    Для Сч = 1 по СписокГруппировок.РазмерСписка() Цикл
        Название = СписокГруппировок.ПолучитьЗначение(Сч);
        Если (Название = "Контрагент") и (ПоГруппам = 1) Тогда
            Доб = "&";
        Иначе
            Доб = "";
        КонецЕсли;
        СтрокаГруппировок = СтрокаГруппировок + "Инд" + Название + ":" + Доб + Название + "; ";
    КонецЦикла;

    Возврат Лев(СтрокаГруппировок, СтрДлина(СтрокаГруппировок) - 2);
КонецФункции //СформироватьСтрокуГруппировки()

//Может и плоховато, лень сильно думать было, улучшения приветствуются, пишите
Процедура ВывестиГруппировку(ИТЗ, Ном)
    Если ИТЗ.НомерКолонки("Контрагент_Родитель") > 0 Тогда
        НазваниеГруппировки = "Контрагент";
        ЕстьГруппы = 1;
    Иначе
        НазваниеГруппировки = СписокГруппировок.ПолучитьЗначение(Ном);
    КонецЕсли;
    ИТЗ.ВыбратьСтроки();
    Пока ИТЗ.ПолучитьСтроку()=1 Цикл
        ПечТекстСтроки = ИТЗ.ПолучитьЗначение(,НазваниеГруппировки);
        ТекРасшифровка = ПечТекстСтроки;
        НазваниеСекции = "Строка" + Ном;
        Прибавить = 1;
        Если ЕстьГруппы = 1 Тогда
            Если ИТЗ.__ЭтоГруппа__ = 1 Тогда
                НазваниеСекции = НазваниеСекции + "Г";
                Прибавить = 0;
            КонецЕсли;
        КонецЕсли;
        Если ПустоеЗначение(ПечТекстСтроки) = 1 Тогда
            ПечТекстСтроки = "Не выбран";
        КонецЕсли;
        //Тут ничего сложного, см. типовые отчеты
        ПечатьСтроки(ИТЗ,Ном,НазваниеСекции,НазваниеГруппировки,ПечТекстСтроки,ТекРасшифровка);
        Если ИТЗ.НомерКолонки("тзПотомки") > 0 Тогда
            Если ПустоеЗначение(ИТЗ.тзПотомки) = 0 Тогда
                ВывестиГруппировку(ИТЗ.тзПотомки, Ном + Прибавить);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры //ВывестиГруппировку()      

Данный подход с группировками и последующим их выводом применим и с использованием прямых или штатных запросов.

Только не забывайте в штатных запросах ставить Без итогов, Без упорядочивания (если все равно потребуется дальнейшая обработка таблицы) и Без групп (если группировать то уж группировать)

В прямых запросах можно обходиться другими методами.