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