Имя: Пароль:
1C
1C 7.7
v7: Как отсортировать таблицу значений с группами?
0 OTMOPO3OK
 
27.09.13
19:22
Группы могут быть в любой колонке. Сначала должна идти группа, потом её потомки и т. д. Я написал сортировку по двум колонкам с использованием рекурсии, а дальше затык. Не могу удержать в памяти весь алгоритм универсальной сортировки по любому количеству колонок. Помогите.
1 Barmalei
 
27.09.13
19:45
а сколько всего колонок ?
2 OTMOPO3OK
 
27.09.13
19:45
(1) Сколько угодно может быть колонок, по которым нужно сортировать.
3 OTMOPO3OK
 
27.09.13
19:47
Процедура кк_СортироватьТаблицу(Таблица, Группировки)
    ТаблицаСРодителями = кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    
    ТаблицаСРодителями.НоваяКолонка("НомерСтроки_");
    
    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
        НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
        ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.НомерСтроки_ = ТаблицаСРодителями.НомерСтроки;
        Для К = 1 По К_Группировки Цикл
            С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
            ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
            Если кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    
    Колонки = кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая1 = кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая1, 1, 1);
    ТаблицаРезультирующая1.УдалитьСтроки();
    
    
    СтрокиУпорядоченные = кк_СоздатьСписок();
    кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировки.ПолучитьЗначение(1), , Колонки, К_Колонки, СтрокиУпорядоченные);
    кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировки.ПолучитьЗначение(1), ПолучитьПустоеЗначение("Справочник.Номенклатура"), Колонки, К_Колонки, СтрокиУпорядоченные);
        
    К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
    Для К = 1 По К_СтрокиУпорядоченные Цикл
        ТаблицаРезультирующая1.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(К), Колонка);
            ТаблицаРезультирующая1.УстановитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка, ЗначениеКолонки);
        КонецЦикла;
    КонецЦикла;
        
    
    ТаблицаРезультирующая2 = кк_СоздатьТаблицу();
    ТаблицаРезультирующая1.Выгрузить(ТаблицаРезультирующая2, 1, 1);
    ТаблицаРезультирующая2.УдалитьСтроки();
    
    ТаблицаВременная = кк_СоздатьТаблицу();
    ТаблицаРезультирующая1.Выгрузить(ТаблицаВременная, 1, 1);
    ТаблицаВременная.УдалитьСтроки();
    
    С_Группировка = Группировки.ПолучитьЗначение(1).Получить("Имя");
    ТаблицаРезультирующая1.ВыбратьСтроки();
    Пока ТаблицаРезультирующая1.ПолучитьСтроку() = 1 Цикл
        ЗначениеГруппировки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, С_Группировка);
        Если ТаблицаВременная.КоличествоСтрок() = 0 Тогда
            ТаблицаВременная.НоваяСтрока();
            Для К = 1 По К_Колонки Цикл
                Колонка = Колонки.ПолучитьЗначение(К);
                ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
            КонецЦикла;
        Иначе
            ТекущееЗначениеГруппировки = ТаблицаВременная.ПолучитьЗначение(1, С_Группировка);
            Если ЗначениеГруппировки = ТекущееЗначениеГруппировки Тогда
                ТаблицаВременная.НоваяСтрока();
                Для К = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(К);
                    ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                    ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            Иначе
                СтрокиУпорядоченные2 = кк_СоздатьСписок();
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), , Колонки, К_Колонки, СтрокиУпорядоченные2);
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), ПолучитьПустоеЗначение("Справочник.Контрагенты"), Колонки, К_Колонки, СтрокиУпорядоченные2);
                
                К_СтрокиУпорядоченные2 = СтрокиУпорядоченные2.РазмерСписка();
                Для К = 1 По К_СтрокиУпорядоченные2 Цикл
                    ТаблицаРезультирующая2.НоваяСтрока();
                    Для Л = 1 По К_Колонки Цикл
                        Колонка = Колонки.ПолучитьЗначение(Л);
                        ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные2.ПолучитьЗначение(К), Колонка);
                        ТаблицаРезультирующая2.УстановитьЗначение(ТаблицаРезультирующая2.НомерСтроки, Колонка, ЗначениеКолонки);
                    КонецЦикла;
                КонецЦикла;
                
                ТаблицаВременная.УдалитьСтроки();
                ТаблицаВременная.НоваяСтрока();
                Для К = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(К);
                    ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                    ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    СтрокиУпорядоченные2 = кк_СоздатьСписок();
    кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), , Колонки, К_Колонки, СтрокиУпорядоченные2);
    кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), ПолучитьПустоеЗначение("Справочник.Контрагенты"), Колонки, К_Колонки, СтрокиУпорядоченные2);

    К_СтрокиУпорядоченные2 = СтрокиУпорядоченные2.РазмерСписка();
    Для К = 1 По К_СтрокиУпорядоченные2 Цикл
        ТаблицаРезультирующая2.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные2.ПолучитьЗначение(К), Колонка);
            ТаблицаРезультирующая2.УстановитьЗначение(ТаблицаРезультирующая2.НомерСтроки, Колонка, ЗначениеКолонки);
        КонецЦикла;
    КонецЦикла;
    
    Таблица = ТаблицаРезультирующая2;
КонецПроцедуры // кк_СортироватьТаблицу(Таблица, Группировки)
4 Barmalei
 
27.09.13
19:48
это значит содержимое одной колонки никак не связано с содержимым другой.  тогда можно использовать 1 алгоритм для 1 колонки в цикле на все колонки ?
5 OTMOPO3OK
 
27.09.13
19:48
Из этой портянки видно, что сортировка работает только по двум колонкам. Естественно, что это не универсально и вообще не красиво. Но я наверное уже выдохся и не вижу.
6 Рэйв
 
27.09.13
19:49
реально мешает банер рекламы.
Асмоди....Это все реально отвлекает.
7 OTMOPO3OK
 
27.09.13
19:50
(4) Ну в целом да, но вот как?
8 OTMOPO3OK
 
27.09.13
19:52
Понятно, что должен быть цикл по колонкам, но я не вижу его, глаз замылился, наверное.
9 OTMOPO3OK
 
27.09.13
19:53
Процедура кк_СортироватьТаблицуПоГруппировке(Таблица, Группировка, ЗначениеРодителя, Колонки, К_Колонки, СтрокиУпорядоченные)
    ТаблицаПромежуточная = кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаПромежуточная);
    
    Значения = кк_СоздатьСписок();
    С_Группировка = Группировка.Получить("Имя");
    Значения.ДобавитьЗначение(ЗначениеРодителя, С_Группировка + "_Родитель");
    кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная, кк_ПреобразоватьСтрокуВСписок(С_Группировка + "_Родитель"), Значения);
    
    
    ТаблицаПромежуточная.Сортировать(С_Группировка);
    
    ТаблицаПромежуточная.ВыбратьСтроки();
    Пока ТаблицаПромежуточная.ПолучитьСтроку() = 1 Цикл
        СтрокиУпорядоченные.ДобавитьЗначение(ТаблицаПромежуточная.НомерСтроки_);
        ЗначениеГруппировки = ТаблицаПромежуточная.ПолучитьЗначение(ТаблицаПромежуточная.НомерСтроки, С_Группировка);
        Если кк_ТипЗначения(ЗначениеГруппировки) <> 0 Тогда
            Если ЗначениеГруппировки.ЭтоГруппа() = 1 Тогда
                кк_СортироватьТаблицуПоГруппировке(Таблица, Группировка, ЗначениеГруппировки, Колонки, К_Колонки, СтрокиУпорядоченные);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры // кк_СортироватьТаблицуПоГруппировке(Таблица, Группировка, ЗначениеРодителя, Колонки, К_Колонки, СтрокиУпорядоченные)
10 Barmalei
 
27.09.13
19:53
по идее так будет в самом начале

Для А=1 По ТЗ.КоличествоКолонок() Цикл
  тут делаем сортировку по 1 колонке
КонецЦикла;
11 OTMOPO3OK
 
27.09.13
19:55
(10) Вот сортировка по первой колонке:

    ТаблицаРезультирующая1 = кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая1, 1, 1);
    ТаблицаРезультирующая1.УдалитьСтроки();
    
    
    СтрокиУпорядоченные = кк_СоздатьСписок();
    кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировки.ПолучитьЗначение(1), , Колонки, К_Колонки, СтрокиУпорядоченные);
    кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировки.ПолучитьЗначение(1), ПолучитьПустоеЗначение("Справочник.Номенклатура"), Колонки, К_Колонки, СтрокиУпорядоченные);
        
    К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
    Для К = 1 По К_СтрокиУпорядоченные Цикл
        ТаблицаРезультирующая1.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(К), Колонка);
            ТаблицаРезультирующая1.УстановитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка, ЗначениеКолонки);
        КонецЦикла;
    КонецЦикла;
12 OTMOPO3OK
 
27.09.13
19:55
(10) А вот по второй:

    ТаблицаРезультирующая2 = кк_СоздатьТаблицу();
    ТаблицаРезультирующая1.Выгрузить(ТаблицаРезультирующая2, 1, 1);
    ТаблицаРезультирующая2.УдалитьСтроки();
    
    ТаблицаВременная = кк_СоздатьТаблицу();
    ТаблицаРезультирующая1.Выгрузить(ТаблицаВременная, 1, 1);
    ТаблицаВременная.УдалитьСтроки();
    
    С_Группировка = Группировки.ПолучитьЗначение(1).Получить("Имя");
    ТаблицаРезультирующая1.ВыбратьСтроки();
    Пока ТаблицаРезультирующая1.ПолучитьСтроку() = 1 Цикл
        ЗначениеГруппировки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, С_Группировка);
        Если ТаблицаВременная.КоличествоСтрок() = 0 Тогда
            ТаблицаВременная.НоваяСтрока();
            Для К = 1 По К_Колонки Цикл
                Колонка = Колонки.ПолучитьЗначение(К);
                ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
            КонецЦикла;
        Иначе
            ТекущееЗначениеГруппировки = ТаблицаВременная.ПолучитьЗначение(1, С_Группировка);
            Если ЗначениеГруппировки = ТекущееЗначениеГруппировки Тогда
                ТаблицаВременная.НоваяСтрока();
                Для К = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(К);
                    ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                    ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            Иначе
                СтрокиУпорядоченные2 = кк_СоздатьСписок();
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), , Колонки, К_Колонки, СтрокиУпорядоченные2);
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), ПолучитьПустоеЗначение("Справочник.Контрагенты"), Колонки, К_Колонки, СтрокиУпорядоченные2);
                
                К_СтрокиУпорядоченные2 = СтрокиУпорядоченные2.РазмерСписка();
                Для К = 1 По К_СтрокиУпорядоченные2 Цикл
                    ТаблицаРезультирующая2.НоваяСтрока();
                    Для Л = 1 По К_Колонки Цикл
                        Колонка = Колонки.ПолучитьЗначение(Л);
                        ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные2.ПолучитьЗначение(К), Колонка);
                        ТаблицаРезультирующая2.УстановитьЗначение(ТаблицаРезультирующая2.НомерСтроки, Колонка, ЗначениеКолонки);
                    КонецЦикла;
                КонецЦикла;
                
                ТаблицаВременная.УдалитьСтроки();
                ТаблицаВременная.НоваяСтрока();
                Для К = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(К);
                    ЗначениеКолонки = ТаблицаРезультирующая1.ПолучитьЗначение(ТаблицаРезультирующая1.НомерСтроки, Колонка);
                    ТаблицаВременная.УстановитьЗначение(ТаблицаВременная.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    СтрокиУпорядоченные2 = кк_СоздатьСписок();
    кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), , Колонки, К_Колонки, СтрокиУпорядоченные2);
    кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировки.ПолучитьЗначение(2), ПолучитьПустоеЗначение("Справочник.Контрагенты"), Колонки, К_Колонки, СтрокиУпорядоченные2);

    К_СтрокиУпорядоченные2 = СтрокиУпорядоченные2.РазмерСписка();
    Для К = 1 По К_СтрокиУпорядоченные2 Цикл
        ТаблицаРезультирующая2.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные2.ПолучитьЗначение(К), Колонка);
            ТаблицаРезультирующая2.УстановитьЗначение(ТаблицаРезультирующая2.НомерСтроки, Колонка, ЗначениеКолонки);
        КонецЦикла;
    КонецЦикла;
13 OTMOPO3OK
 
27.09.13
19:58
По третьей колонке сортировка будет выглядеть ещё ужаснее. Нужно увидеть во всём этом универсальный алгоритм. Я его не вижу.
14 Barmalei
 
27.09.13
20:00
так выходит есть связь 1 и 2 колонки ?

иначе все просто было бы
Для А=1 По ТЗ.КоличествоКолонок() Цикл
  сортировка по колонке
КонецЦикла;
15 КонецЦикла
 
27.09.13
20:01
Где потом используешь эту сортировку?
Вот перед использованием и сортируй по нужным колонкам ТЗ, потом потомки
Вот пример рекурсивного вызова для ИТЗ, добавит просто сортировку в вывод группировок
http://1c911.by/stati_1s/statya-uskoryaem-otchety-ubiraya-nenuzhnye-zaprosy.htm
16 OTMOPO3OK
 
27.09.13
20:16
(14) Связь только в том, что сортировать, конечно же, нужно с учётом предыдущих колонок.
(15) Использую непосредственно перед подсчётом итогов по группировкам (и группам), который ещё предстоит написать.

То, что по ссылке, мне пока совсем не подходит. Данные уже есть в таблице значений. Их просто нужно отсортировать.
17 OTMOPO3OK
 
27.09.13
20:38
А, ладно, сейчас блок-схему буду рисовать. Всем спасибо.
18 NS
 
27.09.13
20:45
новаяколонка,, заполняешь полным наименованием - .полноенаименование(), и сортируешь по ней.
19 OTMOPO3OK
 
27.09.13
21:23
(18) Полное наименование выдает строку вида "родитель/потомок". А в наименовании элемента справочника может использоваться символ слэша. И поэтому такая сортировка может быть неправильной. Ну, это если конечно я ничего не путаю.
20 NS
 
27.09.13
21:54
(19) это все легко обходится.
21 OTMOPO3OK
 
27.09.13
22:01
(20) Как?
22 NS
 
27.09.13
22:11
(21) написанием своей простенькой функции получения полного наименования, где в качестве разделителя например используется симв(1)
23 КонецЦикла
 
27.09.13
22:27
(16) Ну дык... ИТЗ сама подсчитает итоги по группировкам
Зачем мучать анальное отверстие?
24 GStiv
 
27.09.13
22:48
А если привязать дополнительно Уровень() дполнительно в колонке
25 Попытка1С
 
27.09.13
22:59
(23) +1
26 OTMOPO3OK
 
27.09.13
23:51
Меня немного смущает лицензия, по которой распространяется  icpp.

Но конечно я рассмотрю и этот вариант. Всем спасибо.
27 OTMOPO3OK
 
29.09.13
01:24
Вот, написал. Примерно так это выглядит:

Процедура кк_СортироватьТаблицу(Таблица, Группировки)
    ТаблицаСРодителями = кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.НоваяКолонка("НомерСтроки_");
    
    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
        НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
        ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.НомерСтроки_ = ТаблицаСРодителями.НомерСтроки;
        Для К = 1 По К_Группировки Цикл
            С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
            ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
            Если кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    К_ТаблицаСРодителями = ТаблицаСРодителями.КоличествоСтрок();
    
    Колонки = кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();

    ТаблицаВременная = кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаВременная, 1, 1);
    ТаблицаВременная.УдалитьСтроки();

    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        Группировка = Группировки.ПолучитьЗначение(К);
        Если К = 1 Тогда
            СтрокиУпорядоченные = кк_СоздатьСписок();
            кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
            кк_СортироватьТаблицуПоГруппировке(ТаблицаСРодителями, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
                
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Л = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для М = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(М);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Л), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.НомерСтроки_ = ТаблицаСРодителями.НомерСтроки;
            КонецЦикла;
        Иначе
            Группировки2 = кк_СоздатьСписок();
            Для Л = 1 По К - 1 Цикл
                Группировки2.ДобавитьЗначение(Группировки.ПолучитьЗначение(Л));
            КонецЦикла;
            
            СтрокиУпорядоченные = кк_СоздатьСписок();
            М = 1;
            Пока М <= К_ТаблицаСРодителями Цикл
                ТаблицаСРодителями.Выгрузить(ТаблицаВременная);
                Значения = кк_Значения(ТаблицаСРодителями, М, Группировки2);
                
                кк_ОтфильтроватьТаблицу(ТаблицаВременная, Группировки2, Значения);
                
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
                кк_СортироватьТаблицуПоГруппировке(ТаблицаВременная, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
                
                К_ТаблицаВременная = ТаблицаВременная.КоличествоСтрок();
                М = М + К_ТаблицаВременная - 1;
                
                ТаблицаВременная.УдалитьСтроки();
                
                М = М + 1;
            КонецЦикла;
            
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Н = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для О = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(О);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Н), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.НомерСтроки_ = ТаблицаСРодителями.НомерСтроки;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
    Таблица = ТаблицаСРодителями;
КонецПроцедуры // кк_СортироватьТаблицу(Таблица, Группировки)
28 ADirks
 
30.09.13
07:55
(26) ага, придут авторы, и потребуют все исходники! кошмаррр!
:))
29 OTMOPO3OK
 
30.09.13
11:08
(28) О, привет. Ты ж создатель индексированной таблицы. Как в ней искать неопределённое значение? Создал индекс из трёх колонок. Но в ключе последнее значение должно быть неопределённым. А в список значений неопределённое значение невозможно засунуть.

И вот я сижу и думаю, если создать индекс из двух первых колонок, то будет ли "НайтиСтроку" позиционироваться точно на строку ИТЗ с неопределённым значением третьей колонки, не участвующей в индексе? Но что-то мне сдаётся, что не обязательно будет так.
30 ADirks
 
30.09.13
11:15
(29) а не пробовал
сзКлюч = СоздатьОбъект("СписокЗначений");
сзКлюч.РазмерСписка(3);
сзКлюч.УстановитьЗначение(1, );
сзКлюч.УстановитьЗначение(2, );

вроде должно пройти
31 aka AMIGO
 
30.09.13
11:15
можно и я вылезу со своим вариантом? :)

как-то давно тому делал такую сортировку
для этого создал еще одну колонку, записал в неё ПолныеКоды товаров из соотв.колонки, да по ним и отсортировал.
32 OTMOPO3OK
 
30.09.13
11:22
(30) Не работает. РазмерСписка только возвращает размер списка. Но я всё равно попробовал и вот: "Слишком много параметров передано при вызове функции/процедуры объекта".
33 Mikeware
 
30.09.13
11:25
Используй ИНдексированнуюТаблицу, и не взрывай мозг...
34 OTMOPO3OK
 
30.09.13
11:27
(31) Если сможешь ответить на вопрос из (29), то прямо сейчас перепишу на ИТЗ.
35 Mikeware
 
30.09.13
11:30
(29) А зачем искать неопределенное? Может, добавить пустое значение?
36 ADirks
 
30.09.13
11:31
(32) точно, гоню ...
единственный вариант - воспользоваться тем фактом, что неопределенные значения всегда первые в сортировке.
примерно так, хотя конечно изврат

    ит.ДобавитьИндекс("и1", "-к1, к2");
    сзКлюч = СоздатьОбъект("СписокЗначений");
    сзКлюч.ДобавитьЗначение(2);
    ит.Подмножество(сзКлюч, 1, "и1");
    ит.ВыбратьСтроки("и1");
    Пока ит.ПолучитьСтроку("и1") = 1 Цикл
        Если ит.к2 = Неопределено Тогда
            Сообщить(""+ит.к1+", "+ит.к2);
        КонецЕсли;
    КонецЦикла;
37 OTMOPO3OK
 
30.09.13
11:37
(35) Пустое значение занято для пустого элемента. Они у меня есть. А неопределённые в строках с группировками.
(36) Да, только вот так получается. А сейчас с обычными ТЗ я сначала делаю индексную строку из внутренних представлений и уже её ищу. В любом случае этот вариант с ИТЗ будет быстрее, чем мой?
38 ADirks
 
30.09.13
11:44
(37) Насчет быстрее - необязательно. Такая сортировка с иерархией - это куча обращений к базе, что сводит на нет все другие оптимизации.
Но он может оказаться понятнее - и это немаловажно. А может и не оказаться :)
39 OTMOPO3OK
 
30.09.13
11:44
Я почему спрашиваю. Потому что процедуру сбора итогов про группам справочника я ещё не сделал, и мне кажется, что это будет сложно. Вот думаю теперь, что будет проще: либо её своими силами написать или на ИТЗ сделать (ведь в этом случае, многое придётся переписывать). Учитывая, что мне только это и осталось. Планировалось, что оптимизацией и ускорением я займусь потом, когда всё будет работать.
40 Mikeware
 
30.09.13
11:47
(39) похожен, что надо начинать с постановки задачи...
41 OTMOPO3OK
 
30.09.13
11:47
(31) Этот вариант мне не нравится, теоретически коды могут быть не уникальны. Такое конечно редко бывает, но тем не менее. Вариант с полным наименованием мне тоже не нравится. Теоретически в наименовании может быть любой символ, который можно было бы использовать как разделитель. Вы все конечно можете подумать, что выдумываю лишнее, но я люблю, чтобы было всё максимально однозначно.
42 Mikeware
 
30.09.13
11:48
(39) Ты хочешь сделать что-то типа сводной экзеля/олап-куба?
43 ADirks
 
30.09.13
11:48
(39) Если ты возьмёшь ИТ.Группировать() - то оптимизацией и ускорением ты не сможешь заняться :)
Всё, что ты можешь сделать это:
"При группировке возможно также подсчитывать суммы по группам справочников - для этого в списке модификаторов индекса нужно указать '&'. Если в таблице есть колонка с именем '<ИмяКолонкиСправочника>_Родитель', то родитель для элемента будет браться из этой колонки - это уменьшает количество обращений к базе, и заметно увеличивает производительность."
44 Mikeware
 
30.09.13
11:48
(41) собирай в щепочку иды(внуртенние коды)
45 OTMOPO3OK
 
30.09.13
11:59
(42) Да не, всего лишь маленькая библиотека для создания простеньких кросс-отчётов.
(43) Спасибо, с этим я ещё не разобрался.
(41) Мне нужно в перспективе, чтобы группы и элементы можно было отсортировать в алфавитном порядке или в обратном. Сделать это с использованием внутренних идентификаторов будет проблематично, мне кажется. Да это и не важно сейчас. Но тем не менее спасибо за участие.
46 Chum
 
30.09.13
12:02
Весь текст не читал, но:
1. Что мешает ТС использовать дерево, т.е. таблицы в таблицах?
2. Что мешает ТС, если не применять п.1, то добавить сортирующие колонки, например: уровень, родитель?

имхо дерево решает все задачи, а там хоть засортируйся.
47 OTMOPO3OK
 
30.09.13
12:06
(46) Наверное, ничто не мешает. Просто я не задумывался об этом. Спасибо, ваш комментарий ценен для меня. Я подумаю.
48 Mikeware
 
30.09.13
12:10
(45)1. Используй нормальные инструменты, и будет тебе счастье.
например, такое: http://s020.radikal.ru/i719/1309/c0/610202e75e28.jpg
3. думаю, что не так уж проблематично - вторым ключевым полем первые буквы наименований.
(46) если я правильно понял задачу, ему неизвестен первоначально порядок столбцов сортировок.
49 OTMOPO3OK
 
30.09.13
12:32
(48) Ух ты, выглядит прикольно. Спасибо.
50 Mikeware
 
30.09.13
12:39
(49)Это то, что хотел?
тогда юзай QryConsole.
51 Simod
 
30.09.13
12:52
Заготовка:

Запрос = СоздатьОбъект("Запрос");

ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|ТекущийЭлемент = Справочник.Номенклатура.ТекущийЭлемент;
|Группировка ТекущийЭлемент;
|"
;

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

ТЗ.НоваяКолонка("СортНоменклатура", "Число", 10, 0);

Счетчик = 0;

Пока Запрос.Группировка(1) = 1 Цикл
    Счетчик = Счетчик + 1;
    НомСтроки = "";
    Если ТЗ.НайтиЗначение(Запрос.ТекущийЭлемент, НомСтроки, "Номенклатура") = 1 Тогда
        ТЗ.УстановитьЗначение(НомСтроки, "СортНоменклатура", Счетчик);
    КонецЕсли;
КонецЦикла;

ТЗ.Сортировать("СортНоменклатура");
52 OTMOPO3OK
 
30.09.13
13:06
(50) Спасибо. Я тут подумал, что qryConsole конечно полезная вещь, я её обязательно изучу. Но сейчас уже многое сделано. Библиотечку эту я ж не просто так пишу, а для отчёта, который не спешно ваяю. Пожалуй, его я по старинке докончу.
(51) Ваш комментарий тоже ценен для меня. Изучу всесторенне.
53 Mikeware
 
30.09.13
13:46
(51) С квериконсолью "неспешнописуемый" отчет не будет иметь никакого смысла (кроме разве что учебной цели). Быстрее сделать на консоли.
хотя - каждый ССЗБ.
54 OTMOPO3OK
 
30.09.13
17:29
(53) С одной стороны хочется, конечно, изучить что-то новое, удобное, красивое. Но для этого опять придётся стопятьсот часов с красными глазами просидеть. Спрашивается, нужно ли это сейчас, когда семёрка уже устарела?
55 Mikeware
 
30.09.13
17:33
(54) да там, собственно, и изучать нефиг...
всяко меньше времени надо, чтоб написать  "универсальную библиотечку"
56 Evrepid
 
30.09.13
18:38
Н да.... Один краше другого советы дают.
57 КонецЦикла
 
30.09.13
18:43
Добавился пример переделанного отчета

1c911.by/sites/default/files/user//files/primer_itz.rar
58 ADirks
 
30.09.13
18:50
(57) Всё-таки наиболее дельный совет - от Майка. Надо кубики, значит берём кубики, зачем мудрить.
59 КонецЦикла
 
30.09.13
18:56
А я нечетал честно говоря
Как правило нужен готовый отчет с минимумом настроек, как в макдаке (так любят некоторые руководители говорить)
60 Serginio1
 
30.09.13
18:59
Посмотри http://1c.proclub.ru/modules/mydownloads/personal.php?cid=115&lid=2019

там есть группировка и вывод по группам
61 Злопчинский
 
30.09.13
19:02
(48) у, елы-палы, а это у тебя что за интересный такой объект используется..?
62 Mikeware
 
30.09.13
19:34
(61) квериконсоль, и вывод в ПивотТэйбл
63 OTMOPO3OK
 
30.09.13
19:50
Я с ИТЗ ещё не до конца разобрался, чего уж говорить про квериконсоль. Это надолго. Что ещё к этому всему добавить, если я только вчера догадался прикрутить gcomp чтобы он автоматически распаковывал обработку при сохранении, а до этого пару лет вручную текст модуля в файлик копировал, чтобы исходник нормально в git засовывать?
64 ADirks
 
30.09.13
19:54
Да забей ты на ИТ, тебе же другое нужно, ну вот правда же
65 ADirks
 
30.09.13
20:01
Разберись с тем, про что Майк говорил, ну нафига велосипед заново конструировать? Лучше то не будет. И быстрее не будет.
66 OTMOPO3OK
 
30.09.13
20:10
(65) Да я пытаюсь… Там просто много чего для меня нового.
67 ADirks
 
30.09.13
20:13
Нормальное положение программиста, ничего страшного. Это же оч.шорошо, что много нового.
68 Злопчинский
 
30.09.13
20:57
я вот вообще к мысли пришел. что не в 1с счастье... когда утрясутся все бури житейские - буду сидеть на голой пенсии, пить кисель да на солнце смотреть...
69 OTMOPO3OK
 
07.10.13
13:16
Выяснилось, что первоначальный вариант был ошибочный. Этот вроде рабочий. Единственное, что меня смущает — производительность. Вы наверное заметили в цикле по строкам таблицы выгрузку всей таблицы и фильтрацию всей таблицы:

Процедура _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
    ТаблицаСРодителями = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.НоваяКолонка(_кк_СТР_НОМЕР_СТРОКИ);
    
    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        Если Группировки.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
            С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
        Для К = 1 По К_Группировки Цикл
            Если Группировки.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
                С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    К_ТаблицаСРодителями = ТаблицаСРодителями.КоличествоСтрок();
    
    Колонки = _кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();

    ТаблицаВременная = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаВременная, 1, 1);
    ТаблицаВременная.УдалитьСтроки();

    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        Группировка = Группировки.ПолучитьЗначение(К);
        Если К = 1 Тогда
            СтрокиУпорядоченные = _кк_СоздатьСписок();
            _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаСРодителями, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
            Если Группировка.Получить("СГруппами") = 1 Тогда
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаСРодителями, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
            КонецЕсли;
                
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Л = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для М = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(М);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Л), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
            КонецЦикла;
        Иначе
            Группировки2 = _кк_СоздатьСписок();
            Для Л = 1 По К - 1 Цикл
                Группировки2.ДобавитьЗначение(Группировки.ПолучитьЗначение(Л));
            КонецЦикла;
            
            СтрокиУпорядоченные = _кк_СоздатьСписок();
            М = 1;
            Пока М <= К_ТаблицаСРодителями Цикл
                ТаблицаСРодителями.Выгрузить(ТаблицаВременная);
                Значения = _кк_Значения(ТаблицаСРодителями, М, Группировки2);
                
                _кк_ОтфильтроватьТаблицу(ТаблицаВременная, Группировки2, Значения);
                
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаВременная, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
                Если Группировка.Получить("СГруппами") = 1 Тогда
                    _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаВременная, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
                КонецЕсли;
                
                К_ТаблицаВременная = ТаблицаВременная.КоличествоСтрок();
                М = М + К_ТаблицаВременная - 1;
                
                ТаблицаВременная.УдалитьСтроки();
                
                М = М + 1;
            КонецЦикла;
            
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Н = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для О = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(О);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Н), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
    Таблица = ТаблицаСРодителями;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
70 OTMOPO3OK
 
07.10.13
13:19
Делал замеры. Этот метод выполняется 70% всего времени в отчёте за один день. Конечно это никуда не годится. Если же запустить отчёт за весь год, то думаю, он займёт 95% времени.
71 Mikeware
 
07.10.13
13:30
(69) "вы, наверное, заметили" - наивный, ну кому нафик твой код сдался? :-)
72 OTMOPO3OK
 
07.10.13
14:10
(71) Мне сдался. Я люблю свой код. Он для меня как четвёртый ребёнок.
73 ZaOS
 
07.10.13
17:34
74 ZaOS
 
07.10.13
17:34
vc
75 monsterZE
 
07.10.13
18:03
Я ваще не понял чего хотел тс.. =) Ты хоть бы на примере что-ли объяснил.
76 Mikeware
 
07.10.13
18:27
(75) сводную таблицу с итогом по группам.
задачка, вообще-то , давно решена нормальными способами, но ТС хочет изобрести скоростной трехколесный велосипед со взаимно ортогональными колесами разного диаметра, и цепной передачей от педалей к рулю... Почти изобрел, но жалуется на скорость...
77 Salimbek
 
07.10.13
19:36
(0) Используй Индексированную таблицу.
Использование типа:
Процедура ОбработатьГруппировку(вхИТЗ, Колонка)
вхИТЗ.Группировать(Колонка,,1);
вхИТЗ.ВыбратьСтроки(Колонка);
Пока вхИТЗ.ПолучитьСтроку(Колонка)=1 Цикл
ВложеннаяИТЗ = вхИТЗ.ТЗПотомки;
СледующаяКолонка = ПолучитьСледующуюКолонкуДляСортировки();
ОбработатьГруппировку(ВложеннаяИТЗ, СледующаяКолонка);
КонецЦикла;
КонецПроцедуры
78 OTMOPO3OK
 
07.10.13
20:20
(76) Ты мне скажи, что плохого в том, что я изобретаю велосипед? Сейчас я понимаю, что всё уже давно изобретено. Но это всё ещё нужно запустить, а оно у меня пока не взлетает. Имею в виду твой метод с квериконсолью и пивоттэйблом.

А ты ведь наверняка знаешь, какого это — долгое время не видеть результатов своего труда, когда ты готов почти на любые костыли и подпорки, чтобы только хоть как-нибудь заработало.

Велосипед уже готов. Он медленно едет, но его, я уверен, можно ускорить. И я понимаю, что возможно мне не следовало его писать, что нужно было чуть подольше погуглить, найти твой метод и начать сразу с него. Но что уж теперь, выкидывать? Это был бы ещё более глупый поступок.

Спасибо за ценную информацию о квериконсоли и т. д., но твои причитания мне уже наскучили.
79 monsterZE
 
07.10.13
22:31
я делал прайс с подсчетом колва элементов в группах и с разбегом цен от мин до макс.. без ИТЗ =) завтра свой трехколесный пригоню ;-)
80 monsterZE
 
08.10.13
10:29
81 monsterZE
 
08.10.13
10:30
82 Salimbek
 
08.10.13
10:37
(81) У тебя развернут только один вид справочника. ТС же нужно несколько разновидностей разворачивать. Т.е. первый вид, допустим справочник магазинов с группами в виде регионов, второй вид: номенклатура, третий - еще какой-то вид справочников.
83 Mikeware
 
08.10.13
10:46
(78) плохо то, что он, этот велосипед, бесполезный - ни тебе опыта, ни людям решения.
84 iamnub
 
08.10.13
10:48
(0)
А откуда ты взял свою ТЗ? Может быть решить твою проблему раньше?
85 OTMOPO3OK
 
09.10.13
13:08
Прошу прощения. В (69) код неправильный. Неправильно сортирует по второй и последующим колонкам. Ну и конечно очень медленный.

(83) Ну а вдруг я потом на bitbucket.com открою репозиторий. Хоть кому-нибудь может пригодиться для тривиальных вещей. Вероятность ненулевая.

(84) Я ещё не думал над оптимизацией запроса и последующей обработкой его результата. Возможно, удастся избавиться от лишних этапов. Так-то запрос вроде по некоторым колонкам возвращает то, что мне нужно, но потом я в таблицу добавляю ещё несколько группировок. А новые строки с итогами по по этим группировкам добавляю в конец таблицы, а потом её сортирую. По идее было бы неплохо подумать над тем, чтобы не сортировать таблицу из запроса, а вставлять новые строки прямо в правильные места. Но это уже потом. В любом случае сейчас я хочу это доделать всё-таки. Пригодится это или нет мне или кому-нибудь неважно. Просто хочу доделать.
86 Salimbek
 
09.10.13
13:13
(85) А можешь хоть словами описать, что у тебя в развороте первой иерархии, что во второй, что в третьей?
87 Mikeware
 
09.10.13
13:14
(86) секс ради секса.
88 OTMOPO3OK
 
09.10.13
13:22
(85) В первой справочник «Номенклатура», во второй «Контрагенты», в третьей тупо строка. Да это и неважно в сущности, что у меня там. Какая вообще разница? Там что угодно может быть.

(87) Секс ради удовольствия. Мне нравится, когда что-то получается, пусть даже это на твой взгляд чепуха. Я вот когда это сделаю (а осталось немного), тогда уже буду думать, потратил я время зря или нет, и в будущем возможно освою твой мегасуперметод с квериконсолью.
89 Mikeware
 
09.10.13
13:29
(88) твой метод требует очень много лишних сил и движений.
по сути, ты пытаешьс сделать предпросчитанный куб. Т.е. то, что делает, скажем, ms analysis services.
Средствами 1с - это долго и нерационально, и до конца (с разумной мерностью, и за вменяемое время) сделано не будет.
90 OTMOPO3OK
 
09.10.13
13:48
(89) Так я же пишу простенькую библиотеку. Для простых случаев с относительно небольшим количеством измерений вполне подойдёт. Конечно, если удастся что-то сделать со скоростью.

Вот я честно пытался твой метод использовать. Запустил пример, и он у меня не заработал. Прописал внутри загрузку 1CPP.dll, он заработал, но выдал ошибку, связанную vfoxsqlprovider. Скачал, установил, запустил, получил ошибку, связанную с metainfoчто-то. Поэтому я погрустнел и отложил до лучших времён.
91 uno-group
 
09.10.13
13:59
Все не читал но на вскидку создаем дубли всех колонок которые подлежат сортировке и в них пишем полный код и сортируем
по этим колонкам.
92 OTMOPO3OK
 
09.10.13
19:23
Опять же прошу прощения. Код в (69) правильный. Разве что процедура _кк_ОтфильтроватьТаблицу некорректно работала, но её код я не приводил. А всё дело в том, что после очередного рефакторинга этой процедуры, она регрессировала.

Без юнит-тестирования очень плохо, оказывается. (89) Видишь, какой прогресс. Благодаря этой задаче я освоил несколько вещей, полезных для разработки, даже если сама эта задача бессмысленна. А вот сейчас об юнит-тестировании в 1С задумался.
93 ADirks
 
10.10.13
08:14
(92) http://1c.alterplast.ru/functest/index.html
Как пример практического применения можно скачать исходники 1С++ - там база юнит-тестов немаленькая.
94 OTMOPO3OK
 
10.10.13
13:48
(93) Спасибо за полезную информацию.
95 OTMOPO3OK
 
11.10.13
03:48
Как смог, улучшил быстродействие. Что-то мне подсказывает, что можно ещё лучше, но на первых порах и так сойдёт:

Процедура _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
    ТаблицаСРодителями = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.НоваяКолонка(_кк_СТР_НОМЕР_СТРОКИ);
    
    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        Если Группировки.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
            С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
        Для К = 1 По К_Группировки Цикл
            Если Группировки.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
                С_Группировка = Группировки.ПолучитьЗначение(К).Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    К_ТаблицаСРодителями = ТаблицаСРодителями.КоличествоСтрок();
    
    Колонки = _кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();

    ТаблицаВременная = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаВременная, 1, 1);
    ТаблицаВременная.УдалитьСтроки();

    К_Группировки = Группировки.РазмерСписка();
    Для К = 1 По К_Группировки Цикл
        Группировка = Группировки.ПолучитьЗначение(К);
        Если К = 1 Тогда
            СтрокиУпорядоченные = _кк_СоздатьСписок();
            _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаСРодителями, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
            Если Группировка.Получить("СГруппами") = 1 Тогда
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаСРодителями, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
            КонецЕсли;
                
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Л = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для М = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(М);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Л), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
            КонецЦикла;
        Иначе
            Группировки2 = _кк_СоздатьСписок();
            Для Л = 1 По К - 1 Цикл
                Группировки2.ДобавитьЗначение(Группировки.ПолучитьЗначение(Л));
            КонецЦикла;
            
            ПредыдущаяКолонка = Группировки.ПолучитьЗначение(К - 1).Получить("Имя");
            
            СтрокиУпорядоченные = _кк_СоздатьСписок();
            М = 1;
            Пока М <= К_ТаблицаСРодителями Цикл
                ЗначениеПредыдущейКолонки = ТаблицаСРодителями.ПолучитьЗначение(М, ПредыдущаяКолонка);
                Если _кк_ТипЗначения(ЗначениеПредыдущейКолонки) <> 0  Тогда
                    Если ЗначениеПредыдущейКолонки.ЭтоГруппа() = 0 Тогда
                        ТаблицаСРодителями.Выгрузить(ТаблицаВременная, М);
                        Значения = _кк_Значения(ТаблицаСРодителями, М, Группировки2);
                        
                        _кк_ОтфильтроватьТаблицу(ТаблицаВременная, Группировки2, Значения);
                        
                        _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаВременная, Группировка, , Колонки, К_Колонки, СтрокиУпорядоченные);
                        Если Группировка.Получить("СГруппами") = 1 Тогда
                            _кк_СортироватьТаблицуКроссТаблицыПоГруппировкеПоГруппе(ТаблицаВременная, Группировка, ПолучитьПустоеЗначение(Группировка.Получить("Тип")), Колонки, К_Колонки, СтрокиУпорядоченные);
                        КонецЕсли;
                        
                        К_ТаблицаВременная = ТаблицаВременная.КоличествоСтрок();
                        М = М + К_ТаблицаВременная - 1;
                        
                        ТаблицаВременная.УдалитьСтроки();
                    Иначе
                        СтрокиУпорядоченные.ДобавитьЗначение(ТаблицаСРодителями.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
                    КонецЕсли;
                Иначе
                    СтрокиУпорядоченные.ДобавитьЗначение(ТаблицаСРодителями.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
                КонецЕсли;
                
                М = М + 1;
            КонецЦикла;
            
            К_СтрокиУпорядоченные = СтрокиУпорядоченные.РазмерСписка();
            Для Н = 1 По К_СтрокиУпорядоченные Цикл
                ТаблицаРезультирующая.НоваяСтрока();
                Для О = 1 По К_Колонки Цикл
                    Колонка = Колонки.ПолучитьЗначение(О);
                    ЗначениеКолонки = ТаблицаСРодителями.ПолучитьЗначение(СтрокиУпорядоченные.ПолучитьЗначение(Н), Колонка);
                    ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, ЗначениеКолонки);
                КонецЦикла;
            КонецЦикла;
            
            ТаблицаРезультирующая.Выгрузить(ТаблицаСРодителями);
            ТаблицаРезультирующая.УдалитьСтроки();
            
            ТаблицаСРодителями.ВыбратьСтроки();
            Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
                ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
    Таблица = ТаблицаСРодителями;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
96 OTMOPO3OK
 
18.10.13
15:27
Товарищи, я тут решил улучшить эту сортировку. Сделал её (с одним примечанием: она пока не работает с неопределёнными значениями в случае, если группировка с группами) гораздо более красивой и логичной. Но у меня возникла небольшая проблема. 1С говорит: «Недостаточно свободной оперативной памяти на этом компьютере». Это было бы логично, учитывая, что здесь использована рекурсия, но в сортируемой таблице всего 2к с лишним строк и всего четыре группировки, из которых всего лишь две первые с группами, остальные плоские. Как освобождать память в 1С 7.7, кто знает? Вот сижу уже час думаю, а в голову ничего не приходит.

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать, Родитель, ГруппировкиПоКоторымСортировать, СписокНомеров)
    // Чтобы не испортить её, выгружаем таблицу с родителями в промежуточную таблицу
    ТаблицаПромежуточная = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаПромежуточная);
    
    С_ГруппировкаПоКоторойСортировать = ГруппировкаПоКоторойСортировать.Получить("Имя");
    
    // Если группировка с группами, отфильтровываем промежуточную таблицу по родителю
    Если ГруппировкаПоКоторойСортировать.Получить("СГруппами") = 1 Тогда
        Значения = _кк_СоздатьСписок();
        Значения.ДобавитьЗначение(Родитель, С_ГруппировкаПоКоторойСортировать + "_Родитель");
        _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать + "_Родитель"), Значения);
    КонецЕсли;
    
    // Сортируем промежуточную таблицу
    Список = _кк_СоздатьСписок();
    Список.ДобавитьЗначение(ГруппировкаПоКоторойСортировать);
    ТаблицаПромежуточная.Сортировать(_кк_ПреобразоватьСписокВСтроку(Список, , 1));
    
    // Перебираем промежуточную таблицу
    М = 1;
    К_ТаблицаПромежуточная = ТаблицаПромежуточная.КоличествоСтрок();
    Пока М <= К_ТаблицаПромежуточная Цикл
        З_Группировка = ТаблицаПромежуточная.ПолучитьЗначение(М, С_ГруппировкаПоКоторойСортировать);
        Если _кк_ТипЗначения(З_Группировка) <> 0 Тогда
            // Текущее значение группировки - не неопределённое значение
            Если _кк_ТипЗначения(З_Группировка) = 11 Тогда
                // Текущее значение группировки - элемент или группа справочника
                Если З_Группировка.ЭтоГруппа() = 0 Тогда
                    // Текущее значение группировки - элемент справочника
                    ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
                    ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
                    
                    Значения2 = _кк_СоздатьСписок();
                    Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
                    _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
                    
                    ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
                    
                    Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                        // Это не последняя группировка
                        ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                        ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);
                        
                        _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаПромежуточная2, ГруппировкаПоКоторойСортировать2,
                            ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать2.Получить("Тип")), ГруппировкиПоКоторымСортировать2, СписокНомеров);
                    Иначе
                        // Это последняя группировка
                        ТаблицаПромежуточная2.ВыбратьСтроки();
                        Пока ТаблицаПромежуточная2.ПолучитьСтроку() = 1 Цикл
                            СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(ТаблицаПромежуточная2.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ));
                        КонецЦикла;
                    КонецЕсли;
                    
                    К_ТаблицаПромежуточная2 = ТаблицаПромежуточная2.КоличествоСтрок();
                    М = М + К_ТаблицаПромежуточная2;
                Иначе
                    // Текущее значение группировки - группа справочника
                    СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
                    
                    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
                        З_Группировка, ГруппировкиПоКоторымСортировать, СписокНомеров);
                    
                    М = М + 1;
                КонецЕсли;
            Иначе
                // Текущее значение группировки - вообще ни элемент, ни группа справочника
                ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
                ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
                
                Значения2 = _кк_СоздатьСписок();
                Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
                _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
                
                ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
                
                Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                    ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                    ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);

                    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаПромежуточная2, ГруппировкаПоКоторойСортировать2,
                        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать2.Получить("Тип")), ГруппировкиПоКоторымСортировать2, СписокНомеров);
                Иначе
                    ТаблицаПромежуточная2.ВыбратьСтроки();
                    Пока ТаблицаПромежуточная2.ПолучитьСтроку() = 1 Цикл
                        СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(ТаблицаПромежуточная2.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ));
                    КонецЦикла;
                КонецЕсли;
                
                К_ТаблицаПромежуточная2 = ТаблицаПромежуточная2.КоличествоСтрок();
                М = М + К_ТаблицаПромежуточная2;
            КонецЕсли;
        Иначе
            // Текущее значение группировки - неопределённое значение
            СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
            
            М = М + 1;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать, Родитель, ГруппировкиПоКоторымСортировать, СписокНомеров)

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки) // todo Метод не универсальный. Подходит только для сортировки таблицы или
    // шапки кросс-таблицы
    ГруппировкиПоКоторымСортировать = _кк_СкопироватьСписок(Группировки);
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 0 По К_ГруппировкиПоКоторымСортировать - 1 Цикл
        Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        Если Группировка.Получить("Сортировать") = 0 Тогда
            ГруппировкиПоКоторымСортировать.УдалитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.НоваяКолонка(_кк_СТР_НОМЕР_СТРОКИ);
    
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
        Если ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
            С_Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
        Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
            Если ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
                С_Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    ГруппировкаПоКоторойСортировать = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(1);
    ГруппировкиПоКоторымСортировать.УдалитьЗначение(1);
    
    ТаблицаСРодителями.ВыбратьСтроку();
    Сообщить(ТаблицаСРодителями.КоличествоСтрок());
    
    СписокНомеров = _кк_СоздатьСписок();
    
    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать.Получить("Тип")), ГруппировкиПоКоторымСортировать, СписокНомеров);
        
    Колонки = _кк_Колонки(Таблица);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();
        
    К_СписокНомеров = СписокНомеров.РазмерСписка();
    Сообщить(К_СписокНомеров);
    Для К = 1 По К_СписокНомеров Цикл
        НомерСтроки = СписокНомеров.ПолучитьЗначение(К);
        ТаблицаРезультирующая.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            З_Колонка = Таблица.ПолучитьЗначение(НомерСтроки, Колонка);
            ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, З_Колонка);
        КонецЦикла;
    КонецЦикла;
    
    ТаблицаРезультирующая.ВыбратьСтроку();
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
97 OTMOPO3OK
 
18.10.13
15:30
Предполагается, что этот вариант должен работать гораздо быстрее предыдущего. Если бы не нехватка памяти. Чего её не хватает? Табличка ведь маленькая. Ну, в общем вот так.
98 OTMOPO3OK
 
18.10.13
16:37
А, пардон, товарищи, этот код работает, оказывается. Просто я для второй группировки с группами не включил настройку "СГруппами". Единственное, что теперь нужно, чтобы он с неопределёнными значениями работал. Ну, это дело техники.
99 OTMOPO3OK
 
18.10.13
22:51
Этот вариант работает в четыре раза быстрее на таблице в 2к строк, чем вариант в (95). И, предполагаю, во многие-многие разы быстрее на таблице в 20к строк. На том можно и успокоиться.

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать, Родитель, ГруппировкиПоКоторымСортировать, СписокНомеров) // todo
    // Чтобы не испортить её, выгружаем таблицу с родителями в промежуточную таблицу
    ТаблицаПромежуточная = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаПромежуточная);
    
    С_ГруппировкаПоКоторойСортировать = ГруппировкаПоКоторойСортировать.Получить("Имя");
    
    // Если группировка с группами, отфильтровываем промежуточную таблицу по родителю
    Если ГруппировкаПоКоторойСортировать.Получить("СГруппами") = 1 Тогда
        Значения = _кк_СоздатьСписок();
        Значения.ДобавитьЗначение(Родитель, С_ГруппировкаПоКоторойСортировать + "_Родитель");
        _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать + "_Родитель"), Значения);
    КонецЕсли;
    
    // Сортируем промежуточную таблицу
    Список = _кк_СоздатьСписок();
    Список.ДобавитьЗначение(ГруппировкаПоКоторойСортировать);
    ТаблицаПромежуточная.Сортировать(_кк_ПреобразоватьСписокВСтроку(Список, , 1));
    
    // Перебираем промежуточную таблицу
    М = 1;
    К_ТаблицаПромежуточная = ТаблицаПромежуточная.КоличествоСтрок();
    Пока М <= К_ТаблицаПромежуточная Цикл
        З_Группировка = ТаблицаПромежуточная.ПолучитьЗначение(М, С_ГруппировкаПоКоторойСортировать);
        Если _кк_ТипЗначения(З_Группировка) = 11 Тогда
            // Текущее значение группировки - элемент или группа справочника
            Если З_Группировка.ЭтоГруппа() = 0 Тогда
                // Текущее значение группировки - элемент справочника
                ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
                ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
                
                Значения2 = _кк_СоздатьСписок();
                Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
                _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
                
                ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
                Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                    // Это не последняя группировка
                    ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                    ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);
                    
                    Если ГруппировкаПоКоторойСортировать2.Получить("СГруппами") = 1 Тогда
                        ТаблицаПромежуточная2.Сортировать(ГруппировкаПоКоторойСортировать2.Получить("Имя"));
                        СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(1, _кк_СТР_НОМЕР_СТРОКИ));
                    КонецЕсли;
                    
                    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаПромежуточная2, ГруппировкаПоКоторойСортировать2,
                        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать2.Получить("Тип")), ГруппировкиПоКоторымСортировать2, СписокНомеров);
                Иначе
                    // Это последняя группировка
                    ТаблицаПромежуточная2.ВыбратьСтроки();
                    Пока ТаблицаПромежуточная2.ПолучитьСтроку() = 1 Цикл
                        СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(ТаблицаПромежуточная2.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ));
                    КонецЦикла;
                КонецЕсли;
                
                К_ТаблицаПромежуточная2 = ТаблицаПромежуточная2.КоличествоСтрок();
                М = М + К_ТаблицаПромежуточная2;
            Иначе
                // Текущее значение группировки - группа справочника
                СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
                
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
                    З_Группировка, ГруппировкиПоКоторымСортировать, СписокНомеров);
                
                М = М + 1;
            КонецЕсли;
        Иначе
            // Текущее значение группировки - вообще ни элемент, ни группа справочника
            ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
            ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
            
            Значения2 = _кк_СоздатьСписок();
            Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
            _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
            
            ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
            
            Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                // Это не последняя группировка
                ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);

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

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки) // todo Метод не универсальный. Подходит только для сортировки таблицы или
    // шапки кросс-таблицы
    ГруппировкиПоКоторымСортировать = _кк_СкопироватьСписок(Группировки);
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 0 По К_ГруппировкиПоКоторымСортировать - 1 Цикл
        Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        Если Группировка.Получить("Сортировать") = 0 Тогда
            ГруппировкиПоКоторымСортировать.УдалитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.НоваяКолонка(_кк_СТР_НОМЕР_СТРОКИ);
    
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
        Если ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
            С_Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
        Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
            Если ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("СГруппами") = 1 Тогда
                С_Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К).Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    ГруппировкаПоКоторойСортировать = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(1);
    ГруппировкиПоКоторымСортировать.УдалитьЗначение(1);
    
    СписокНомеров = _кк_СоздатьСписок();
    
    ТаблицаСРодителями2 = _кк_СоздатьТаблицу(); // todo Немного костыльный код
    ТаблицаСРодителями.Выгрузить(ТаблицаСРодителями2);
    ТаблицаСРодителями2.Сортировать(ГруппировкаПоКоторойСортировать.Получить("Имя"));
    СписокНомеров.ДобавитьЗначение(ТаблицаСРодителями2.ПолучитьЗначение(1, _кк_СТР_НОМЕР_СТРОКИ));
    
    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать.Получить("Тип")), ГруппировкиПоКоторымСортировать, СписокНомеров);
        
    Колонки = _кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();
        
    К_СписокНомеров = СписокНомеров.РазмерСписка();
    Для К = 1 По К_СписокНомеров Цикл
        НомерСтроки = СписокНомеров.ПолучитьЗначение(К);
        ТаблицаРезультирующая.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            З_Колонка = ТаблицаСРодителями.ПолучитьЗначение(НомерСтроки, Колонка);
            ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, З_Колонка);
            
            // А вот эта странная строка нужна для того, чтобы подсчёт итогов по группам работал так, как прежде
            ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаРезультирующая.НомерСтроки);
        КонецЦикла;
    КонецЦикла;
    
    Таблица = ТаблицаРезультирующая;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
100 PavelKompal
 
18.10.13
23:42
А кто-то реально вникает в горы кода, которым здесь сыпет ОТМОРОЗОК ??? Лично у меня не возникает ни малейшего желания вникать в эту кучу чужого кода ...
101 monsterZE
 
19.10.13
09:15
(100) смеешься? =) чего только одни названия функций стоят..
и конструкции вида

_кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
                        З_Группировка, ГруппировкиПоКоторымСортировать, СписокНомеров);

_кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать + "_Родитель"), Значения);
102 OTMOPO3OK
 
19.10.13
09:19
(100) Один человек уже вник или попытался вникнуть. Конструкции проанализировал.
(101) А что в них не так? Это неправильные с вашей точки зрения названия и конструкции, да?
103 monsterZE
 
19.10.13
09:25
(102) не знаю, я не вникал..
а есть пример таблицы на входе и что должно получиться на выходе? =)
104 OTMOPO3OK
 
19.10.13
09:49
(103) Есть таблица значений, в ней, положим, две колонки: номенклатура и контрагент, которые могут быть с группами. Ну и нужно её отсортировать произвольным образом, но при этом непосредственные потомки родителя должны следовать за ним. В общем так, ломает демонстрационный материл готовить.
105 monsterZE
 
19.10.13
09:59
я хз чего тебе там надо.. =)
но можно - добавить колонку с полным кодом и сортировать по ней, можно состряпать табличку элемент-родитель, выделить группы и элементы 1 уровня например и отсортировав по выделенному - вывести с иерархией. добавив еще пару колонок, можно собрать и количество элементов в группах и т.д..
106 Попытка1С
 
19.10.13
10:58
Тебе все еще в (15) написали а ты все трешь.
107 OTMOPO3OK
 
19.10.13
11:31
(105) Да всё уже это есть в (99).
(106) И продолжу это делать, если потребуется.
108 Mikeware
 
19.10.13
11:34
(107) и думаешь, что эта фигня кому-нибудь, кроме тебя, нужна и интересна? :-)
109 OTMOPO3OK
 
19.10.13
11:45
(108) Не важно, нужно ли это ещё кому-нибудь кроме меня. Мне нужно, и это главное. А если ты спрашиваешь, зачем я выкладываю это на форум, то я отвечу, что мне нравится, когда мой код критикуют. Это побуждает задуматься, иногда заставляет по-другому взглянуть на проблему и порой укрепляет в уверенности, что я делаю всё правильно.
110 OTMOPO3OK
 
22.10.13
17:32
Ёжик волосатый… Вдруг выяснилось, что код в (99) не всегда работает правильно. Борода. Хотя, казалось бы, чему там неправильно работать? Стоило только две первые колонки поменять местами и всё накрылось медным тазом. Подозреваю, косяк в группах.
111 Ёпрст
 
22.10.13
17:43
Всё не читал, а чего надо то в итоге ?
112 Ёпрст
 
22.10.13
17:47
прочитал..
Итоги погруппам нужны в кросс табличке ?
113 fisher
 
22.10.13
17:49
(0) Прям ностальгия... Была у меня на 7.7 рекурсивная процедурка, которая умела подбивать итоги в ТЗ, в т.ч. и по иерахии (исходная таблица без групп предполагалась). Очень актуально было для сложных универсальных отчетов.
114 OTMOPO3OK
 
22.10.13
17:49
(111) Итоги тоже нужны. Но сейчас главнее сортировка. Картинку сейчас сделаю. С ней будет яснее.
115 OTMOPO3OK
 
22.10.13
17:50
(113) Вот, что-то типа этого. Вернее даже точно это.
116 fisher
 
22.10.13
17:51
На восьмерке это уже неактуально :)
117 GreyK
 
22.10.13
17:53
(115) А чем "функция" в запросе не устраивает?
118 OTMOPO3OK
 
22.10.13
17:53
(116) Это общеизвестный факт. :)
119 OTMOPO3OK
 
22.10.13
17:54
Сейчас народ, картинку готовлю. Из неё должно быть всё ясно…
120 fisher
 
22.10.13
18:00
(115) Я там обходил ТЗ и втыкал строки с итогами по нужным группировкам. Т.е. как бы за один проход таблицы получалось это сделать. Для получения данных по иерархии, ессно приходилось сначала дополнительно в БД лезть. Но полученную информацию о группах я кэшировал, чтобы лишний раз не лазить.
А вот сортировку я юзал какую-то хитрую комбинированную, т.к. чистая сортировка по полному наименованию в каких-то хитрых случаях (с одинаковыми наименованиями групп, например) могла подводить.
121 GreyK
 
22.10.13
18:02
(119) Ты для начаоа просто ответь откуда ты берёшь данные для ТЗ по контрагентам и товарам.
122 OTMOPO3OK
 
22.10.13
18:09
Вот картинки:

Первая. Тут всё понятно:
https://www.evernote.com/shard/s6/sh/c3bfd635-c34f-4d66-b701-bceba4e034e6/61f753b35daff2b5df8ce35ec0715e9f?noteKey=61f753b35daff2b5df8ce35ec0715e9f¬eGuid=c3bfd635-c34f-4d66-b701-bceba4e034e6

Вторая. Её я в Экселе склеил. Так как макет для её формирования пока не готов. Но в целом тоже должно быть понятно:
https://www.evernote.com/shard/s6/sh/7cbe5f68-e956-48d4-992f-f0468e882ab7/7f068b1fa8659840e1fc06430194f53d?noteKey=7f068b1fa8659840e1fc06430194f53d¬eGuid=7cbe5f68-e956-48d4-992f-f0468e882ab7
123 OTMOPO3OK
 
22.10.13
18:11
(121) Данные как обычно берутся из запроса, перебрасываются в ТЗ и в ней крутятся-вертятся.
124 Mikeware
 
22.10.13
18:12
125 Mikeware
 
22.10.13
18:12
126 GreyK
 
22.10.13
18:15
(125) Зато сериал на две страницы :)
127 Mikeware
 
22.10.13
18:17
(126) "неуловимый джо".
зы.сериал с количеством дырок в дуршлаге (ну и "взлетит-невзлетит" )был веселее..
128 Ёпрст
 
22.10.13
18:17
Охрененть жешь..
Открываем типовоую торговлю, в ней - ведомость по партиям... имеем сабж на картинке..
Я то думал, действительно нужен разворот вправо, да еще и с итогами по группам вправо/вниз..
129 GreyK
 
22.10.13
18:21
(123) Ничего у тебя не вертится по ходу, всё берётся из документов или регистров.
    "//{{ЗАПРОС(Сформировать)
    |Контрик = Регистр.ОстаткиТоваров.Контрагент;
    |Товар = Регистр.ОстаткиТоваров.Товар;
    |Функция МоёЗначениеИзТЗ1 = Сумма(ПолучитьЗначениеИзТЗ1(Товар));
    |Группировка Документ;
    |Группировка Товар;
    |"//}}ЗАПРОС
130 GreyK
 
22.10.13
18:22
+(129)
   |Функция МоёЗначениеИзТЗ1 = Сумма(ПолучитьЗначениеИзТЗ1(Контрик,Товар));
131 ADirks
 
22.10.13
18:23
(122) лучше-б ты картинок не рисовал, ей богу...
132 OTMOPO3OK
 
22.10.13
18:30
Смеётесь надо мной…
133 OTMOPO3OK
 
22.10.13
18:34
Я понимаю, что отчёт похож на Ведомость по партиям, и я её даже смотрел. Там запрос сразу обходится и выводится в табличный документ без дополнительной обработки (насколько я могу судить). А мне такое не подходит. У меня справа от тех колонок ещё тыщамиллионов колонок, группировок, просто на картинках они не показаны.
134 OTMOPO3OK
 
22.10.13
18:39
Разворот вправо, короче говоря, есть, и итоги по вертикальным группировкам, но для цели этого топика (сортировка по колонкам с учётом групп) они не важны. Забудьте обо всём, кроме того, что нужно таблицу отсортировать. Откуда берутся данные, тоже не важно. Если бы всё это можно было сделать (или если бы это представлялось мне лёгким, простым делом) запросом, то я бы так не парился.
135 GreyK
 
22.10.13
18:40
(132) Не то слово.
(133) Так кто тебе мешает использовать внешнюю функцию с передачей параметров в запросе!? И группировки будут, и значения будут из ТЗ переданны в твой запрос.
136 OTMOPO3OK
 
22.10.13
18:42
(135) А вот это можно рассмотреть. Я думал о том, что запрос можно было бы улучшить. Я собирался этим заняться, когда всё будет хоть как-нибудь стабильно работать. Дело возможно в том, что я не очень силён в запросах 1С 7.7. Внешнюю функцию, говоришь… интересно…
137 OTMOPO3OK
 
22.10.13
18:50
(135) А, вижу, ты написал в (129).

А можно ли вот так примерно:

|Контрик = Регистр.ОстаткиТоваров.Контрагент;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Функция Чтото = ПолучитьЧтото(Чтотодругое);
|Группировка Документ;
|Группировка Товар;
|Группировка Чтото;

По-моему, насколько я помню, вряд ли.
138 GreyK
 
22.10.13
18:55
(137) Нее... ни так. Примерно так:
|Функция Чтото = Сумма(ПолучитьЧтото(Контрик,Товар));
"Контрик" и "товар" определяются в запросе и передаются из запроса во внешнию функцию, итоги по группировкам считаются фукцией "Сумма".
139 OTMOPO3OK
 
22.10.13
19:06
(138) Так функция "сумма" ж сумму чего-то возвращает. А мне не число нужно, а ну, например, строка. И вот по ней нужно ещё и группировку зафигачить. А сейчас эту группировку я в таблице значений создаю.

Проблема в том, что создав эту группировку, изначальная сортировка (из результата выполнения запроса) в этой таблице нарушается, поэтому главным образом и потребовалось потом ещё эту ТЗ сортировать вот таким образом.

Но даже если бы удалось сделать так, чтобы при создании группировки в ТЗ не нарушался изначальный порядок, мне всё равно хотелось бы этот метод для сортировки доделать. Зря что ли я на него тыщумиллионов часов убил…

Возможно зря, я это понимаю, но всё равно хотелось бы доделать. Осталось-то чуть-чуть.
140 OTMOPO3OK
 
24.10.13
21:57
С трудом, но починил. Но возникла одна маленькая проблема: если передвинуть группировку "Партия" перед группировками "Номенклатура" и "Поставщик", то подсчёт итогов занимает в сто раз больше времени, чем при более естественном порядке ("Номенклатура", "Поставщик", "Партия"). Впрочем, методы для подсчёта итогов здесь не показаны. С другой стороны, для целей отчёта нет нужды ставить группировку "Партия" первой, но всё же немного грустно.

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать, Родитель, ГруппировкиПоКоторымСортировать, СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке) // todo
    С_ГруппировкаПоКоторойСортировать = ГруппировкаПоКоторойСортировать.Получить("Имя");
    
    ТаблицаСРодителями.Сортировать(С_ГруппировкаПоКоторойСортировать);
    Если _кк_ТипЗначения(ТаблицаСРодителями.ПолучитьЗначение(1, С_ГруппировкаПоКоторойСортировать)) = 0 Тогда
        СписокНомеров.ДобавитьЗначение(ТаблицаСРодителями.ПолучитьЗначение(1, _кк_СТР_НОМЕР_СТРОКИ));
        ТаблицаСРодителями.УдалитьСтроку(1);
        УдаленаИтоговаяСтрокаПоВерхнейГруппировке = 1;
    КонецЕсли;
    
    ТаблицаПромежуточная = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаПромежуточная);
    
    // Если группировка с группами, отфильтровываем промежуточную таблицу по родителю
    Если ГруппировкаПоКоторойСортировать.Получить("СГруппами") = 1 Тогда
        Значения = _кк_СоздатьСписок();
        Значения.ДобавитьЗначение(Родитель, С_ГруппировкаПоКоторойСортировать + "_Родитель");
        _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать + "_Родитель"), Значения);
    КонецЕсли;
    
    // Сортируем промежуточную таблицу // todo Костыль
    Список = _кк_СоздатьСписок();
    Список.ДобавитьЗначение(ГруппировкаПоКоторойСортировать);
    СтрокаДляСортировки = _кк_ПреобразоватьСписокВСтроку(Список, , 1);
    Если ГруппировкаПоКоторойСортировать.Получить("СсылочныйТип") = 1 Тогда
        СтрокаДляСортировки = СтрокаДляСортировки + ", " + С_ГруппировкаПоКоторойСортировать + "_ДляСортировкиПоВнутреннемуПредставлению *";
    КонецЕсли;
    ТаблицаПромежуточная.Сортировать(СтрокаДляСортировки); // todo
    
    // Перебираем промежуточную таблицу
    М = 1;
    К_ТаблицаПромежуточная = ТаблицаПромежуточная.КоличествоСтрок();
    Пока М <= К_ТаблицаПромежуточная Цикл
        З_Группировка = ТаблицаПромежуточная.ПолучитьЗначение(М, С_ГруппировкаПоКоторойСортировать);
        Если _кк_ТипЗначения(З_Группировка) = 11 Тогда
            // Текущее значение группировки - элемент или группа справочника
            Если З_Группировка.ЭтоГруппа() = 0 Тогда
                // Текущее значение группировки - элемент справочника
                ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
                ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
                
                Значения2 = _кк_СоздатьСписок();
                Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
                _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
                
                ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
                Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                    // Это не последняя группировка
                    ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                    ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);
                    
                    УдаленаИтоговаяСтрокаПоВерхнейГруппировке2 = 0;
                    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаПромежуточная2, ГруппировкаПоКоторойСортировать2,
                        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать2.Получить("Тип")), ГруппировкиПоКоторымСортировать2,
                        СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке2);
                Иначе
                    // Это последняя группировка
                    ТаблицаПромежуточная2.ВыбратьСтроки();
                    Пока ТаблицаПромежуточная2.ПолучитьСтроку() = 1 Цикл
                        СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(ТаблицаПромежуточная2.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ));
                    КонецЦикла;
                КонецЕсли;
                
                К_ТаблицаПромежуточная2 = ТаблицаПромежуточная2.КоличествоСтрок();
                М = М + К_ТаблицаПромежуточная2 + УдаленаИтоговаяСтрокаПоВерхнейГруппировке2;
            Иначе
                // Текущее значение группировки - группа справочника
                СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная.ПолучитьЗначение(М, _кк_СТР_НОМЕР_СТРОКИ));
                
                УдаленаИтоговаяСтрокаПоВерхнейГруппировке2 = 0;
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать,
                    З_Группировка, ГруппировкиПоКоторымСортировать, СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке2);
                
                М = М + 1;
            КонецЕсли;
        Иначе
            // Текущее значение группировки - вообще ни элемент, ни группа справочника
            ТаблицаПромежуточная2 = _кк_СоздатьТаблицу();
            ТаблицаПромежуточная.Выгрузить(ТаблицаПромежуточная2, М);
            
            Значения2 = _кк_СоздатьСписок();
            Значения2.ДобавитьЗначение(З_Группировка, С_ГруппировкаПоКоторойСортировать);
            _кк_ОтфильтроватьТаблицу(ТаблицаПромежуточная2, _кк_ПреобразоватьСтрокуВСписок(С_ГруппировкаПоКоторойСортировать), Значения2);
            
            ГруппировкиПоКоторымСортировать2 = _кк_СкопироватьСписок(ГруппировкиПоКоторымСортировать);
            
            Если ГруппировкиПоКоторымСортировать2.РазмерСписка() >= 1 Тогда
                // Это не последняя группировка
                ГруппировкаПоКоторойСортировать2 = ГруппировкиПоКоторымСортировать2.ПолучитьЗначение(1);
                ГруппировкиПоКоторымСортировать2.УдалитьЗначение(1);
                
                УдаленаИтоговаяСтрокаПоВерхнейГруппировке2 = 0;
                _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаПромежуточная2, ГруппировкаПоКоторойСортировать2,
                    ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать2.Получить("Тип")), ГруппировкиПоКоторымСортировать2,
                    СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке2);
            Иначе
                // Это последняя группировка
                ТаблицаПромежуточная2.ВыбратьСтроки();
                Пока ТаблицаПромежуточная2.ПолучитьСтроку() = 1 Цикл
                    СписокНомеров.ДобавитьЗначение(ТаблицаПромежуточная2.ПолучитьЗначение(ТаблицаПромежуточная2.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ));
                КонецЦикла;
            КонецЕсли;
            
            К_ТаблицаПромежуточная2 = ТаблицаПромежуточная2.КоличествоСтрок();
            М = М + К_ТаблицаПромежуточная2 + УдаленаИтоговаяСтрокаПоВерхнейГруппировке2;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями, ГруппировкаПоКоторойСортировать, Родитель, ГруппировкиПоКоторымСортировать, СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке)

////////////////////////////////////////////////////////////////////////////////
Процедура _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки) // todo Метод не универсальный. Подходит только для сортировки таблицы или
    // шапки кросс-таблицы
    ГруппировкиПоКоторымСортировать = _кк_СкопироватьСписок(Группировки);
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 0 По К_ГруппировкиПоКоторымСортировать - 1 Цикл
        Группировка = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        Если Группировка.Получить("Сортировать") = 0 Тогда
            ГруппировкиПоКоторымСортировать.УдалитьЗначение(К_ГруппировкиПоКоторымСортировать - К);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями = _кк_СоздатьТаблицу();
    Таблица.Выгрузить(ТаблицаСРодителями);
    
    ТаблицаСРодителями.ВставитьКолонку(_кк_СТР_НОМЕР_СТРОКИ, 1);
    
    К_ГруппировкиПоКоторымСортировать = ГруппировкиПоКоторымСортировать.РазмерСписка();
    Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
        ГруппировкаПоКоторойСортировать = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К);
        Если ГруппировкаПоКоторойСортировать.Получить("СГруппами") = 1 Тогда
            С_Группировка = ГруппировкаПоКоторойСортировать.Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_Родитель", НомерКолонки + 1);
        КонецЕсли;
        Если ГруппировкаПоКоторойСортировать.Получить("СсылочныйТип") = 1 Тогда
            С_Группировка = ГруппировкаПоКоторойСортировать.Получить("Имя");
            НомерКолонки = ТаблицаСРодителями.ПолучитьПараметрыКолонки(С_Группировка);
            ТаблицаСРодителями.ВставитьКолонку(С_Группировка + "_ДляСортировкиПоВнутреннемуПредставлению", НомерКолонки + 1);
        КонецЕсли;
    КонецЦикла;
    
    ТаблицаСРодителями.ВыбратьСтроки();
    Пока ТаблицаСРодителями.ПолучитьСтроку() = 1 Цикл
        ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаСРодителями.НомерСтроки);
        Для К = 1 По К_ГруппировкиПоКоторымСортировать Цикл
            ГруппировкаПоКоторойСортировать = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(К);
            Если ГруппировкаПоКоторойСортировать.Получить("СГруппами") = 1 Тогда
                С_Группировка = ГруппировкаПоКоторойСортировать.Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_Родитель", ЗначениеГруппировки.Родитель);
                КонецЕсли;
            КонецЕсли;
            Если ГруппировкаПоКоторойСортировать.Получить("СсылочныйТип") = 1 Тогда
                С_Группировка = ГруппировкаПоКоторойСортировать.Получить("Имя");
                ЗначениеГруппировки = ТаблицаСРодителями.ПолучитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка);
                Если _кк_ТипЗначения(ЗначениеГруппировки) = 11 Тогда
                    ТаблицаСРодителями.УстановитьЗначение(ТаблицаСРодителями.НомерСтроки, С_Группировка + "_ДляСортировкиПоВнутреннемуПредставлению", ЗначениеГруппировки);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    ГруппировкаПоКоторойСортировать = ГруппировкиПоКоторымСортировать.ПолучитьЗначение(1);
    ГруппировкиПоКоторымСортировать.УдалитьЗначение(1);
    
    СписокНомеров = _кк_СоздатьСписок();
    
    ТаблицаСРодителями2 = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаСРодителями2);
    УдаленаИтоговаяСтрокаПоВерхнейГруппировке = 0;
    _кк_СортироватьТаблицуКроссТаблицыПоГруппировке(ТаблицаСРодителями2, ГруппировкаПоКоторойСортировать,
        ПолучитьПустоеЗначение(ГруппировкаПоКоторойСортировать.Получить("Тип")), ГруппировкиПоКоторымСортировать,
        СписокНомеров, УдаленаИтоговаяСтрокаПоВерхнейГруппировке);
        
    Колонки = _кк_Колонки(ТаблицаСРодителями);
    К_Колонки = Колонки.РазмерСписка();
    
    ТаблицаРезультирующая = _кк_СоздатьТаблицу();
    ТаблицаСРодителями.Выгрузить(ТаблицаРезультирующая, 1, 1);
    ТаблицаРезультирующая.УдалитьСтроки();
        
    К_СписокНомеров = СписокНомеров.РазмерСписка();
    Для К = 1 По К_СписокНомеров Цикл
        НомерСтроки = СписокНомеров.ПолучитьЗначение(К);
        
        ТаблицаРезультирующая.НоваяСтрока();
        Для Л = 1 По К_Колонки Цикл
            Колонка = Колонки.ПолучитьЗначение(Л);
            З_Колонка = ТаблицаСРодителями.ПолучитьЗначение(НомерСтроки, Колонка);
            ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, Колонка, З_Колонка);
        КонецЦикла;
        
        // А вот эта странная строка нужна для того, чтобы подсчёт итогов по группам работал так, как прежде
        ТаблицаРезультирующая.УстановитьЗначение(ТаблицаРезультирующая.НомерСтроки, _кк_СТР_НОМЕР_СТРОКИ, ТаблицаРезультирующая.НомерСтроки);
    КонецЦикла;
    
    Таблица = ТаблицаРезультирующая;
КонецПроцедуры // _кк_СортироватьТаблицуКроссТаблицы(Таблица, Группировки)
141 OTMOPO3OK
 
30.10.13
21:27
Отчёт написал. Убил много времени. Взглянул и что я вижу? Это ведь обычная Ведомость по партиям ТМЦ, только развёрнутая вправо по видам движения и месяцам, ну, и ещё вес считает и может все ресурсы сразу выводить. Только вот, падла, медленная, тормознутая, если за весь год запустить, то можно сходить попить чаю, потом сходить пос рать успеть, посмотреть серию ТББТ, потом покурить и снова пос рать. Удобства из типовой ведомости к нему можно прикрутить, ну, то есть фильтры и прочее, только вот надо ли, хороший вопрос.

Кажется, у меня развивается депрессия. :(
143 КонецЦикла
 
30.10.13
21:56
(141) omg
чо эта было?
ничего из топика не помогло?
144 OTMOPO3OK
 
30.10.13
22:22
(143) Да не, советы были полезны. Только он (отчёт) медленный как го вно мамонта на пологом склоне.

И ещё удручает, что выручить за него я, если и смогу, то несоизмеримо мало по сравнению с усилиями на его создание.

Плюс к тому же я, кажется, только что нашёл в нём ошибку. Её я конечно найду и пофиксю. А что делать? Хоть что-то же за это нужно получить.

В общем писать сколько-нибудь сложные отчёты для пары заказчиков не выгодно. Вот что я понял из всего этого. Нужно делать что-нибудь тиражное.
145 GreyK
 
30.10.13
23:05
(144) Накопленный опыт дорогого стоит.
А вообще-то отчетик не сложный :)
146 OTMOPO3OK
 
30.10.13
23:39
(145) Так-то да, не сложный сам по себе. Я имел в виду делать разворот вбок было не совсем просто для меня. Показывать не буду, а-то я тут выкладывал скрины, все смеялись.
147 ADirks
 
31.10.13
08:25
Ничо, ещё пару десятков таких нарисуешь, глядишь и научишься.
148 OTMOPO3OK
 
31.10.13
08:47
(147) Тебе спасибо за ИТЗ. А нельзя ли как-нибудь так сделать, чтобы в ИТЗ можно было искать неопределённые значения как в обычной ТЗ? Или всё уже, проект не развивается? А если бы она была ещё полностью совместимой с ТЗ, то вообще было бы замечательно.
149 ADirks
 
31.10.13
08:55
Со значениями типа Неопределенный есть прикольная фишка - эти значения не запихнёшь в СЗ, например. Думали уже на эту тему, пришли к выводу, что не стоит оно того.
150 OTMOPO3OK
 
31.10.13
09:17
(149) Что-то припоминаю, там ж вроде методу Найти скармливается индекс и список со значениями колонок индекса. То есть, действительно, передать неопределённое значение при такой конструкции затруднительно. А если, например, сделать один метод, типа "УстановитьЗначениеКолонкиФильтра", в который передвать индекс, номер колонки фильтра и значение колонки фильтра, которое может быть неопределённым?
151 OTMOPO3OK
 
31.10.13
09:49
(149) Хотя что я спрашиваю… Наверняка такой вариант тоже обсуждался.
152 ADirks
 
31.10.13
09:56
обсуждался :)
решили, что вред от иррегулярности интерфейса перевесит обретаемый функционал
153 Shaman100M
 
31.10.13
10:37
Не все читал в ветке. Вот это не подойдет?
http://infostart.ru/public/14710/
154 slowpoke1C
 
31.10.13
11:27
К (0). А встроенный метод "Свернуть" не предлагать?

Свернуть(<ГруппКолонки>,<СуммКолонки>)

Ась?
155 slowpoke1C
 
31.10.13
11:35
На (141) Товарищ OTMOPO3OK! Вам надо курить встроенный объект "Запрос"! Оно само группирует в любом измерении, и даже сортирует!
156 OTMOPO3OK
 
01.11.13
14:16
(153) Да, примерно такое. Только вот там в первом комментарии сказано, что в этой штуке глюк с группировками, а автор не отписался, исправил он эту ошибку или нет. В целом неплохо. Посмотрю, если его решение быстрее моего, то возьму без стеснения. Лицензия вроде бы свободная.

А, это ж ты автор. Ты исправил глюк из первого комментария?
157 OTMOPO3OK
 
01.11.13
14:43
(152) Что ты имеешь в виду под "иррегулярностью интерфейса"? Тот факт, что в ТЗ можно искать неопределённые значения, а в ИТЗ это невозможно без геморроя не совсем удобно. Почему ИТЗ настолько не совместима с ТЗ, кстати? Вот например в ТЗ строку для сортировки можно задавать в виде "Колонка *", а в ИТЗ такое не прокатит, для неё нужно обязательно писать "*Колонка". Я ничего против не имею, просто в данной ситуации невозможно легко заюзать ИТЗ вместо ТЗ в существующих проектах.
158 ADirks
 
01.11.13
14:53
(157) про иррегулярность: специально для неопределенных значений пришлось бы как-то менять интерфейс, причём это было бы дублирование существующего. Два способа сделать что-то - это плохо (в данном случае).

про совместимость с ТЗ: это невозможно в принципе - ибо принципиально разный функционал. Более того, я уж сто раз пожалел, что некоторые методы ИТ похожи на методы ТЗ - постоянно возникает куча вопросов, из-за того что от внешнего сходства ждут схожих результатов.

про *: это ты что-то путаешь, если мне память не изменяет, то можно писать хоть "Кол*онка".
159 fisher
 
01.11.13
14:56
Держи привет из 2004-го. За работоспособность не ручаюсь, давно это было :)

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

Ну, если ты утверждаешь, что сделать ИТЗ обратно совместимой с ТЗ невозможно, то тебе, наверное, виднее.

Вероятно, ты прав. Тогда видимо дело в пробеле между модификатором и наименованием колонки.