问题场景
需要弹出一个ALV并获取选择的数据
实现思路
- 跳转屏幕
- 弹出ALV(通过SALV)
- 弹出ALV(通过REUSE_ALV_POPUP_TO_SELECT)
实现效果
因为这里需要的是单选,所以没有多选列
 
实现代码
 MODULE sel_zfretype INPUT.
  DATA:lt_zmmt041 LIKE TABLE OF zmmt041,
       lt_twlad   LIKE TABLE OF twlad,
       lt_twlad01 LIKE TABLE OF twlad.
  DATA:lfdnr TYPE lfdnr_twlad.
  DATA: lt_msg TYPE rs_t_msg,
        ls_msg TYPE bal_s_msg.
  DATA: lf_one_msg_as_sys_msg TYPE flag.
  DATA go_alv TYPE REF TO cl_salv_table.
  DATA: go_functions  TYPE REF TO cl_salv_functions_list,
        go_selections TYPE REF TO cl_salv_selections,
        go_layout     TYPE REF TO cl_salv_layout,
        go_display    TYPE REF TO cl_salv_display_settings.
  DATA: gr_columns TYPE REF TO cl_salv_columns_table.
  DATA: gr_column TYPE REF TO cl_salv_column_table.
  DATA lt_rows TYPE salv_t_row.
  DATA:ls_row TYPE LINE OF salv_t_row.
  DATA:lv_wlzs LIKE zmmtydand-menge.
  DATA:BEGIN OF lt_sel OCCURS 1,
         zbjh       LIKE zmmt041-zbjh,
         zxmh       LIKE zmmt041-zxmh,
         zfylx      LIKE zmmt041-zfylx,
         zfylx_t    LIKE zmmt041-zfylx_t,
         zvendor    LIKE zmmt041-zvendor,
         name2      LIKE zmmt041-name2,
         zkunnr     LIKE zmmt041-zkunnr,
         name1      LIKE zmmt041-name1,
         zarea      LIKE zmmt041-zarea,
         zcity      LIKE zmmt041-zcity,
         zcountry   LIKE zmmt041-zcountry,
         zarea_t    LIKE zsdt010-zarea_t,
         zcity_t    LIKE zsdt010-zcity_t,
         zcountry_t LIKE zsdt010-zcounty_t,
         zdj        LIKE zmmt041-zdj,
         zdtszl     LIKE zmmt041-zdtszl,
         zsl        LIKE zmmt041-zsl,
         zbz        LIKE zmmt041-zbz.
  DATA:END OF lt_sel.
  DATA:lt_lfa1     LIKE TABLE OF lfa1 WITH HEADER LINE,
       lt_zsdt0101 TYPE TABLE OF zsdt010 WITH HEADER LINE.
  REFRESH:lt_zmmt041,lt_twlad,lt_twlad01.
  "校验供应商
  IF g_wa_data-lifnr IS INITIAL.
    REFRESH lt_msg.
    CLEAR ls_msg.
    ls_msg-msgty = 'E'.
    ls_msg-msgid = 'ZMM01'.
    ls_msg-msgno = '113'.
    APPEND ls_msg TO lt_msg.
    IF lt_msg IS NOT INITIAL.
      cl_epic_ui_services=>show_messages_with_alog(
             it_messages       = lt_msg
             iv_one_msg_direct = lf_one_msg_as_sys_msg ).
      CLEAR:g_wa_item_fre-zfretype.
      RETURN.
    ENDIF.
  ENDIF.
  "处理费用类型描述
  CHECK g_wa_item_fre-zfrename <> '运输费用'.
  IF g_wa_item_fre-zfrename EQ '运输费用'.
    RETURN.
  ELSE.
    SELECT SINGLE zfrename INTO g_wa_item_fre-zfrename
    FROM zmmt037
    WHERE zfretype  = g_wa_item_fre-zfretype.
  ENDIF.
  CLEAR:g_wa_item_fre-zfredj,g_wa_item_fre-zfresl,g_wa_item_fre-zfretax,g_wa_item_fre-zfrecefy,g_wa_item_fre-zfreje.
  "处理单价和税率
  SELECT * FROM zmmt041 INTO CORRESPONDING FIELDS OF TABLE lt_zmmt041
  WHERE zvendor =  g_wa_data-lifnr AND vstel = g_wa_data-vstel
  AND zwxp = g_wa_data-zwxp AND zfylx = g_wa_item_fre-zfretype
  AND zstatus = '3' AND zyxqc < sy-datum AND zyxqd > sy-datum
  AND zwzc = g_wa_data-zwzc.
  "modify by wangk at 20230214 其他费用选择逻辑变更
  "处理最小桶数/重量,过滤高于最小桶数/重量的
  lv_wlzs = 0.
  LOOP AT g_it_item.
    lv_wlzs = lv_wlzs + g_it_item-menge.
  ENDLOOP.
  DELETE lt_zmmt041[] WHERE zdtszl >= lv_wlzs.
  IF lt_zmmt041[] IS INITIAL.
    g_wa_item_fre-zfrejhw = 'X'.
    RETURN.
  ENDIF.
  "选择报价
  REFRESH:lt_sel,lt_lfa1,lt_zsdt0101.
  MOVE-CORRESPONDING lt_zmmt041[] TO lt_sel[].
  SELECT * FROM lfa1 INTO CORRESPONDING FIELDS OF TABLE lt_lfa1
  FOR ALL ENTRIES IN lt_sel
  WHERE lifnr = lt_sel-zvendor.
  SELECT * FROM zsdt010 INTO CORRESPONDING FIELDS OF TABLE lt_zsdt0101.
  LOOP AT lt_sel INTO DATA(ls_sel).
    "供应商
    READ TABLE lt_lfa1 WITH KEY lifnr = ls_sel-zvendor.
    IF sy-subrc = 0.
      ls_sel-name2 = lt_lfa1-sortl.
    ENDIF.
    "三级地址
    IF ls_sel-zarea IS NOT INITIAL.
      READ TABLE lt_zsdt0101 WITH KEY zarea = ls_sel-zarea.
      IF sy-subrc = 0.
        ls_sel-zarea_t = lt_zsdt0101-zarea_t.
      ENDIF.
    ENDIF.
    IF ls_sel-zcity IS NOT INITIAL.
      READ TABLE lt_zsdt0101 WITH KEY zcity = ls_sel-zcity zarea = ls_sel-zarea.
      IF sy-subrc = 0.
        ls_sel-zcity_t = lt_zsdt0101-zcity_t.
      ENDIF.
    ENDIF.
    IF ls_sel-zcountry IS NOT INITIAL.
      READ TABLE lt_zsdt0101 WITH KEY zcounty = ls_sel-zcountry  zcity = ls_sel-zcity zarea = ls_sel-zarea.
      IF sy-subrc = 0.
        ls_sel-zcountry_t = lt_zsdt0101-zcounty_t.
      ENDIF.
    ENDIF.
    MODIFY lt_sel FROM ls_sel.
    CLEAR:ls_sel.
  ENDLOOP.
  TRY.
      cl_salv_table=>factory(
        IMPORTING
          r_salv_table = go_alv"方法生成的ALV容器对象
        CHANGING
          t_table      = lt_sel[] )."alv展示的数据
    CATCH cx_salv_msg.
  ENDTRY.
  go_functions = go_alv->get_functions( ).
  go_functions->set_all( 'X' )."设置默认按键
  go_selections = go_alv->get_selections( ).
  go_selections->set_selection_mode( if_salv_c_selection_mode=>single )."设置选择模式
  go_display = go_alv->get_display_settings( ).
  go_display->set_fit_column_to_table_size( 'X' )."列自适应
  gr_columns = go_alv->get_columns( ).
  gr_columns->set_optimize( 'X' ).
  gr_column ?= gr_columns->get_column( 'ZBZ' )."需处理的列
  gr_column->set_long_text( '备注' ).
  gr_column->set_medium_text( '备注' ).
  gr_column->set_short_text( '备注' ).
*gr_column->set_output_length( 15 ).
  gr_column ?= gr_columns->get_column( 'NAME2' )."需处理的列
  gr_column->set_long_text( '分包方' ).
  gr_column->set_medium_text( '分包方' ).
  gr_column->set_short_text( '分包方' ).
  gr_column ?= gr_columns->get_column( 'NAME1' )."需处理的列
  gr_column->set_long_text( '送达方' ).
  gr_column->set_medium_text( '送达方' ).
  gr_column->set_short_text( '送达方' ).
  gr_column ?= gr_columns->get_column( 'ZAREA_T' )."需处理的列
  gr_column->set_long_text( '目的城市(省)' ).
  gr_column->set_medium_text( '目的城市(省)' ).
  gr_column->set_short_text( '省' ).
  gr_column ?= gr_columns->get_column( 'ZCITY_T' )."需处理的列
  gr_column->set_long_text( '目的城市(市)' ).
  gr_column->set_medium_text( '目的城市(市)' ).
  gr_column->set_short_text( '市' ).
  gr_column ?= gr_columns->get_column( 'ZCOUNTRY_T' )."需处理的列
  gr_column->set_long_text( '目的城市(县/区/镇)' ).
  gr_column->set_medium_text( '目的城市(县/区/镇)' ).
  gr_column->set_short_text( '县/区/镇' ).
  gr_column ?= gr_columns->get_column( 'ZDTSZL' )."需处理的列
  gr_column->set_long_text( '最低桶数/重量' ).
  gr_column->set_medium_text( '最低桶数/重量' ).
  gr_column->set_short_text( '最低桶数/重量' ).
  gr_column ?= gr_columns->get_column( 'ZDJ' )."需处理的列
  gr_column->set_long_text( '单价' ).
  gr_column->set_medium_text( '单价' ).
  gr_column->set_short_text( '单价' ).
  gr_column ?= gr_columns->get_column( 'ZAREA' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZCITY' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZCOUNTRY' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZFYLX' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZBJH' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZXMH' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZVENDOR' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZKUNNR' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  gr_column ?= gr_columns->get_column( 'ZSL' ).
  gr_column->set_visible( cl_salv_column_table=>false ).
  IF go_alv IS BOUND.
    go_alv->set_screen_popup(
      start_column = 10
      end_column  = 110
      start_line  = 5
      end_line    = 15 ).
    go_alv->display( ). "调用显示方法
  ENDIF.
  REFRESH:lt_rows.
  lt_rows = go_selections->get_selected_rows( ).
  IF lt_rows[] IS INITIAL.
    g_wa_item_fre-zfrejhw = 'X'.
    RETURN.
  ENDIF.
  LOOP AT lt_rows INTO ls_row.
    READ TABLE lt_sel INTO DATA(ls_zmmt041) INDEX ls_row.
    g_wa_item_fre-zfredj = ls_zmmt041-zdj.
    g_wa_item_fre-zfretax = ls_zmmt041-zsl.
    g_wa_item_fre-zfrejhw = ''.
    CLEAR:ls_row.
  ENDLOOP.
ENDMODULE.     
实现过程思路
- 因为屏幕这块做的比较多了,所以这次就想通过ALV实现,一开始使用的函数:REUSE_ALV_POPUP_TO_SELECT。使用这个函数遇到了1个问题:无法实现单选。一直没有找到解决方案,就放弃了。
- 采用SALV实现,系统提供了一个示例程序可以参考:SALV_TEST_TABLE_SELECTIONS
 使用这个方案也是需要解决几个问题:a.列的宽度自适应 b.隐藏列 c.实现单单选效果 d.修改列对应的描述 e.获取返回的数据
 问题a: 想通过下面这个方法实现
go_display = go_alv->get_display_settings( ).
go_display->set_fit_column_to_table_size( 'X' )."列自适应
但是调试一直不生效,没找到问题出在哪里。
 后面通过另外一种方案实现:
gr_columns = go_alv->get_columns( ).
gr_columns->set_optimize( 'X' ).
成功达到了想要的效果。
 问题b:
 这里我想到了fieldcat,但是SALV的fieldcat是通过以下实现的
gr_column ?= gr_columns->get_column( 'ZAREA' ).
gr_column->set_visible( cl_salv_column_table=>false ).
问题c:
go_selections = go_alv->get_selections( ).
go_selections->set_selection_mode( if_salv_c_selection_mode=>single )."设置选择模式
这里有几种选择模式
 
 问题d:
gr_columns = go_alv->get_columns( ).
gr_column ?= gr_columns->get_column( 'ZBZ' )."需处理的列
gr_column->set_long_text( '备注' ).
gr_column->set_medium_text( '备注' ).
gr_column->set_short_text( '备注' ).
*gr_column->set_output_length( 15 ).
gr_column下面有很多方法
 
 这里面也有几个关于前导0的函数,我也是多次调试没有生效,截止到现在没有找到问题的原因,因为最近需求比较急,我就没花时间去深究。
 问题e:
 在display( )方法后面可以通过函数获取选择的行。
IF go_alv IS BOUND.
  go_alv->set_screen_popup(
    start_column = 10
    end_column  = 110
    start_line  = 5
    end_line    = 15 ).
  go_alv->display( ). "调用显示方法
ENDIF.
REFRESH:lt_rows.
lt_rows = go_selections->get_selected_rows( ).
LOOP AT lt_rows INTO ls_row.
  READ TABLE lt_sel INTO DATA(ls_zmmt041) INDEX ls_row.
ENDLOOP.
附加收获
下面是一段逻辑流,遇到的问题及解决方案:
- 编辑后保存不了——没有写FIELD
- 写了MODULE没有生效——需要计算的数据一定顺序一定在被计算的后面,比如下面的zfreje和zfrecefy是由zfredj和zfresl计算出来的,那么顺序上zfreje和zfrecefy要在上面
- 改了zfretype其他字段没有更新——因为zfretype的优先级最高,所以要放在最后,这样zfretype对应的MODULE才会覆盖前面的字段。
  LOOP AT g_it_item_fre.
    CHAIN.
      FIELD g_wa_item_fre-zno.
      FIELD g_wa_item_fre-zfreje.
      FIELD g_wa_item_fre-zfrecefy.
      FIELD g_wa_item_fre-zfredj MODULE js_zfreje ON REQUEST.
      FIELD g_wa_item_fre-zfresl MODULE js_zfreje ON REQUEST.
      FIELD g_wa_item_fre-zfretax.
      FIELD g_wa_item_fre-zfrejhw.
      FIELD g_wa_item_fre-zfretype MODULE sel_zfretype ON REQUEST.
      MODULE tab_item_fre_modify ON CHAIN-REQUEST.
    ENDCHAIN.
    FIELD g_wa_item_fre-box
      MODULE tab_item_fre_mark ON REQUEST.
  ENDLOOP.

















