Дерево значений идеально подходит для выгрузки иерархии:
// выгребаем запросом и кидаем в Дерево с ценами
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
| ТоварыНаСкладахОстатки.ВНаличииОстаток КАК ВНаличииОстаток,
| ТоварыНаСкладахОстатки.Характеристика КАК Характеристика
|ПОМЕСТИТЬ втОстатки
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК ТоварыНаСкладахОстатки
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| Характеристика
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| втОстатки.Номенклатура.ЭтоГруппа КАК Группа,
| втОстатки.Номенклатура КАК Номенклатура,
| втОстатки.Характеристика КАК Характеристика,
| втОстатки.ВНаличииОстаток КАК Остаток,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
| ШтрихкодыНоменклатуры.Штрихкод КАК Штрихкод
|ИЗ
| втОстатки КАК втОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ВидЦены = &ВидЦены) КАК ЦеныНоменклатурыСрезПоследних
| ПО втОстатки.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
| И втОстатки.Характеристика = ЦеныНоменклатурыСрезПоследних.Характеристика
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
| ПО втОстатки.Номенклатура = ШтрихкодыНоменклатуры.Номенклатура
| И втОстатки.Характеристика = ШтрихкодыНоменклатуры.Характеристика
|
|УПОРЯДОЧИТЬ ПО
| втОстатки.Номенклатура.Наименование,
| Остаток УБЫВ
|ИТОГИ
| МАКСИМУМ(Характеристика),
| СУММА(Остаток),
| МАКСИМУМ(Цена),
| МАКСИМУМ(Штрихкод)
|ПО
| Номенклатура ТОЛЬКО ИЕРАРХИЯ";
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
ДЗ = Новый ДеревоЗначений;
ДЗ = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Рекурсия - обязательный ингредиент для обхода дерева (форматируем ячейки по ходу):
Процедура ВывестиДеревоВЭксель(СтрокиДерева, Лист, НомерСтроки, ВнешнийБланк) // ТЕСТ перед переносом в Модуль
Для Каждого стрДерева из СтрокиДерева Цикл
Лист.Range(Лист.cells(НомерСтроки,1),Лист.cells(НомерСтроки,6)).Borders.Linestyle = 1; // тонкая линия вокруг ячеек
Лист.Cells(НомерСтроки,1).NumberFormat = "@"; //"@" - текстовый "0.00" - числовой
Лист.cells(НомерСтроки,1).value = ?(стрДерева.Группа, "", Строка(стрДерева.Штрихкод));
Если стрДерева.Группа Тогда // Форматируем строку ГРУППЫ
Если стрДерева.Уровень() = 0 Тогда // исключительно для Корня с уровнем 0
Лист.Rows(НомерСтроки).Font.Size = 14;
Лист.Rows(НомерСтроки).Font.Bold = 1;
Лист.Rows(НомерСтроки).HorizontalAlignment = -4108; //По центру -4108
Лист.Range(Лист.cells(НомерСтроки,1),Лист.cells(НомерСтроки,6)).Interior.Color = ПолучитьЦветExcelRGB(255, 255, 0); // залить желтым
Иначе
Лист.Rows(НомерСтроки).Font.Size = 12;
Лист.Rows(НомерСтроки).Font.Bold = 1;
Лист.Range(Лист.cells(НомерСтроки,1),Лист.cells(НомерСтроки,6)).Interior.Color = ПолучитьЦветExcelRGB(50, 205, 50); // красим группу в салатовый
КонецЕсли;
Лист.cells(НомерСтроки,2).value = Строка(стрДерева.Номенклатура); // выводим только Номенклатуру
Иначе // это детальные записи
Лист.cells(НомерСтроки,2).value = Строка(стрДерева.Номенклатура) + " /" + Строка(стрДерева.Характеристика) + "/";
Если ВнешнийБланк Тогда
Лист.cells(НомерСтроки,4).value = стрДерева.Цена; // выводим цену в ячейку
// красим ячейку в нужный цвет
Если стрДерева.Остаток < 5 Тогда //красный
Лист.Cells(НомерСтроки,3).Interior.Color = ПолучитьЦветExcelRGB(255,0,0);
ИначеЕсли стрДерева.Остаток < 10 Тогда //желтый
Лист.Cells(НомерСтроки,3).Interior.Color = ПолучитьЦветExcelRGB(255,255,0);
Иначе //Зеленый
Лист.Cells(НомерСтроки,3).Interior.Color = ПолучитьЦветExcelRGB(0,255,0);
КонецЕсли;
Иначе // на внутреннем бланке нужно количество в цифрах, а цена не нужна
Лист.cells(НомерСтроки,3).value = СтрЗаменить(стрДерева.Остаток,Символы.НПП,""); // убрать неразрывный пробел между тысячами Строка(стрДерева.Остаток);
КонецЕсли;
Лист.Cells(НомерСтроки,5).Interior.Color = ПолучитьЦветExcelRGB(255,200,200); //красим поле "необходимое количество"
Лист.Cells(НомерСтроки,6).FormulaLocal = "=RC[-2]*RC[-1]";
КонецЕсли;
НомерСтроки = НомерСтроки + 1; // идем на следующую строку
Если стрДерева.Строки.Количество() <> 0 Тогда // рекурсия
ВывестиДеревоВЭксель(стрДерева.Строки, Лист, НомерСтроки, ВнешнийБланк);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Тестировал на УТ 11.4.13.155.
Чуть позже добавлю полный справочник по командам Excel.