递归函数实现省市区多级联动搜索帮助
1、需求背景
当程序中有互为层级的字段,需要使用搜索帮助时,可以通过多次调用搜索帮助来实现。比如在程序中需要填写省市区三级地址
2、实现方式
2.1、平铺直叙
程序的搜索帮助,通常使用F4IF_INT_TABLE_VALUE_REQUEST来实现。多级的搜索帮助,可以简单的通过多次调用F4函数来实现。
点击省字段,弹出省搜索帮助,根据选择的省份,查询对应的市,弹出市搜索帮助,根据选择的市,查询对应的区县,弹出区县搜索帮助,选择后更新到ALV报表。
同理,点击市则弹出市和区的搜索帮助;点击区则只弹出区的搜索帮助
如图所示:
点击省字段代码示例,省需要写三遍F4:
"--------------------@斌将军-------------------- READ TABLE gt_cjso_alv ASSIGNING <fs_cjso_alv> INDEX pv_row_no-row_id. "获取对应数据集 CASE lv_fieldname1. WHEN 'ZZDEADREGION'."送货地址-省 SELECT land1, bland AS zzdeadregion, bezei FROM t005u INTO TABLE @DATA(lt_t005u) WHERE land1 EQ 'CN' AND spras EQ @sy-langu. ASSIGN lt_t005u TO <lt_f4table>. REFRESH gt_return. CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST' EXPORTING retfield = lv_fieldname1 dynpprog = sy-repid dynpnr = sy-dynnr dynprofield = lv_fieldname2 value_org = 'S' display = 'F' TABLES value_tab = <lt_f4table> return_tab = gt_return EXCEPTIONS parameter_error = 1 no_values_found = 2 OTHERS = 3. IF sy-subrc = 0. READ TABLE gt_return INTO gs_return INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT lv_fieldname1 OF STRUCTURE <fs_cjso_alv> TO <lv_field>. <lv_field> = gs_return-fieldval. SELECT country, region, city_code AS zzdeadcity, city_name FROM v_adrcity INTO TABLE @DATA(lt_v_adrcity) WHERE country EQ 'CN' AND langu EQ @sy-langu AND region EQ @<fs_cjso_alv>-zzdeadregion. ASSIGN lt_v_adrcity TO <lt_f4table>. lv_fieldname = 'ZZDEADCITY'. lv_dynprofld = 'ZZDEADCITY'. REFRESH gt_return. CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST' EXPORTING retfield = lv_fieldname dynpprog = sy-repid dynpnr = sy-dynnr dynprofield = lv_dynprofld value_org = 'S' display = 'F' TABLES value_tab = <lt_f4table> return_tab = gt_return EXCEPTIONS parameter_error = 1 no_values_found = 2 OTHERS = 3. IF sy-subrc = 0. READ TABLE gt_return INTO gs_return INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT 'ZZDEADCITY' OF STRUCTURE <fs_cjso_alv> TO <lv_field>. <lv_field> = gs_return-fieldval. lv_zzdeadcity = |{ <fs_cjso_alv>-zzdeadcity ALPHA = IN }|. SELECT country, city_code, city_name, strt_code AS zzdeadstreet, street FROM m_strta INTO TABLE @DATA(lt_m_strta) WHERE country EQ 'CN' AND langu EQ @sy-langu AND region EQ @<fs_cjso_alv>-zzdeadregion AND city_code EQ @lv_zzdeadcity. ASSIGN lt_m_strta TO <lt_f4table>. lv_fieldname = 'ZZDEADSTREET'. lv_dynprofld = 'ZZDEADSTREET'. REFRESH gt_return. CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST' EXPORTING retfield = lv_fieldname dynpprog = sy-repid dynpnr = sy-dynnr dynprofield = lv_dynprofld value_org = 'S' display = 'F' TABLES value_tab = <lt_f4table> return_tab = gt_return EXCEPTIONS parameter_error = 1 no_values_found = 2 OTHERS = 3. IF sy-subrc = 0. READ TABLE gt_return INTO gs_return INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT 'ZZDEADSTREET' OF STRUCTURE <fs_cjso_alv> TO <lv_field>. <lv_field> = gs_return-fieldval. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. WHEN 'ZZDEADCITY'."送货地址-市 …… WHEN 'ZZDEADSTREET'."送货地址-区县 …… WHEN OTHERS. ENDCASE. PERFORM frm_refresh_alv USING g_grid_9001. "--------------------@斌将军--------------------
2.2、简洁递归
上述方法,虽然能够实现,但是三级地址就需要写五遍重复性代码,如果遇到层级更多的搜索帮助,则需要写N(N+1)/2遍代码,所以我们可以使用递归函数,重复调用搜索帮助,使代码更简洁。
这里说明一点,什么是递归函数?
递归函数:在函数内部调用自身的函数被称为递归函数。递归函数可以将复杂问题转化为更简单的子问题来解决。一个经典的递归函数例子是阶乘函数,其中 n! 等于 n 乘以 (n-1)!。在函数内部通过调用自身来计算阶乘。
抽出通用代码,编写递归函数
"--------------------@斌将军-------------------- FORM frm_callback_f4 USING pv_level pv_fieldname CHANGING ps_alv TYPE ty_cjso_alv. * DATA:lv_zzdeadcity TYPE vbak-zzdeadcity. "送货地址-市 DATA:lt_return TYPE STANDARD TABLE OF ddshretval, ls_return TYPE ddshretval. DATA:lv_next_field TYPE dfies-fieldname, lv_next_level TYPE int4, lv_fieldname TYPE dfies-fieldname, lv_dynprofld TYPE help_info-dynprofld. FIELD-SYMBOLS:<lv_field>. lv_fieldname = pv_fieldname. lv_dynprofld = pv_fieldname. CONDENSE:lv_fieldname,lv_dynprofld NO-GAPS. lv_next_level = pv_level. "根据层级,查询当前层级的数据集,并赋值下一层的字段名 CASE lv_next_level. WHEN 1."第1层 省 SELECT land1, bland AS zzdeadregion, bezei FROM t005u INTO TABLE @DATA(lt_t005u) WHERE land1 EQ 'CN' AND spras EQ @sy-langu. UNASSIGN <gt_f4table>. ASSIGN lt_t005u TO <gt_f4table>. lv_next_field = 'ZZDEADCITY'. WHEN 2."第2层 市 SELECT country, region, city_code AS zzdeadcity, city_name FROM v_adrcity INTO TABLE @DATA(lt_v_adrcity) WHERE country EQ 'CN' AND langu EQ @sy-langu AND region EQ @ps_alv-zzdeadregion. UNASSIGN <gt_f4table>. ASSIGN lt_v_adrcity TO <gt_f4table>. lv_next_field = 'ZZDEADSTREET'. WHEN 3."第3层 区 DATA(lv_zzdeadcity) = |{ ps_alv-zzdeadcity ALPHA = IN }|. SELECT country, city_code, city_name, strt_code AS zzdeadstreet, street FROM m_strta INTO TABLE @DATA(lt_m_strta) WHERE country EQ 'CN' AND langu EQ @sy-langu AND region EQ @ps_alv-zzdeadregion AND city_code EQ @lv_zzdeadcity. UNASSIGN <gt_f4table>. ASSIGN lt_m_strta TO <gt_f4table>. WHEN OTHERS. ENDCASE. "调用搜索帮助函数 CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST' EXPORTING retfield = lv_fieldname dynpprog = sy-repid dynpnr = sy-dynnr dynprofield = lv_dynprofld value_org = 'S' display = 'F' TABLES value_tab = <gt_f4table> return_tab = lt_return EXCEPTIONS parameter_error = 1 no_values_found = 2 OTHERS = 3. IF sy-subrc = 0. READ TABLE lt_return INTO ls_return INDEX 1. IF sy-subrc = 0. ASSIGN COMPONENT lv_fieldname OF STRUCTURE ps_alv TO <lv_field>. <lv_field> = ls_return-fieldval. IF lv_next_level < 3."第三层查询完退出 lv_next_level = lv_next_level + 1. "调用函数本身,开始下次循环 PERFORM frm_callback_f4 USING lv_next_level lv_next_field CHANGING ps_alv. ENDIF. ENDIF. ENDIF. ENDFORM. "--------------------@斌将军--------------------
在点击字段时调用,通过赋值层级,就可以循环调用多级搜索帮助,且代码更加简洁,复用性更高
"--------------------@斌将军-------------------- FORM frm_alv_on_f4_9001 USING pv_fieldname pv_fieldvalue pv_row_no TYPE lvc_s_roid pv_event_data TYPE REF TO cl_alv_event_data pv_display. READ TABLE gt_cjso_alv ASSIGNING <fs_cjso_alv> INDEX pv_row_no-row_id. "获取对应数据集 CASE pv_fieldname. WHEN 'ZZDEADREGION'."送货地址-省 PERFORM frm_callback_f4 USING 1 'ZZDEADREGION' CHANGING <fs_cjso_alv>. WHEN 'ZZDEADCITY'."送货地址-市 PERFORM frm_callback_f4 USING 2 'ZZDEADCITY' CHANGING <fs_cjso_alv>. WHEN 'ZZDEADSTREET'."送货地址-区县 PERFORM frm_callback_f4 USING 3 'ZZDEADSTREET' CHANGING <fs_cjso_alv>. WHEN OTHERS. ENDCASE. PERFORM frm_refresh_alv USING g_grid_9001. ENDFORM. "--------------------@斌将军--------------------
定期更文,欢迎关注