8.х Дерево значений: группировка по условию

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 8"", создана пользователем Hr0n, 26 мар 2010.

  1. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Есть док, нужно выгрузить его тч в дерево значений (в обработке), т.е. сформировать дерево запросом и разбить на дополнительные группировки по заданным условиям.
    Выгружаю ТЗ в дерево запросом, формирую группировки:
    Код:
    Дерево = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
    Выборка1 = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
    Пока Выборка1.Следующий() Цикл
    Выборка2 = Выборка1.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
    //заполняю верхний уровень
    Д1         = Дерево.Строки.Добавить();
    Пока Выборка2.Следующий() Цикл
    Если Д1.Строки.Количество() = 0  Тогда
    Д2 = Д1.Строки.Добавить();
    КонецЕсли;
    ВыборкаСтрок = Выборка2.Выбрать();
    Пока ВыборкаСтрок.Следующий() Цикл
    //формирую условия для создания 2 и 3 уровня группировки
    Если ...
    Если...
    СформироватьГруппировкиДерева("Нужная группа", Д1, Д2, ВыборкаСтрок, Строка.Документ);
    ИначеЕсли...
    СформироватьГруппировкиДерева("Другая группа", Д1, Д2, ВыборкаСтрок, Строка.Документ);
    КонецЕсли
    КонецЕсли
    КонецЦикла;
    КонецЦикла;
    
    // формирую группировки 2 и 3 уровня    
    Процедура СформироватьГруппировкиДерева(Группа, Д1, Д2, ВыборкаСтрок, Документ)
    Если Д2.КодТНВЭД <> Неопределено  И ВыборкаСтрок.ВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Обувь") Тогда
    Если Группа<>Д2.Группа Тогда
    Отбор = Новый Структура;
    Отбор.Вставить("Группа", Группа);
    Результат = Д1.Строки.НайтиСтроки(Отбор);
    // косяк! он живет тут. Создается дополнительная строка с такой же группой, хотя
    // группа уже существует. Родителя изменить невозможно.
    Если Результат.Количество() = 1 Тогда
    // Д2.Строки.Родитель = Результат[0]; // получаю нужную группу но сделать с ней ничего не могу, т.к. родитель доступен только для чтения.
    Д2 = Д1.Строки.Добавить();
    Д2.КодТНВЭД = ВыборкаСтрок.КодТНВЭД;
    Д2.Группа = Группа;
    Иначе
    Д2 = Д1.Строки.Добавить();
    Д2.КодТНВЭД = ВыборкаСтрок.КодТНВЭД;
    Д2.Группа = Группа;
    КонецЕсли;
    ИначеЕсли Д2.Группа = Неопределено Тогда
    Д2.КодТНВЭД = ВыборкаСтрок.КодТНВЭД;
    Д2.Группа = Группа;
    КонецЕсли;
    КонецЕсли;
    //заполняю строку 2 уровня
    Д3 = Д2.Строки.Добавить();
    //заполняю строку 3 уровня
    КонецПроцедуры
    
    
    
    Проблема в следующем: в случае, когда при переборе строк нужная группа уже существует (была создана в начале цикла), все равно приходится добавлять новую группу 2 уровня, т.к. поместить строку в другую группу нельзя, т.к. родитель доступен только для чтения.
    Что можно сделать, чтобы группировки формировались правильно?
    Пример результата который получаю:
    [​IMG]
    Заранее благодарю!
  2. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Запрос покажите, не очень понятно, зачем вручную перебор делать...
  3. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Код:
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    |    ПеремещениеТоваровТовары.Покупатель КАК Покупатель,
    |    ПеремещениеТоваровТовары.Номенклатура.КодТНВЭД КАК КодТНВЭД,
    |    ПеремещениеТоваровТовары.Группа,
    |    ПеремещениеТоваровТовары.Номенклатура,
    |    ПеремещениеТоваровТовары.МинРазмер,
    |    ПеремещениеТоваровТовары.МаксРазмер,
    |    ПеремещениеТоваровТовары.Номенклатура.Марка КАК Марка,
    |    ПеремещениеТоваровТовары.Номенклатура.Артикул КАК Артикул,
    |    ПеремещениеТоваровТовары.КолМест КАК КолМест,
    |    ПеремещениеТоваровТовары.Объем КАК Объем,
    |    ПеремещениеТоваровТовары.Количество КАК Количество,
    |    ПеремещениеТоваровТовары.Вес КАК Вес,
    |    ПеремещениеТоваровТовары.ЗаКуб КАК ЗаКуб,
    |    ПеремещениеТоваровТовары.ТП КАК ТП,
    |    ПеремещениеТоваровТовары.ЗаЕд КАК ЗаЕд,
    |    ПеремещениеТоваровТовары.Факт КАК Факт,
    |    ПеремещениеТоваровТовары.ЦенаИ КАК ЦенаИ,
    |    ПеремещениеТоваровТовары.СуммаО КАК СуммаО,
    |    ПеремещениеТоваровТовары.КолВУп КАК КолВУп,
    |    ПеремещениеТоваровТовары.ВесНетто КАК ВесНетто,
    |    ПеремещениеТоваровТовары.Ссылка КАК Докум,
    |    ПеремещениеТоваровТовары.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,
    |    ПеремещениеТоваровТовары.Номенклатура.КодТНВЭД.Родитель.Код КАК КодТНВЭДРодитель,
    |    ПеремещениеТоваровТовары.Номенклатура.Наименование КАК Наименование
    |ИЗ
    |    Документ.ПеремещениеТоваров.Товары КАК ПеремещениеТоваровТовары
    |ГДЕ
    |    ПеремещениеТоваровТовары.Ссылка = &Документ
    |
    |УПОРЯДОЧИТЬ ПО
    |    Покупатель,
    |    КодТНВЭДРодитель,
    |    КодТНВЭД,
    |    Наименование,
    |    Марка,
    |    Артикул
    |ИТОГИ
    |    СУММА(КолМест),
    |    СУММА(Объем),
    |    СУММА(Количество),
    |    СУММА(Вес),
    |    СРЕДНЕЕ(ЗаКуб),
    |    СУММА(ТП),
    |    СРЕДНЕЕ(ЗаЕд),
    |    СРЕДНЕЕ(Факт),
    |    СРЕДНЕЕ(ЦенаИ),
    |    СУММА(СуммаО),
    |    СУММА(КолВУп),
    |    СУММА(ВесНетто)
    |ПО
    |    Покупатель,
    |    КодТНВЭД";
    //Параметры запроса
    Запрос.УстановитьПараметр("Документ", Строка.Документ);// Документ ссылка: Перемещение товаров
    
    
    
    В ручную перебираю для того чтобы сформировать нужную мне группировку по условию
  4. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Храните в соответствии родителя по отбору.
    Т.е. создайте кэш групп, что бы не менять родителя, а присваивать его.
  5. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Можете подсказать, каким образом это можно сделать? Пример кода по созданию кэша и пример по присвоению родителя подчиненной строке?
    Заранее благодарен
  6. uza
    Offline

    uza 1С, VBA (EXCEL), VB (.NET + WEB)

    Регистрация:
    10 июл 2007
    Сообщения:
    1.845
    Симпатии:
    1
    Баллы:
    29
    Ну... например создаете таблицу значения
    +-----------------------------------------+--------------------------+
    | ЭлементСправочника (родитель) | КореньСправочника. |
    +-----------------------------------------+--------------------------+

    Пришел на вход "Вася" из группы "ИТшники" - прошлись по таблице значений (точнее попросили пройтись 1Ску, сказав ей тзКорниДерева.Найти(Вася.Родитель, "Элементы"),
    нашли запись "ИТишники" (или не нашли - ну тут наверное следует создавать новый узел, не забыв его закешировать в обозначенную таблицу)
    получили от туда "корень" ветки - добавили к корню (узлу)
    ветки строку.

    Визуализировали дерево - и все хорошо. И не важно что из группы ИТшники "Вася" пришел строк через 500 после "Коли" из той же группы "ИТшники".

    Ну примерно понятно?

    Есть и еще варианты - сотни их. Ести вариант и без кэширования, тупо каждый раз "оббегать" все дерево, ища нужный нам узел (но это чую дольше работать будет)
    эдак в разы, а то и на порядок (зависит от "разлапистости" дерева)

    P.S. Посмотрите в своем коде, чую много там пробелов или табов лишних - страница "расползлась"
  7. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Подождите, посмотрел на результат... А зачем вам менять родителя для группы?
    Вам надо изменить родителя для строки в группе, а лишнюю группу удалить!
  8. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Изменить родителя для группы - именно это я пытался сделать... Но как ни пытался, поле родитель недоступно для записи. Подскажите пожалуйста как это можно сделать?
  9. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Зачем Вам менять родителя ГРУППЫ, когда надо менять родителя СТРОКИ?
  10. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Извините, неправильно выразился. пытался изменить родителя СТРОКИ. Каким образом это можно сделать чтобы не было ошибок?
    Код:
    Если Группа<>Д2.Группа Тогда
    Отбор = Новый Структура;
    Отбор.Вставить("Группа", Группа);
    Результат = Д1.Строки.НайтиСтроки(Отбор);
    // косяк! он живет тут. Создается дополнительная строка с такой же группой, хотя
    // группа уже существует. Родителя изменить невозможно.
    Если Результат.Количество() = 1 Тогда
    Д2.Строки.Родитель = Результат[0].Строки.Родитель;
    
    Ошибка: поле не доступно для записи. Сильно подозреваю что делаю не правильно. Подскажите пожалуйста как будет правильно! :unsure:
  11. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Не парьтесь, а создайте новую строк в нужной группе, а эту удалите.
  12. TopicStarter Overlay
    Hr0n
    Offline

    Hr0n Опытный в 1С

    Регистрация:
    17 авг 2009
    Сообщения:
    353
    Симпатии:
    0
    Баллы:
    26
    Спасибо всем! Разобрался. назначил родителя для строки:
    Код:
    Отбор = Новый Структура;
    Отбор.Вставить("Группа", Группа);
    Результат = Д1.Строки.НайтиСтроки(Отбор);
    Если Результат.Количество() = 1 Тогда
    Д2 = Результат[0];
    Д2.КодТНВЭД = ВыборкаСтрок.КодТНВЭД;
    Д2.Группа = Группа;
    КонецЕсли;
    
    Теперь все работает как надо :)

Поделиться этой страницей