ABAP SALV实现弹出ALV选择

问题场景

需要弹出一个ALV并获取选择的数据

实现思路

  1. 跳转屏幕
  2. 弹出ALV(通过SALV
  3. 弹出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.     

实现过程思路

  1. 因为屏幕这块做的比较多了,所以这次就想通过ALV实现,一开始使用的函数:REUSE_ALV_POPUP_TO_SELECT。使用这个函数遇到了1个问题:无法实现单选。一直没有找到解决方案,就放弃了。
  2. 采用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.

附加收获

下面是一段逻辑流,遇到的问题及解决方案:

  1. 编辑后保存不了——没有写FIELD
  2. 写了MODULE没有生效——需要计算的数据一定顺序一定在被计算的后面,比如下面的zfreje和zfrecefy是由zfredj和zfresl计算出来的,那么顺序上zfreje和zfrecefy要在上面
  3. 改了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.
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用SAP ABAP语言编写一个ALV列表。首先,你需要了解ALV(Adobe List Viewer)是什么,它是SAP系统中用于显示数据的一种标准用户界面控件。 具体来说,你可以使用ALV函数库,这些函数可以让你设置ALV列表的各种属性,如列宽、字段格式、排序方式等。 例如,你可以使用REUSE_ALV_GRID_DISPLAY函数来显示ALV列表,并使用IT_FIELDCAT参数来设置列的格式。 下面是一个简单的例子: ``` *定义数据结构 TYPES: BEGIN OF ty_sflight, carrid TYPE sflight-carrid, connid TYPE sflight-connid, fldate TYPE sflight-fldate, END OF ty_sflight. *定义数据表 DATA: it_sflight TYPE TABLE OF ty_sflight. *定义字段描述表 DATA: it_fieldcat TYPE lvc_t_fcat. *填充数据 SELECT * FROM sflight INTO TABLE it_sflight. *填充字段描述表 APPEND INITIAL LINE TO it_fieldcat ASSIGNING FIELD-SYMBOL(<fs_fieldcat>). <fs_fieldcat>-fieldname = 'CARRID'. <fs_fieldcat>-seltext_l = '航空公司代码'. APPEND INITIAL LINE TO it_fieldcat ASSIGNING FIELD-SYMBOL(<fs_fieldcat>). <fs_fieldcat>-fieldname = 'CONNID'. <fs_fieldcat>-seltext_l = '航班号'. APPEND INITIAL LINE TO it_fieldcat ASSIGNING FIELD-SYMBOL(<fs_fieldcat>). <fs_fieldcat>-fieldname = 'FLDATE'. <fs_fieldcat>-seltext_l = '起飞日期'. *显示ALV列表 CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' EXPORTING i_callback_program = sy-repid i_structure_name = 'TY_SFLIGHT' i_save = 'A' TABLES t_outtab = it_sflight i_fieldcat = it_fieldcat. ``` ### 回答2: ABAP是SAP系统的编程语言,可用于开发和定制各种功能和报表。以下是使用ABAP编写一个ALV列表的步骤。 1. 定义内表:首先,我们需要定义一个内表来存储数据。使用ABAP的DATA语句创建一个具有所需字段的内表。 2. 获取数据:使用ABAP的SELECT语句从数据库中检索所需的数据,并将其存储在内表中。 3. 创建ALV试图:使用ABAP的CL_GUI_ALV_GRID类创建一个ALV列表的实例。定义此实例的属性和设置,如列标题,列宽度,排序等。 4. 载入数据:将内表的数据加载到ALV列表中,使用ALV实例的METHODS属性和方法。 5. 显示ALV列表:使用ABAP的CALL METHOD语句调用ALV实例的DISPLAY方法,以便将其显示在屏幕上。 6. 添加用户交互功能:根据需要,您可以在ALV列表中添加各种用户交互功能,如过滤器,排序,编辑等。使用ALV实例的相应方法和事件来实现它们。 7. 添加功能按钮:您还可以为ALV列表添加自定义功能按钮,以实现特定的操作。使用ABAP的FUNCTION_KEY语句来定义功能按钮,并使用ALV实例的EVENTS属性和方法来处理按钮的点击事件。 8. 处理用户输入:如果用户在ALV列表中进行了更改或交互操作,您可以使用相应的ALV事件来处理这些更改,并在内表中更新数据。 9. 处理指令:根据需要,您可以处理ALV列表中的不同命令,如打印,导出等。使用ALV实例的事件和方法来实现这些指令的功能。 10. 完善界面:最后,如果需要在ALV列表中添加其他UI元素,如选择框,文本框等,您可以使用ABAP的DIALOG和SCREEN等功能来实现。 以上是使用ABAP编写一个ALV列表的一般步骤。根据实际需求和具体业务场景,您可能需要根据自己的要求进行适当的调整和修改。 ### 回答3: ABAP是一种编程语言,用于在SAP系统中开发和定制应用程序。要使用ABAP编写一个ALVABAP List Viewer)列表,可以按照以下步骤进行操作: 1. 创建一个ABAP报表程序,使用SE38事务代码打开ABAP编辑器。 2. 在ABAP编辑器中,定义一个内部表,用于存储数据。例如,可以使用类型为TABLE OF结构的内部表。 3. 在ABAP编辑器中,使用SELECT语句从数据库表中检索所需的数据,并将其放入内部表中。 4. 定义一个ALV网格控件,并与内部表关联。可以使用CL_SALV_TABLE类来创建ALV网格控件对象。 5. 在ALV网格控件上,定义列,标题和布局等。可以使用方法ADD_COLUMN和SET_TABLE_FOR_FIRST_DISPLAY来添加列和定义布局。 6. 调用方法DISPLAY来显示ALV列表。 7. 为ALV列表添加自定义功能。例如,可以添加排序、筛选、汇总等功能。 8. 编译并执行ABAP报表程序,以显示ALV列表。 下面是一个示例代码,用于创建一个包含两列的ALV列表,并在SFLIGHT表中显示航班号和航班日期。 ``` REPORT ZALV_LIST. DATA: lt_flight TYPE TABLE OF sflight, lr_alv TYPE REF TO cl_salv_table. START-OF-SELECTION. SELECT carrid, connid, fldate, price FROM sflight INTO TABLE lt_flight. CREATE OBJECT lr_alv. lr_alv->add_column( 'Carrid' ). lr_alv->add_column( 'Connid' ). lr_alv->set_table_for_first_display( CHANGING it_outtab = lt_flight ). lr_alv->display( ). ``` 以上是一个简单的示例,您可以根据实际需求对代码进行修改和扩展。请注意,使用ALV列表还可以进行更复杂的操作,如行编辑、数据修改等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值