将 ABAP 740 语法转换为 700 - VALUE & LOOP AT ... GROUP BY

Converting ABAP 740 syntax to 700 - VALUE & LOOP AT ... GROUP BY

我在网上找到了一个demo program我想用的tree salv,但由于它使用740语法,我必须先转换它。这也是进一步了解新语法的好机会。

我已经完成了几乎所有的工作,但是 VALUE 遇到了问题。阅读此 wiki entry 等内容对我没有帮助。

740中的原码:

" Treenodes einfügen
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-carrid.

  DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).

  DATA(o_parent) = o_tree->get_nodes( )->add_node( related_node   = ''
                                                   relationship   = cl_gui_column_tree=>relat_last_child
                                                   collapsed_icon = CONV #( icon_closed_folder )
                                                   expanded_icon  = CONV #( icon_open_folder )
                                                   row_style      = if_salv_c_tree_style=>intensified
                                                   text           = CONV #( <c>-carrid ) ).

  IF lines( it_cp ) > 1.
    o_parent->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>button ).
    o_parent->get_item( 'CARRID' )->set_value( 'all' ).
  ENDIF.

  LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<f>).
    DATA(o_carrid) = o_tree->get_nodes( )->add_node( related_node = o_parent->get_key( )
                                                     relationship = cl_gui_column_tree=>relat_last_child
                                                     data_row     = <f>
                                                     row_style    = if_salv_c_tree_style=>intensified
                                                     text         = CONV #( <f>-connid ) ).

    o_carrid->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>checkbox ).
    o_carrid->get_item( 'CARRID' )->set_editable( abap_true ).
  ENDLOOP.
ENDLOOP.

700 中的新代码,除了符合 VALUE 的行:

" new variables added to convert code to 700
DATA: o_nodes  TYPE REF TO cl_salv_nodes,
      o_parent TYPE REF TO cl_salv_node,
      o_carrid TYPE REF TO cl_salv_node,
      o_item   TYPE REF TO cl_salv_item,
      o_key    TYPE lvc_nkey.

DATA: h_collapsed_icon TYPE salv_de_tree_image VALUE 'icon_closed_folder',
      h_expanded_icon TYPE salv_de_tree_image VALUE 'icon_open_folder',
      h_text_carrid TYPE lvc_value.

DATA: it_cp TYPE STANDARD TABLE OF ty_it_spfli.    

SORT it_spfli BY carrid.

" Treenodes einfügen
LOOP AT it_spfli ASSIGNING <c>.

  AT NEW carrid.

    it_cp = value TY_IT_SPFLI( for <CP> in GROUP <c> ( <CP> ) ).  <--- Here

    o_nodes = o_tree->get_nodes( ).

    h_text_carrid = <c>-carrid.

    o_parent = o_nodes->add_node( related_node   = ''
                                  relationship   = cl_gui_column_tree=>relat_last_child
                                  collapsed_icon = h_collapsed_icon
                                  expanded_icon  = h_expanded_icon
                                  row_style      = if_salv_c_tree_style=>intensified
                                  text           = h_text_carrid ).

    IF LINES( it_cp ) > 1.
      o_item = o_parent->get_item( 'CARRID' ).
      o_item->set_type( if_salv_c_item_type=>button ).
      o_item->set_value( 'all' ).
    ENDIF.

  ENDAT.

  o_key = o_parent->get_key( ).

  o_carrid = o_nodes->add_node( related_node = o_key
                                relationship = cl_gui_column_tree=>relat_last_child
                                data_row     = <c>
                                row_style    = if_salv_c_tree_style=>intensified
                                text         = h_text_carrid ).

  o_item = o_parent->get_item( 'CARRID' ).
  o_item->set_type( if_salv_c_item_type=>checkbox ).
  o_item->set_editable( abap_true ).

ENDLOOP.

我现在的问题是:

  1. 我是否使用 AT NEW 正确转换了 LOOP AT ... GROUP BY
  2. 如何转换带有 VALUE 的行?

预先感谢您的帮助。

其实你问的是"FOR ... IN GROUP":

这一行是什么意思
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
DATA it_spfli TYPE ty_it_spfli.
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-carrid.
  DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).
  ...
ENDLOOP.

首先,带有 "GROUP BY" 的外循环迭代 CARRID 组件的不同值。比如内部的tableit_spfli可能有100行,但是只有10个不同的CARRID值,所以会迭代10次

里面的"value construction"FOR <cp> IN GROUP <c>"group""members"处做了一个循环 of lines <c>,其中"members"是对应当前组的it_spfli行(对应当前组CARRID值的那些行),并且在每次迭代中,行 ( <cp> ) 附加到变量 it_cp.

这一行:

DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).

等价于LOOP AT GROUP下面的语法,也是从7.40开始有效,不过大家应该更清楚,7.0可以更直观的转换一下:

DATA(it_cp) = VALUE ty_it_spfli( ). " initialization (empty internal table)
LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<cp>).
  INSERT <cp> INTO TABLE it_cp.
ENDLOOP.

您不能像您那样进行转换。 CARRID 原始代码分组的外层循环与 AT NEW 并不完全相同,因为它生成了一个临时组 table 然后你可以在任何地方使用。没有它,你应该提前生成组。

我没有验证代码,但是为了模拟 GROUP BY 然后使其余的转换变得容易而不必重写太多,我会为每个 CARRID 创建一个嵌套的 table原文:

DATA: BEGIN OF ls_spfli_carrid_group,
        carrid  TYPE carrid,
        flights TYPE ty_it_spfli,
      END OF ls_spfli_carrid_group,
      lt_spfli_carrid_group LIKE STANDARD TABLE OF ls_spfli_carrid_group.

SORT it_spfli BY carrid.
LOOP AT it_spfli INTO ls_spfli.
  AT NEW carrid.
    it_spfli
    ls_spfli_carrid_group-carrid = ls_spfli-carrid.
    REFRESH ls_spfli_carrid_group-flights.
    APPEND ls_spfli_carrid_group TO lt_spfli_carrid_group.
  ENDAT.
  APPEND ls_spfli TO ls_spfli_carrid_group-flights.
ENDLOOP.

LOOP AT lt_spfli_carrid_group INTO ls_spfli_carrid_group.
  it_cp = ls_spfli_carrid_group-flights.
  ...
  LOOP AT ls_spfli_carrid_group-flights INTO ls_flight. "Should be like the LOOP AT GROUP
  ENDLOOP.
ENDLOOP.

感谢 Sandra 和 RaTiO 的帮助。

现在我明白了应该发生什么,我有以下两个解决方案(其中一个是来自 RaTiO 的解决方案)。

(应该发生什么:VALUE 命令应该用循环 table 的那些行填充另一个 itab,其中包含当前 CARRID。然后取决于数量行,你可以看到节点是否有子节点,因此需要是一个扩展按钮。)

所以我自己想到的解决办法是在LOOP里面填充一份table,删除那些不包含当前CARRID的条目。

DATA: it_copy_spfli TYPE ty_it_spfli.

...

SORT it_spfli BY carrid.

LOOP AT it_spfli ASSIGNING <c>.

  AT NEW carrid.

    REFRESH it_copy_spfli.
    it_copy_spfli = it_spfli.
    DELETE it_copy_spfli WHERE carrid <> <c>-carrid.

    ...

    IF LINES( it_copy_spfli ) > 1.
      ...
    ENDIF.

  ENDAT.

  ...

ENDLOOP.

然后是 RaTiO 的解决方案,创建一个嵌套的 table 来代替循环。

DATA: it_copy_spfli TYPE ty_it_spfli.

DATA: BEGIN OF ls_spfli_carrid_group,
        carrid  TYPE s_carr_id,
        flights TYPE ty_it_spfli,
      END OF ls_spfli_carrid_group.

DATA: ls_spfli  TYPE spfli,
      ls_flight TYPE spfli,
      lt_spfli_carrid_group LIKE STANDARD TABLE OF ls_spfli_carrid_group.

SORT it_spfli BY carrid.

LOOP AT it_spfli INTO ls_spfli.

  APPEND ls_spfli TO ls_spfli_carrid_group-flights.

  AT END OF carrid.
    ls_spfli_carrid_group-carrid = ls_spfli-carrid.
    APPEND ls_spfli_carrid_group TO lt_spfli_carrid_group.
    REFRESH ls_spfli_carrid_group-flights.
  ENDAT.

ENDLOOP.

LOOP AT lt_spfli_carrid_group INTO ls_spfli_carrid_group.

  REFRESH it_copy_spfli.
  it_copy_spfli = ls_spfli_carrid_group-flights.

  ...

  h_text_carrid = ls_spfli_carrid_group-carrid.

  ...

  IF LINES( it_copy_spfli ) > 1.
    ...
  ENDIF.

  LOOP AT ls_spfli_carrid_group-flights INTO ls_flight.

    ...

    o_carrid = o_nodes->add_node( ...
                                  data_row     = ls_flight
                                  ... ).

    ...

  ENDLOOP.
ENDLOOP.

然后我将其修改为使用 FIELD-SYMBOLS。

DATA: it_copy_spfli TYPE ty_it_spfli.

TYPES: BEGIN OF ty_spfli_carrid_group,
        carrid  TYPE s_carr_id,
        flights TYPE ty_it_spfli,
END OF ty_spfli_carrid_group.

DATA: lt_spfli_carrid_group TYPE STANDARD TABLE OF ty_spfli_carrid_group.

FIELD-SYMBOLS: <spfli>  TYPE spfli,
               <flight> TYPE spfli,
               <spfli_carrid_group> TYPE ty_spfli_carrid_group.

SORT it_spfli BY carrid.

LOOP AT it_spfli ASSIGNING <spfli>.

  AT NEW carrid.
    APPEND INITIAL LINE TO lt_spfli_carrid_group ASSIGNING <spfli_carrid_group>.
  ENDAT.

  APPEND <spfli> TO <spfli_carrid_group>-flights.

  AT END OF carrid.
    <spfli_carrid_group>-carrid = <spfli>-carrid.
  ENDAT.

ENDLOOP.

LOOP AT lt_spfli_carrid_group ASSIGNING <spfli_carrid_group>.

  ...

  LOOP AT <spfli_carrid_group>-flights ASSIGNING <flight>.

    ...

  ENDLOOP.
ENDLOOP.

所有解决方案都按预期工作。比较运行时,最后一个是最快的,但它们非常接近。所以我决定使用我的,因为它只有几行,而 RaTiO 需要另一个 LOOP。

再次感谢您=)