问题场景
需要弹出一个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.