解决Search help (F4 help)区分大小写的问题
在abap编程中,search help是一个非常有用,也经常涉及到的东东。它有个问题是,自动区分大小写。而且没有设置去更改这种行为。有客户抱怨说,他搜索时不需要区分大小写。解决方法是建一个search help exit(也就是指定一个function module)去自定义搜索内容。
这里,我提供两种代码实现方式。
方法一:
FUNCTION yzr_fto_f4help_exit . *"---------------------------------------------------------------------- *"*"Local Interface: *" TABLES *" SHLP_TAB TYPE SHLP_DESCT *" RECORD_TAB STRUCTURE SEAHLPRES *" CHANGING *" REFERENCE(SHLP) TYPE SHLP_DESCR *" REFERENCE(CALLCONTROL) LIKE DDSHF4CTRL STRUCTURE DDSHF4CTRL *"---------------------------------------------------------------------- DATA: it_shlpselop TYPE ddshselops, wa_shlpselop LIKE LINE OF it_shlpselop, lv_name1 TYPE /sapsll/v_orgbp-name1, lv_usrname1 TYPE /sapsll/v_orgbp-name1, lv_tabix TYPE i, it_shlp TYPE shlp_descr-fielddescr, wa_shlp LIKE LINE OF it_shlp. CONSTANTS: BEGIN OF gc_memory, "#EC * fto_name1 TYPE char16 VALUE 'FTO_F4HELP_NAME1', "#EC * vbs_name1 TYPE char16 VALUE 'VBS_F4HELP_NAME1', "#EC * END OF gc_memory. "#EC * * Step1: Save input parameters to memory and delete them from Selection Options to let search help return whole list. IF callcontrol-step = 'SELECT'. DELETE FROM MEMORY ID gc_memory-fto_name1. LOOP AT shlp-selopt INTO wa_shlpselop. IF wa_shlpselop-shlpfield EQ 'NAME1'. "#EC * lv_usrname1 = wa_shlpselop-low. EXPORT lv_usrname1 TO MEMORY ID gc_memory-fto_name1. DELETE shlp-selopt INDEX sy-tabix. ENDIF. ENDLOOP. ENDIF. * Step2: Restore selection options by comparing with the original text. IF callcontrol-step = 'DISP'. IMPORT lv_usrname1 TO lv_usrname1 FROM MEMORY ID gc_memory-fto_name1. IF NOT lv_usrname1 IS INITIAL. * TRANSLATE lv_usrname1 TO UPPER CASE. LOOP AT record_tab. lv_tabix = sy-tabix. READ TABLE shlp-fielddescr INTO wa_shlp WITH KEY tabname = 'YZR_V_ORGBP' "#EC * fieldname = 'NAME1'. "#EC * wa_shlp-offset = wa_shlp-offset / 2. lv_name1 = record_tab-string+wa_shlp-offset(40). * TRANSLATE lv_name1 TO UPPER CASE. IF NOT lv_name1 CP lv_usrname1. DELETE record_tab INDEX lv_tabix. ENDIF. ENDLOOP. ENDIF. ENDIF.
其主要做法是:
1. 在‘SELECT’事件里,把输入的选择条件保存在全局缓存中,并从shlp-selopt中擦除。这样,search help会把所有记录都找出来。
2. 在‘DISP’事件里,把搜索条件从缓存中读出来,并手动删除不符合条件的记录。这里一定要算准字段的位置和值,并注意使用‘CP’操作符,支持‘*’通配符查询。
此方法有个问题:我们所操作的记录是基于search help自动产生的。Search Help画面中的允许输出最大值将影响到这些记录。比如最大值被设定为500,那么我们操作的记录集最多也只有500条,真正符合条件的则更少。这就带来一个潜在的bug,有可能真正符合条件的有20条,但由于search help本身限定了500条,所以可能这20条中,只有10条在这500条中,其余10条没有传给我们。那结果一定是不正确的。把最大值设为很大很大,可以解决这个问题,但对用户来说是不合理的。
方法二:
FUNCTION /sapsll/shlp_exit_project. *"---------------------------------------------------------------------- *"*"Lokale Schnittstelle: *" TABLES *" SHLP_TAB TYPE SHLP_DESCT *" RECORD_TAB STRUCTURE SEAHLPRES *" CHANGING *" REFERENCE(SHLP) TYPE SHLP_DESCR *" REFERENCE(CALLCONTROL) LIKE DDSHF4CTRL STRUCTURE DDSHF4CTRL *"---------------------------------------------------------------------- DATA: lt_shlpselop TYPE ddshselops, wa_shlpselop LIKE LINE OF lt_shlpselop, lv_pronr TYPE /sapsll/pronr, lv_ernam TYPE /sapsll/ernam, lv_aenam TYPE /sapsll/aenam, lv_text1 TYPE /sapsll/text60, lv_text2 TYPE /sapsll/text60, lv_text3 TYPE /sapsll/text60, lv_tabix TYPE int4, lt_project TYPE TABLE OF /sapsll/v_lcpro, wa_project LIKE LINE OF lt_project. FIELD-SYMBOLS: <lt_tab> TYPE table. CHECK ( callcontrol-step = 'SELECT' ). LOOP AT shlp-selopt INTO wa_shlpselop. CASE wa_shlpselop-shlpfield. WHEN 'PRONR'. "#EC * lv_pronr = wa_shlpselop-low. WHEN 'ERNAM'. "#EC * lv_ernam = wa_shlpselop-low. WHEN 'AENAM'. "#EC * lv_aenam = wa_shlpselop-low. WHEN 'TEXT1'. "#EC * lv_text1 = wa_shlpselop-low. WHEN 'TEXT2'. "#EC * lv_text2 = wa_shlpselop-low. WHEN 'TEXT3'. "#EC * lv_text3 = wa_shlpselop-low. WHEN OTHERS. ENDCASE. ENDLOOP. SELECT t1~pronr t2~text1 t2~text2 t2~text3 t1~ernam t1~aenam FROM /sapsll/lcpro AS t1 JOIN /sapsll/lcprot AS t2 ON t1~guid_lcpro = t2~guid_lcpro AND t1~mandt = t2~mandt AND t2~langu = sy-langu INTO CORRESPONDING FIELDS OF TABLE lt_project ORDER BY t1~pronr. DELETE ADJACENT DUPLICATES FROM lt_project. IF ( lv_pronr IS NOT INITIAL ) OR ( lv_ernam IS NOT INITIAL ) OR ( lv_aenam IS NOT INITIAL ) OR ( lv_text1 IS NOT INITIAL ) OR ( lv_text2 IS NOT INITIAL ) OR ( lv_text3 IS NOT INITIAL ). LOOP AT lt_project INTO wa_project. lv_tabix = sy-tabix. IF ( lv_pronr IS NOT INITIAL AND NOT wa_project-pronr CP lv_pronr ) OR ( lv_ernam IS NOT INITIAL AND NOT wa_project-ernam CP lv_ernam ) OR ( lv_aenam IS NOT INITIAL AND NOT wa_project-aenam CP lv_aenam ) OR ( lv_text1 IS NOT INITIAL AND NOT wa_project-text1 CP lv_text1 ) OR ( lv_text2 IS NOT INITIAL AND NOT wa_project-text2 CP lv_text2 ) OR ( lv_text3 IS NOT INITIAL AND NOT wa_project-text3 CP lv_text3 ). DELETE lt_project INDEX lv_tabix. ENDIF. ENDLOOP. ENDIF. * 'Maximum Number of Rows' logic callcontrol-maxexceed = abap_false. IF callcontrol-maxrecords > 0. * restrict result table to max. rows specified in MAXRECORDS; * set MAXEXCEED if there are more than MAXRECORDS rows DELETE lt_project FROM callcontrol-maxrecords + 1. IF sy-subrc = 0. * more rows exist than requested callcontrol-maxexceed = abap_true. ENDIF. ENDIF. ASSIGN lt_project TO <lt_tab>. CALL FUNCTION 'F4UT_RESULTS_MAP' TABLES shlp_tab = shlp_tab record_tab = record_tab source_tab = <lt_tab> CHANGING shlp = shlp callcontrol = callcontrol. callcontrol-step = 'DISP'. ENDFUNCTION.
此方法主要原理是:
1. 在‘SELECT’事件里,直接从数据库中搜索出所有记录,然后根据过滤条件,手动删除不符合的记录。
2. 判断符合记录的数量是否超过了最大允许输出值,把多余的删除。
此方法解决了方法一中碰到的问题,比较稳妥。