В версии 7.40 в ABAP появилась возможность группировать данные в цикле и обрабатывать эти группы. Группировка в цикле ABAP не только уменьшает количество строк кода, но и улучшает производительность. Здесь на примере разберу варианты использования этой новой конструкции языка ABAP.
Группировка в цикле ABAP GROUP BY
В этой статье на примере задачи по суммированию в цикле и выделению промежуточных итогов разберём использование дополнения LOOP GROUP BY. Задача состоит в группировке:
- По сбытовым организациям и заводам
- По материалам
- Так же было требование выводить и подробные записи без группировки. Поэтому нельзя было организовать группировку раньше, например на уровне базы данных.
Суммирование в цикле ABAP.
На примере подробно разберу каждую строку кода по суммированию в цикле с использованием группировки ABAP и в конце статьи приведу весь код целиком для удобства копирования.
Цикл по основной таблице где начинаем разбивать записи по группам для дальнейшей обработки в подчинённом цикле:
1 2 3 |
LOOP AT lt_data INTO DATA(ls_data) "1" GROUP BY ( vkorg = ls_data-vkorg werks = ls_data-werks ) "2" REFERENCE INTO DATA(group_ref_werks). "3" |
“1” – DATA(ls_data) – динамически определяем структуру.
“2” – Задаём поля, по которым хотим сгруппировать записи таблицы.
“3” – group_ref_werks – Динамически определяем переменную в которую по очереди будут помещаться группы записей с одинаковыми ключевыми полями.
Поочерёдно в этом цикле обходим группы записей сгруппированных по заводам с использованием подчинённого цикла:
1 2 3 4 |
CLEAR ls_grp_werks. LOOP AT GROUP group_ref_werks INTO DATA(ls_werks) "4" GROUP BY ( matnr = ls_werks-matnr ) "5" REFERENCE INTO DATA(group_ref). "6" |
“4” – Используя конструкцию LOOP GROUP пройдём по выделенной группе записей group_ref_werks.
“5” – Здесь можем обработать группу цикла и не группировать, но нам нужна дополнительная группировка ещё и по материалу.
“6” – Помещаем подгруппу уже по новому ключу состоящему не из двух полей, как на уровне выше, а из трёх.
Обрабатываем записи в цикле с двойной группировкой по трём полям, производим суммирование и другие необходимые операции:
1 2 3 4 5 6 7 |
LOOP AT GROUP group_ref REFERENCE INTO DATA(lr_tab)."7" IF ls_matnr IS INITIAL. "8" MOVE-CORRESPONDING lr_tab->* TO ls_matnr. ELSE. ls_matnr-menge = ls_matnr-menge + lr_tab->menge. ENDIF. ENDLOOP. "9" |
“7” – Обрабатываем группу полученную выше и суммируем значения всех записей находящихся в ней.
“8” – Если это первая строка, из группы, то копируем значения.
“9” – Выйдя из этого цикла обработана вся первая группа с одинаковым набором трёх полей.
1 2 3 4 5 |
ls_matnr-menge_fr = ls_matnr-menge_to - ls_matnr-menge_r."10" CLEAR ls_val. MOVE-CORRESPONDING ls_matnr TO ls_val."11" ls_class-menge = ls_grp_class-menge + ls_matnr-menge."12" ENDLOOP."13" |
“10” – После этого можно произвести расчёт зависимых от суммированных полей.
“11” – Сохраняем полученную запись суммы в структуру результата для дальнейшего использование.
“12” – Далее суммируем значения уже для внешнего цикла который проходит по уникальным значениям внешней группировки.
“13” – После выхода из цикла так же обрабатываем необходимым образом поля сумм.
1 2 3 4 |
CLEAR ls_val. MOVE-CORRESPONDING ls_grp_class TO ls_val. APPEND ls_val TO lt_result."14" ENDLOOP. |
“14” – И сохраняем данные по этому проходу цикла в итоговую таблицу.
Закрывается головной цикл и по итогу мы получили результаты суммирования в нескольких разрезах. Полный код и текст комментариев ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
LOOP AT lt_data INTO DATA(ls_data) "1" GROUP BY ( vkorg = ls_data-vkorg werks = ls_data-werks ) "2" REFERENCE INTO DATA(group_ref_werks). "3" CLEAR ls_grp_werks. LOOP AT GROUP group_ref_werks INTO DATA(ls_werks) "4" GROUP BY ( matnr = ls_werks-matnr ) "5" REFERENCE INTO DATA(group_ref). "6" LOOP AT GROUP group_ref REFERENCE INTO DATA(lr_tab)."7" IF ls_matnr IS INITIAL. "8" MOVE-CORRESPONDING lr_tab->* TO ls_matnr. ELSE. ls_matnr-menge = ls_matnr-menge + lr_tab->menge. ENDIF. ENDLOOP. "9" ls_matnr-menge_fr = ls_matnr-menge_to - ls_matnr-menge_r."10" CLEAR ls_val. MOVE-CORRESPONDING ls_matnr TO ls_val."11" ls_class-menge = ls_grp_class-menge + ls_matnr-menge."12" ENDLOOP."13" CLEAR ls_val. MOVE-CORRESPONDING ls_grp_class TO ls_val. APPEND ls_val TO lt_result."14" ENDLOOP. |
Итоговый код программы ABAP по группировке в цикле с комментариями
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
LOOP AT lt_data INTO DATA(ls_data) "1" GROUP BY ( vkorg = ls_data-vkorg werks = ls_data-werks ) "2" REFERENCE INTO DATA(group_ref_werks). "3" CLEAR ls_grp_werks. LOOP AT GROUP group_ref_werks INTO DATA(ls_werks) "4" GROUP BY ( matnr = ls_werks-matnr ) "5" REFERENCE INTO DATA(group_ref). "6" LOOP AT GROUP group_ref REFERENCE INTO DATA(lr_tab)."7" IF ls_matnr IS INITIAL. "8" MOVE-CORRESPONDING lr_tab->* TO ls_matnr. ELSE. ls_matnr-menge = ls_matnr-menge + lr_tab->menge. ENDIF. ENDLOOP. "9" ls_matnr-menge_fr = ls_matnr-menge_to - ls_matnr-menge_r."10" CLEAR ls_val. MOVE-CORRESPONDING ls_matnr TO ls_val."11" ls_class-menge = ls_grp_class-menge + ls_matnr-menge."12" ENDLOOP."13" CLEAR ls_val. MOVE-CORRESPONDING ls_grp_class TO ls_val. APPEND ls_val TO lt_result."14" ENDLOOP. |
- “1” – DATA(ls_data) – динамически определяем структуру.
- “2” – Задаём поля, по которым хотим сгруппировать записи таблицы.
- “3” – group_ref_werks – Динамически определяем переменную в которую по очереди будут помещаться группы записей с одинаковыми ключевыми полями.
- “4” – Используя конструкцию LOOP GROUP пройдём по выделенной группе записей group_ref_werks.
- “5” – Здесь можем обработать группу цикла и не группировать, но нам нужна дополнительная группировка ещё и по материалу.
- “6” – Помещаем подгруппу уже по новому ключу состоящему не из двух полей, как на уровне выше, а из трёх.
- “7” – Обрабатываем группу полученную выше и суммируем значения всех записей находящихся в ней.
- “8” – Если это первая строка, из группы, то копируем значения.
- “9” – Выйдя из этого цикла обработана вся первая группа с одинаковым набором трёх полей.
- “10” – После этого можно произвести расчёт зависимых от суммированных полей.
- “11” – Сохраняем полученную запись суммы в структуру результата для дальнейшего использование.
- “12” – Далее суммируем значения уже для внешнего цикла который проходит по уникальным значениям внешней группировки.
- “13” – После выхода из цикла так же обрабатываем необходимым образом поля сумм.
- “14” – И сохраняем данные по этому проходу цикла в итоговую таблицу.
Пример использования группировки в цикле ABAP на реальных задачах:
- При загрузке из Excel файла данных в SAP систему удобно группировать данные по строкам с использованием LOOP AT GROUP. Пример использования можно посмотреть в статье загрузка данных из Excel.