Возникла обычная задача - использовать фотографии товаров в прайс-листе. В 1С формируется ТЗ, создается книга Excel и в цикле ТЗ заполняются строки, с группировками видов товара и новыми листами в соответствии с заданием.
Варианты использования изображений товаров - в Примечании к ячейкам и в самих ячейках.
Со вставкой в Примечание - справился, а вот с ячейками возник последний "затык". Уточню, что строки Excel группируются, поэтому рисунки в ячейках должны скрываться при включении группировки.
Сделал тестовое заполнение.
Application = СоздатьОбъект("Excel.Application");
WorkBook = Application.WorkBooks.Add();
Worksheet = WorkBook.Worksheets(1);
Worksheet.Rows("2:2").RowHeight = 112.5;
Worksheet.Columns(2).ColumnWidth= 20.71;
Ячейка = Worksheet.Cells(2,2);
Ячейка.Select();
//вставляем объект рисунок
Worksheet.OLEObjects.Add("Forms.Image.1");
//задаем размеры
Worksheet.OLEObjects("Image1").Object.Height = 112.5;
Worksheet.OLEObjects("Image1").Object.Width = 112.5;
//привязываем к ячейке
Worksheet.OLEObjects("Image1").Object.Placement = 1;

А вот теперь нужно присвоить свойству Picture значение LoadPicture("d:\030-14.jpg"). Пока решил использовать макрос, но понятно, что так не прокатит в работе:

st = "Sub OLE1c()"
+Chr(13)+ "ActiveSheet.OLEObjects(""Image1"").Object.Picture = LoadPicture(""d:\030-14.jpg"")"
+Chr(13)+ "End Sub";
Application.VBE.ActiveVBProject.VBComponents(Worksheet.Name).CodeModule.AddFromString(st);
Application.Run(Worksheet.Name+".OLE1c");

Если кто-нибудь сталкивался с решением данного "костыля" - посоветуйте.
Возможно, использование строки
Worksheet.OLEObjects("Image1").Object.Picture
решит проблему, но параметров я не знаю, а в Экселевском макрос присваивание не видно.
---
Самоделкин, постараюсь оставить только необходимый "костяк".

```1c
    Процедура ЗаполнениеТЗ()
    Попытка
    ТЗ.Очистить();
    Исключение
    КонецПопытки;
    ТЗ.НоваяКолонка("Уровень" );
    ТЗ.НоваяКолонка("ГруппаТовара" );
    ТЗ.НоваяКолонка("ПодГруппаТовара" );
    ТЗ.НоваяКолонка("Артикул" );
    ТЗ.НоваяКолонка("Товар" );
    ТЗ.НоваяКолонка("ПолнТовар" );
    ТЗ.НоваяКолонка("Описание" );
    ТЗ.НоваяКолонка("ЦенаРозн" );
    ТЗ.НоваяКолонка("ЦенаМелОпт" );
    ТЗ.НоваяКолонка("ЦенаОпт" );
    ТЗ.НоваяКолонка("НачОст" );
    ТЗ.НоваяКолонка("Приход" );
    ТЗ.НоваяКолонка("Расход" );
    ТЗ.НоваяКолонка("Колво" );
    ТЗ.НоваяКолонка("Партия" );
    ТЗ.НоваяКолонка("Штрихкод" );
    //
    Запрос.вНачалоВыборки();
    Пока Запрос.Группировка() = 1 Цикл
    //пропускаем группы
    Если Запрос.Товар.ЭтоГруппа()=1 Тогда
    Продолжить;
    КонецЕсли;
    //если "только по имеющимся" = V и КонОст = 0, то пропускаем
    Если ((Ост = 1) и (Запрос.КонОст = 0)) Тогда
    Продолжить;
    КонецЕсли;
    //только пришедшие в заданный период
    Если Впериоде = 1 Тогда
    Если Запрос.Приход = 0 тогда
    Продолжить;
    КонецЕсли;
    КонецЕсли;
    //Уровни: 1-й - не использовать; 2-й - бренд; 3-й - вид товара или Товар; 4-й Товар
    ТЗ.НоваяСтрока();
    ТЗ.ПодГруппаТовара = Запрос.Товар.Родитель; //Уровень 3 или 2
    ТЗ.ГруппаТовара = ТЗ.ПодГруппаТовара.Родитель; //Уровень 2 или 1
    ТЗ.Уровень = Запрос.Товар.Уровень(); //4 или 3
    ТЗ.Артикул = СокрЛП(Запрос.Товар.Артикул);
    Если СокрЛП(Запрос.Товар.Описание) <> " Тогда
    ТЗ.Описание = " ("+СокрЛП(Запрос.Товар.Описание)+")";
    КонецЕсли;
    ТЗ.Товар = СокрЛП(Запрос.Товар);
    ТЗ.ПолнТовар = СокрЛП(Запрос.Товар.ПолноеНаименование);
    ТЗ.Товар = СтрЗаменить(ТЗ.Товар," "," ");
    ТЗ.ПолнТовар = СтрЗаменить(ТЗ.ПолнТовар," "," ");
    ТЗ.ЦенаРозн = Запрос.Товар.РозничнаяЦена.Получить(ДатаОтчета);
    ТЗ.ЦенаМелОпт = Запрос.Товар.МелкоОптоваяЦена.Получить(ДатаОтчета);
    ТЗ.ЦенаОпт = Запрос.Товар.ЦенаВРозницу.Получить(ДатаОтчета);
    ТЗ.Колво = Запрос.КонОст;
    Если ДопПоля = 1 Тогда
    ТЗ.НачОст = Запрос.НачОст;
    Если Впериоде = 1 Тогда
    ТЗ.Приход = Запрос.Приход;
    КонецЕсли;
    ТЗ.Расход = Запрос.Расход;
    ТЗ.Партия = Запрос.Партия;
    КонецЕсли;
    Если ШК>1 Тогда
    ТЗ.Штрихкод = Запрос.Товар.ШтрихКод;
    КонецЕсли;
    КонецЦикла;
    //добавляем НовыеТоварыИзЭкселя в прайс
    Если ПустаяЦена = 1 Тогда
    ДобавитьСПустымиЦенами();
    КонецЕсли;

    КонецЕсли;
    //сворачиваем строки
    СтрокаСвернуть = "Уровень,Артикул,ПолнТовар,Товар,ГруппаТовара,ПодГруппаТовара, Штрихкод";
    СуммаСвернуть = "Колво";
    Если флОписание = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",Описание";
    КонецЕсли;
    Если РозничнаяЦена = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаРозн";
    КонецЕсли;
    Если МелкоОптоваяЦена =1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаМелОпт";
    КонецЕсли;
    Если ЦенаВРозницу = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаОпт";
    КонецЕсли;
    Если Впериоде = 1 Тогда
    СуммаСвернуть = СуммаСвернуть + ",Приход";
    КонецЕсли;
    Если ДопПоля = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",Партия";
    СуммаСвернуть = СуммаСвернуть + ",НачОст,Расход";
    КонецЕсли;
    ТЗ.Свернуть(СтрокаСвернуть,СуммаСвернуть);
    //конец свертки
    ТЗ.Сортировать("+ГруппаТовара,ПодГруппаТовара,Артикул,Товар");
    СтрПрайс= ЗначениеВСтроку(ТЗ);
    ТЗ = ";
    ТЗЗапрос= ";
    КонецПроцедуры

    Процедура ТЗвЭксель()
    //выводим данные
    Выполнено = ";
    ПредИмяЛиста = ";
    ПредИмяГруппы = ";
    НачалоГруппировки = 0;
    КонецГруппировки = 0;
    НачалоГруппировкиГлоб = 0; //группировка как раз для листа
    КонецГруппировкиГлоб = 0;
    нСтроки = СтрокаШапки+1;
    Шрифтi = Шрифт.ПолучитьЗначение(Шрифт.ТекущаяСтрока());
    ТЗ = ЗначениеИзСтроки(СтрПрайс); //получаем ранее заполненную ТЗ с данными
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    //получаем имя листа по родителю 2-го уровня, всего в справочнике 4 уровня
    Если ТЗ.Уровень = 4 Тогда
    //ТЗ.ГруппаТовара - это уровень 2, бренд, имя листа
    ИмяЛиста = ТЗ.ГруппаТовара;
    ИначеЕсли ТЗ.Уровень = 3 Тогда
    //ТЗ.ПодГруппаТовара - это уровень 2, бренд, имя листа
    ИмяЛиста = ТЗ.ПодГруппаТовара;
    КонецЕсли;
    Если ИмяЛиста<>ПредИмяЛиста Тогда
    //если лист (глобальная группа) не первый
    Если ПредИмяЛиста <> " Тогда
    ВыводЛиста();
    ИначеЕсли (ПоВкладкам= 2) ИЛИ (Просто=1) Тогда
    ПараметрыЛиста(СокрЛП(ИмяЛиста.Наименование));
    нСтроки = СтрокаШапки+1;
    КонецЕсли;
    ВыводПервогоЛиста();
    ПредИмяЛиста= ИмяЛиста;
    СкГр.УдалитьВсе();
    КонецЕсли;
    //получаем имя группировки по родителю 3-го уровня
    Если ТЗ.Уровень = 4 Тогда
    //ТЗ.ПодГруппаТовара - это уровень 3, вид товара, имя группировки
    ИмяГруппы = ТЗ.ПодГруппаТовара;
    Если ИмяГруппы<>ПредИмяГруппы Тогда
    //знТовар - номер столбца "Товар" - он всегда выводится, нСтроки - номер строки по-порядку
    Форматы("знТовар",нСтроки,ИмяГруппы.Наименование,,8,,,ЦветГруппы.ТекущаяСтрока(),-4131,1);
    //форматирование строки
    Worksheet.Rows(нСтроки).HorizontalAlignment = -4108;
    Worksheet.Range(Worksheet.Cells(нСтроки,1),Worksheet.Cells(нСтроки,ПоследняяКолонка)).Interior.ColorIndex=ЦветГруппы.ТекущаяСтрока();
    ПредИмяГруппы = ИмяГруппы;
    Если Просто = 0 Тогда
    Если (НачалоГруппировки > 0) И (нСтроки > НачалоГруппировки) Тогда
    Если ПоВкладкам = 1 Тогда
    //конец группировки - предыдущая новой группе строка
    Если НачалоГруппировкиГлоб = нСтроки Тогда
    КонецГруппировки = нСтроки-2; //17
    Иначе
    КонецГруппировки = нСтроки-1; //17
    КонецЕсли;
    //группируем
    Worksheet.Range("+НачалоГруппировки+":"+КонецГруппировки).Rows.Group();
    НачалоГруппировки = 0;
    КонецЕсли;
    КонецЕсли;
    НачалоГруппировки = нСтроки+1; //13
    //переходим на новую строку, т.к. в этой все остальные колонки - пустые
    нСтроки = нСтроки+1;
    КонецЕсли;
    КонецЕсли;
    ИначеЕсли ТЗ.Уровень = 3 Тогда
    //значит, "выше только небо (с)". Это Товар без группы, что нужно в 1с исключать
    //выводим СтрокуТаблицы
    КонецЕсли;
    //вывод строки таблицы
    СтрокаТаблицы();
```

Процедура СтрокаТаблица() описана в самом начале темы.
Постарался писать без ошибок, но, как всегда, мог и недосмотреть :)
---
А можете приложить часть файла excel строк на 20 с группировками /то к чему стремитесь/? Очень любопытно посмотреть.
---
А можете приложить часть файла excel строк на 20 с группировками /то к чему стремитесь/? Очень любопытно посмотреть.

Держите.
---
При внедрении кода в рабочую обработку - во время работы цикла возникла ошибка со внедрением рисунка:

Worksheet.OLEObjects.Add("Forms.Image."+номКартинки);
{D:\1S_BASE\EXTFORMS\ВСТАВКАРИСУНКА.ERT(19)}: Microsoft Office Excel: Вставка объекта неосуществима.

номКартинки - целое число. Если использовать

Worksheet.OLEObjects.Add("Forms.Image.1");

то работает.
---
С последней ошибкой (внедрение рисунков в цикле) разобрался:

//внедрение картинки
Worksheet.OLEObjects.Add("Forms.Image.1");
Worksheet.OLEObjects("Image"+номКартинки).Object.Height = 112.5;
Worksheet.OLEObjects("Image"+номКартинки).Object.Width = 112.5;
Worksheet.OLEObjects("Image"+номКартинки).Object.Placement = 1;
---
Так и не смог "раскрутить" excel. :)
Интересное решение - спасибо - заберу в коллекцию.
---
Итак, чтобы попробовать исключить вставку макроса для внедрения рисунка попробую расписать весь код, тем более что слабых мест в нем несколько.

```1c
    Перем Application,WorkBook,Worksheet,Macros,нСтроки,нКолонки,номКартинки,ВыбФото;
    //*******************************************
    Процедура ДобавитьМакрос()
    //тут мы устанавливаем свойство Picture объекта
    Macros = "Sub OLE1c()"
    +Chr(13)+ "ActiveSheet.OLEObjects("Image"+номКартинки+"").Object.Picture = LoadPicture(""+ВыбФото+"")"
    +Chr(13)+ "End Sub"
    //тут мы удаляем все макросы
    +Chr(13)+ "Sub Удалить_код()"
    +Chr(13)+ "For Each iVBComponent In ThisWorkbook.VBProject.VBComponents"
    +Chr(13)+ "With iVBComponent"
    +Chr(13)+ "Select Case .Type"
    +Chr(13)+ "Case 1 To 3: .Collection.Remove iVBComponent"
    +Chr(13)+ "Case 100: .CodeModule.DeleteLines 1, .CodeModule.CountOfLines"
    +Chr(13)+ "End Select"
    +Chr(13)+ "End With"
    +Chr(13)+ "Next"
    +Chr(13)+ "End Sub";
    КонецПроцедуры
    //*******************************************
    Процедура ДобавитьФото()
    номКартинки = номКартинки+1;
    //устанавливаем высоту строки под известную высоту фото
    Worksheet.Rows("+нСтроки+":"+нСтроки).RowHeight = 112.5;
    Ячейка = Worksheet.Cells(нСтроки,нКолонки);
    //выбираем ячейку для вставки
    Ячейка.Select();
    //добавляем объект Рисунок
    Worksheet.OLEObjects.Add("Forms.Image.1");
    //устанавливаем параметры рисунка
    Worksheet.OLEObjects("Image"+номКартинки).Object.Height = 112.5;
    Worksheet.OLEObjects("Image"+номКартинки).Object.Width = 112.5;
    Worksheet.OLEObjects("Image"+номКартинки).Object.Placement = 1;
    //пытаемся с помощью макроса в объект вставить фото
    ДобавитьМакрос();
    //получаем количество объектов, в данном случае это Add (книга+лист(?))
    i = Application.VBE.ActiveVBProject.VBComponents.Count;
    //записываем макрос в Excel
    Application.VBE.ActiveVBProject.VBComponents(i).CodeModule.AddFromString(Macros);
    //WorkBook.VBProject.VBComponents.Item(i).CodeModule.AddFromString(Macros);
    //запускаем макросы по-очереди
    Application.Run("ЭтаКнига.OLE1c");
    Application.Run("ЭтаКнига.Удалить_код");
    КонецПроцедуры
    //*******************************************
    Процедура Сформировать()
    номкартинки = 0;
    нСтроки = 0;
    нКолонки = 1;
    ВыбФото = КаталогИБ()+"Photo\Nophoto.bmp";
    //"запускаем" Excel
    Попытка
    Application = СоздатьОбъект("Excel.Application");
    Исключение
    Предупреждение("У Вас на компьютере не установлен Microsoft Excel. Вставка невозможна!");
    Возврат;
    КонецПопытки;
    //Создание рабочей книги
    WorkBook = Application.WorkBooks.Add();
    //убираем выдачу предупреждений
    Application.DisplayAlerts = 0;
    //удаляем лишние листы
    Если WorkBook.Worksheets.Count = 0 Тогда
    WorkBook.Worksheets.Add();
    Иначе
    Пока WorkBook.Worksheets.Count > 1 Цикл
    WorkBook.Worksheets(1).Delete();
    КонецЦикла;
    КонецЕсли;
    //назначаем рабочий лист
    Worksheet = WorkBook.Worksheets(1);
    //устанавливаем ширину колонки под известную ширину фото
    Worksheet.Columns(нКолонки).ColumnWidth= 20.71;
    //вставляем фото. Например, в 5 ячеек
    Для к=1 По 5 Цикл
    нСтроки = нСтроки+1;
    ДобавитьФото();
    КонецЦикла;
    Application.Visible=-1;
    Application = 0;
    КонецПроцедуры
```

При выполнении макроса на одном листе проблем не возникает, однако - если листов несколько, то выпадает ошибка при добавлении OLE объекта. Дело вот в этой строке:
//получаем количество объектов, в данном случае это Add (книга+лист(?))
 i = Application.VBE.ActiveVBProject.VBComponents.Count;
 Application.VBE.ActiveVBProject.VBComponents(i).CodeModule.AddFromString(Macros);
Макрос принимает имя "ЭтаКнига.<ИмяМакроса>"/
Как обойти ограничение на имя вносимого макроса?
---
Я вообще не парился. Создавал моксель с рисунками и сохранял в эксель. и все. но это конечно если 1 лист...
---
Привет
у меня выдает ошибку, что может быть не верно?
Ячейка.Select();
{C:\DATA\1C\COPY\NEWP_SQL\EXTFORMS\ПРАЙСЛИСТ.ERT(367)}: Microsoft Office Excel: Метод Select из класса Range завершен неверно
---
К сожалению, пока нет времени на доработку - использую только картинки в Примечании к ячейке Excel.
Ошибка Ячейка.Select();
{C:\DATA\1C\COPY\NEWP_SQL\EXTFORMS\ПРАЙСЛИСТ.ERT(367)}: Microsoft Office Excel: Метод Select из класса Range завершен неверно
и у меня выскакивала. Зависимость ее появления отследить не удалось, но грешу на то, что не присваивается Ячейка = Worksheet.Cells(...)
---
zaraki, а можно пример, как каждому листу присвоить присвоить название группы и собрать там все товары из этой группы.
---
Самоделкин, постараюсь оставить только необходимый "костяк".

```1c
    Процедура ЗаполнениеТЗ()
    Попытка
    ТЗ.Очистить();
    Исключение
    КонецПопытки;
    ТЗ.НоваяКолонка("Уровень" );
    ТЗ.НоваяКолонка("ГруппаТовара" );
    ТЗ.НоваяКолонка("ПодГруппаТовара" );
    ТЗ.НоваяКолонка("Артикул" );
    ТЗ.НоваяКолонка("Товар" );
    ТЗ.НоваяКолонка("ПолнТовар" );
    ТЗ.НоваяКолонка("Описание" );
    ТЗ.НоваяКолонка("ЦенаРозн" );
    ТЗ.НоваяКолонка("ЦенаМелОпт" );
    ТЗ.НоваяКолонка("ЦенаОпт" );
    ТЗ.НоваяКолонка("НачОст" );
    ТЗ.НоваяКолонка("Приход" );
    ТЗ.НоваяКолонка("Расход" );
    ТЗ.НоваяКолонка("Колво" );
    ТЗ.НоваяКолонка("Партия" );
    ТЗ.НоваяКолонка("Штрихкод" );
    //
    Запрос.вНачалоВыборки();
    Пока Запрос.Группировка() = 1 Цикл
    //пропускаем группы
    Если Запрос.Товар.ЭтоГруппа()=1 Тогда
    Продолжить;
    КонецЕсли;
    //если "только по имеющимся" = V и КонОст = 0, то пропускаем
    Если ((Ост = 1) и (Запрос.КонОст = 0)) Тогда
    Продолжить;
    КонецЕсли;
    //только пришедшие в заданный период
    Если Впериоде = 1 Тогда
    Если Запрос.Приход = 0 тогда
    Продолжить;
    КонецЕсли;
    КонецЕсли;
    //Уровни: 1-й - не использовать; 2-й - бренд; 3-й - вид товара или Товар; 4-й Товар
    ТЗ.НоваяСтрока();
    ТЗ.ПодГруппаТовара = Запрос.Товар.Родитель; //Уровень 3 или 2
    ТЗ.ГруппаТовара = ТЗ.ПодГруппаТовара.Родитель; //Уровень 2 или 1
    ТЗ.Уровень = Запрос.Товар.Уровень(); //4 или 3
    ТЗ.Артикул = СокрЛП(Запрос.Товар.Артикул);
    Если СокрЛП(Запрос.Товар.Описание) <> " Тогда
    ТЗ.Описание = " ("+СокрЛП(Запрос.Товар.Описание)+")";
    КонецЕсли;
    ТЗ.Товар = СокрЛП(Запрос.Товар);
    ТЗ.ПолнТовар = СокрЛП(Запрос.Товар.ПолноеНаименование);
    ТЗ.Товар = СтрЗаменить(ТЗ.Товар," "," ");
    ТЗ.ПолнТовар = СтрЗаменить(ТЗ.ПолнТовар," "," ");
    ТЗ.ЦенаРозн = Запрос.Товар.РозничнаяЦена.Получить(ДатаОтчета);
    ТЗ.ЦенаМелОпт = Запрос.Товар.МелкоОптоваяЦена.Получить(ДатаОтчета);
    ТЗ.ЦенаОпт = Запрос.Товар.ЦенаВРозницу.Получить(ДатаОтчета);
    ТЗ.Колво = Запрос.КонОст;
    Если ДопПоля = 1 Тогда
    ТЗ.НачОст = Запрос.НачОст;
    Если Впериоде = 1 Тогда
    ТЗ.Приход = Запрос.Приход;
    КонецЕсли;
    ТЗ.Расход = Запрос.Расход;
    ТЗ.Партия = Запрос.Партия;
    КонецЕсли;
    Если ШК>1 Тогда
    ТЗ.Штрихкод = Запрос.Товар.ШтрихКод;
    КонецЕсли;
    КонецЦикла;
    //добавляем НовыеТоварыИзЭкселя в прайс
    Если ПустаяЦена = 1 Тогда
    ДобавитьСПустымиЦенами();
    КонецЕсли;

    КонецЕсли;
    //сворачиваем строки
    СтрокаСвернуть = "Уровень,Артикул,ПолнТовар,Товар,ГруппаТовара,ПодГруппаТовара, Штрихкод";
    СуммаСвернуть = "Колво";
    Если флОписание = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",Описание";
    КонецЕсли;
    Если РозничнаяЦена = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаРозн";
    КонецЕсли;
    Если МелкоОптоваяЦена =1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаМелОпт";
    КонецЕсли;
    Если ЦенаВРозницу = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",ЦенаОпт";
    КонецЕсли;
    Если Впериоде = 1 Тогда
    СуммаСвернуть = СуммаСвернуть + ",Приход";
    КонецЕсли;
    Если ДопПоля = 1 Тогда
    СтрокаСвернуть = СтрокаСвернуть + ",Партия";
    СуммаСвернуть = СуммаСвернуть + ",НачОст,Расход";
    КонецЕсли;
    ТЗ.Свернуть(СтрокаСвернуть,СуммаСвернуть);
    //конец свертки
    ТЗ.Сортировать("+ГруппаТовара,ПодГруппаТовара,Артикул,Товар");
    СтрПрайс= ЗначениеВСтроку(ТЗ);
    ТЗ = ";
    ТЗЗапрос= ";
    КонецПроцедуры

    Процедура ТЗвЭксель()
    //выводим данные
    Выполнено = ";
    ПредИмяЛиста = ";
    ПредИмяГруппы = ";
    НачалоГруппировки = 0;
    КонецГруппировки = 0;
    НачалоГруппировкиГлоб = 0; //группировка как раз для листа
    КонецГруппировкиГлоб = 0;
    нСтроки = СтрокаШапки+1;
    Шрифтi = Шрифт.ПолучитьЗначение(Шрифт.ТекущаяСтрока());
    ТЗ = ЗначениеИзСтроки(СтрПрайс); //получаем ранее заполненную ТЗ с данными
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    //получаем имя листа по родителю 2-го уровня, всего в справочнике 4 уровня
    Если ТЗ.Уровень = 4 Тогда
    //ТЗ.ГруппаТовара - это уровень 2, бренд, имя листа
    ИмяЛиста = ТЗ.ГруппаТовара;
    ИначеЕсли ТЗ.Уровень = 3 Тогда
    //ТЗ.ПодГруппаТовара - это уровень 2, бренд, имя листа
    ИмяЛиста = ТЗ.ПодГруппаТовара;
    КонецЕсли;
    Если ИмяЛиста<>ПредИмяЛиста Тогда
    //если лист (глобальная группа) не первый
    Если ПредИмяЛиста <> " Тогда
    ВыводЛиста();
    ИначеЕсли (ПоВкладкам= 2) ИЛИ (Просто=1) Тогда
    ПараметрыЛиста(СокрЛП(ИмяЛиста.Наименование));
    нСтроки = СтрокаШапки+1;
    КонецЕсли;
    ВыводПервогоЛиста();
    ПредИмяЛиста= ИмяЛиста;
    СкГр.УдалитьВсе();
    КонецЕсли;
    //получаем имя группировки по родителю 3-го уровня
    Если ТЗ.Уровень = 4 Тогда
    //ТЗ.ПодГруппаТовара - это уровень 3, вид товара, имя группировки
    ИмяГруппы = ТЗ.ПодГруппаТовара;
    Если ИмяГруппы<>ПредИмяГруппы Тогда
    //знТовар - номер столбца "Товар" - он всегда выводится, нСтроки - номер строки по-порядку
    Форматы("знТовар",нСтроки,ИмяГруппы.Наименование,,8,,,ЦветГруппы.ТекущаяСтрока(),-4131,1);
    //форматирование строки
    Worksheet.Rows(нСтроки).HorizontalAlignment = -4108;
    Worksheet.Range(Worksheet.Cells(нСтроки,1),Worksheet.Cells(нСтроки,ПоследняяКолонка)).Interior.ColorIndex=ЦветГруппы.ТекущаяСтрока();
    ПредИмяГруппы = ИмяГруппы;
    Если Просто = 0 Тогда
    Если (НачалоГруппировки > 0) И (нСтроки > НачалоГруппировки) Тогда
    Если ПоВкладкам = 1 Тогда
    //конец группировки - предыдущая новой группе строка
    Если НачалоГруппировкиГлоб = нСтроки Тогда
    КонецГруппировки = нСтроки-2; //17
    Иначе
    КонецГруппировки = нСтроки-1; //17
    КонецЕсли;
    //группируем
    Worksheet.Range("+НачалоГруппировки+":"+КонецГруппировки).Rows.Group();
    НачалоГруппировки = 0;
    КонецЕсли;
    КонецЕсли;
    НачалоГруппировки = нСтроки+1; //13
    //переходим на новую строку, т.к. в этой все остальные колонки - пустые
    нСтроки = нСтроки+1;
    КонецЕсли;
    КонецЕсли;
    ИначеЕсли ТЗ.Уровень = 3 Тогда
    //значит, "выше только небо (с)". Это Товар без группы, что нужно в 1с исключать
    //выводим СтрокуТаблицы
    КонецЕсли;
    //вывод строки таблицы
    СтрокаТаблицы();
```

Процедура СтрокаТаблица() описана в самом начале темы.
Постарался писать без ошибок, но, как всегда, мог и недосмотреть :)
---
zaraki, огромное спасибо за подсказку.