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