当前位置:网站首页>介绍一种对 SAP GUI 里的收藏夹事务码管理工具增强的实现方案

介绍一种对 SAP GUI 里的收藏夹事务码管理工具增强的实现方案

2022-07-01 13:19:00 InfoQ

SAP Netweaver 里有很多名字比较长的事务码,比如 SAP CRM UI开发工具BSP_WD_CMPWB,直到今天我也记不住它。幸好SAP贴心地在SAP GUI里提供了收藏夹功能,我们可以在SAP GUI里创建树状结构的收藏夹事务码列表,可以把若干业务上相关的事务码放在同一个文件夹内,文件夹支持嵌套,如下图:

null
SAP菜单是一个由用户主记录中的一个条目集中定义或覆盖的区域菜单。SAP菜单或SAP区域菜单显示SAP菜单树中所有可用的SAP t-code,如下图所示:

null
下面是 SAP Area menu 的创建步骤:

  • 使用事物码 SE43:

null
点击 Create Area Menu 按钮:

null
输入菜单的名称和描述信息:

null
  • 添加菜单可供点击的子节点:

null
依次添加菜单项和点击后执行的事物码即可:

null
但是SAP GUI的收藏夹事务码管理功能有个局限,收藏夹树状结构上的事务码节点不支持剪切粘贴操作。比如我要想把下图收藏夹尾部的BSP_WD_COMWB移动到收藏夹最顶端的Design Layer文件夹里,只能鼠标左键单击BSP_WD_COMWB, 按住不放,然后将其拖拽到顶部的目的文件夹里。

null
因为我的收藏夹内容很多,所以我得按住鼠标不放,同时用鼠标中键把滚动条往上滑好几下,直至收藏夹顶部的目标文件夹出现,再松开鼠标左键,将其放到目标文件夹里。

null
这种收藏夹的管理方式低效而且容易出错,需要按住鼠标左键不放同时滑动鼠标中键,万一此时左键松开,就会误操作。于是我自己开发了一个工具。本地新建一个记事本文件,在其内把自己想要导入SAP GUI收藏夹的事务码按照自己喜欢的层级结构维护好,然后直接把这个记事本文件上传到ABAP系统即可。

null
上图的01. 02. 03开头的内容代表的是SAP GUI里生成收藏夹的文件夹名称,方括号内即事务码本身的值。操作记事本,比用鼠标在SAP GUI里做拖拽操作轻松多了,不是吗?下图右边是我在本地记事本里维护的内容,左边是将这个记事本导入到SAP GUI里生成的收藏夹。

null
我开发的这个报表,会解析记事本里维护的事务码和层级结构,然后把解析出的记录插入到Netweaver存放收藏夹事务码的数据库表里。

源代码如下:

REPORT zfavorite.

TYPES: tt_tcode TYPE STANDARD TABLE OF tstct-tcode,
 tt_wd_app TYPE STANDARD TABLE OF wdy_applicationt-application_name.
TYPES: BEGIN OF ty_file,
 text LIKE smen_buffc-text,
 tcode LIKE smen_buffc-report,
 END OF ty_file.

CLASS lcl_counter DEFINITION.

 PUBLIC SECTION.
 METHODS: get_new_obj_id RETURNING VALUE(rv_id) TYPE int4,
 get_folder_sort RETURNING VALUE(rv_id) TYPE int4,
 get_tcode_sort RETURNING VALUE(rv_id) TYPE int4,
 reset_tcode_sort.

 CONSTANTS: cv_root TYPE smen_buffc-parent_id VALUE '00001'.
 CONSTANTS: cv_level1 TYPE smen_buffc-menu_level VALUE '01',
 cv_level2 LIKE cv_level1 VALUE '02'.
 PRIVATE SECTION.
 DATA: mv_object_id TYPE int4 VALUE 1,
 mv_folder_sort TYPE int4 VALUE 0,
 mv_tcode_sort TYPE int4 VALUE 0.
ENDCLASS.

CLASS lcl_counter IMPLEMENTATION.
 METHOD: get_new_obj_id.
 ADD 1 TO mv_object_id.
 rv_id = mv_object_id.
 ENDMETHOD.

 METHOD: get_folder_sort.
 ADD 10 TO mv_folder_sort.
 rv_id = mv_folder_sort.
 ENDMETHOD.

 METHOD: get_tcode_sort.
 ADD 10 TO mv_tcode_sort.
 rv_id = mv_tcode_sort.
 ENDMETHOD.

 METHOD reset_tcode_sort.
 CLEAR: mv_tcode_sort.
 ENDMETHOD.
ENDCLASS.

CLASS lcl_tool DEFINITION.
 PUBLIC SECTION.
 CLASS-METHODS: is_tcode IMPORTING iv_text TYPE string RETURNING VALUE(result) TYPE abap_bool.
 CLASS-METHODS: is_wd_app IMPORTING iv_text TYPE string RETURNING VALUE(result) TYPE abap_bool.
 CLASS-METHODS: get_tcode IMPORTING iv_text TYPE smen_buffc-text RETURNING VALUE(result) TYPE smen_buffc-report.
 CLASS-METHODS: get_wd_app IMPORTING iv_text TYPE smen_buffc-text RETURNING VALUE(result) TYPE smen_buffc-report.
 CLASS-METHODS: set_tcode_list IMPORTING it_tcode TYPE tt_tcode.
 CLASS-METHODS: set_wd_app_list IMPORTING it_app TYPE tt_wd_app.

 CLASS-METHODS: get_tcode_description IMPORTING iv_tcode TYPE smen_buffc-report RETURNING VALUE(result) TYPE smen_buffc-text.
 CLASS-METHODS: get_app_description IMPORTING iv_app TYPE smen_buffc-text RETURNING VALUE(result) TYPE smen_buffc-text.
 CLASS-METHODS: get_menu_type IMPORTING is_menu TYPE ty_file RETURNING VALUE(result) TYPE int4.

 CONSTANTS: cv_wd_app_type TYPE smen_buffc-reporttype VALUE 'OT',
 cv_wd_app_report TYPE smen_buffc-report VALUE 'WDY_APPLICATION',
 BEGIN OF cs_entry_type,
 top_tcode TYPE int4 VALUE 1,
 folder TYPE int4 VALUE 2,
 child_tcode TYPE int4 VALUE 3,
 top_wd_app TYPE int4 VALUE 4,
 child_wd_app TYPE int4 VALUE 5,
 invalid TYPE int4 VALUE 6,
 END OF cs_entry_type.

 PRIVATE SECTION.
 CLASS-DATA: st_tcode TYPE STANDARD TABLE OF tstct,
 st_wd_app TYPE STANDARD TABLE OF wdy_applicationt.
ENDCLASS.

CLASS lcl_tool IMPLEMENTATION.
 METHOD: is_tcode.
 IF iv_text CP '[*]'.
 result = abap_true.
 ELSE.
 result = abap_false.
 ENDIF.
 ENDMETHOD.

 METHOD: is_wd_app.
 IF iv_text CP '(*)'.
 result = abap_true.
 ELSE.
 result = abap_false.
 ENDIF.
 ENDMETHOD.

 METHOD: get_tcode.

 result = iv_text.
 REPLACE ALL OCCURRENCES OF REGEX `[\[\]]` IN result WITH space.

 CONDENSE result NO-GAPS.
 ENDMETHOD.

 METHOD: get_wd_app.

 result = iv_text.
 REPLACE ALL OCCURRENCES OF REGEX `[\(\)]` IN result WITH space.

 CONDENSE result NO-GAPS.
 ENDMETHOD.

 METHOD: set_tcode_list.
 SELECT * INTO CORRESPONDING FIELDS OF TABLE st_tcode FROM tstct
 FOR ALL ENTRIES IN it_tcode WHERE sprsl = sy-langu AND tcode = it_tcode-table_line.

 ENDMETHOD.

 METHOD: set_wd_app_list.
 SELECT * INTO CORRESPONDING FIELDS OF TABLE st_wd_app FROM wdy_applicationt
 FOR ALL ENTRIES IN it_app WHERE application_name = it_app-table_line AND langu = sy-langu.
 ENDMETHOD.

 METHOD: get_tcode_description.
 FIELD-SYMBOLS: <line> TYPE tstct.
 READ TABLE st_tcode ASSIGNING <line> WITH KEY tcode = iv_tcode.
 IF sy-subrc = 0.
 result = <line>-ttext.
 ENDIF.
 ENDMETHOD.

 METHOD: get_app_description.

 FIELD-SYMBOLS: <line> LIKE LINE OF st_wd_app.
 READ TABLE st_wd_app ASSIGNING <line> WITH KEY application_name = iv_app.
 IF sy-subrc = 0.
 result = <line>-description.
 ENDIF.
 ENDMETHOD.

 METHOD: get_menu_type.
 DATA: lv_is_tcode TYPE abap_bool,
 lv_is_wd_app TYPE abap_bool.

 lv_is_tcode = is_tcode( CONV #( is_menu-text ) ).
 lv_is_wd_app = is_wd_app( CONV #( is_menu-text ) ).

 IF is_menu-text IS NOT INITIAL AND is_menu-tcode IS INITIAL.
 IF is_tcode( CONV #( is_menu-text ) ) = abap_true.
 result = cs_entry_type-top_tcode.
 ELSEIF is_wd_app( CONV #( is_menu-text ) ) = abap_true.
 result = cs_entry_type-top_wd_app.
 ELSE.
 result = cs_entry_type-folder.
 ENDIF.
 ELSEIF is_menu-tcode IS NOT INITIAL.
 IF is_tcode( CONV #( is_menu-tcode ) ) = abap_true.
 result = cs_entry_type-child_tcode.
 ELSEIF is_wd_app( CONV #( is_menu-tcode ) ) = abap_true.
 result = cs_entry_type-child_wd_app.
 ELSE.
 result = cs_entry_type-invalid.
 ENDIF.
 ELSE.
 result = cs_entry_type-invalid.
 ENDIF.
 ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

 DATA: gt_file TYPE STANDARD TABLE OF ty_file,
 gt_tcodes TYPE tt_tcode,
 gt_wd_app TYPE tt_wd_app,
 lo_counter TYPE REF TO lcl_counter,
 lv_filename TYPE localfile,
 lv_name_string type string.

 CALL FUNCTION 'NAVIGATION_FILENAME_HELP'
 EXPORTING
 default_path_long = '*.*'
 mode = 'O'
 IMPORTING
 selected_filename = lv_filename.

 CHECK lv_filename IS NOT INITIAL.
 lv_name_string = lv_filename.
 CREATE OBJECT lo_counter.

 CALL FUNCTION 'GUI_UPLOAD'
 EXPORTING
 filename = lv_name_string
 filetype = 'ASC'
 has_field_separator = 'X'
 TABLES
 data_tab = gt_file
 EXCEPTIONS
 file_open_error = 1
 file_read_error = 2
 no_batch = 3
 gui_refuse_filetransfer = 4
 invalid_type = 5
 no_authority = 6 &quot;as of 4.6C
 OTHERS = 7.

 DELETE gt_file WHERE tcode IS INITIAL AND text IS INITIAL.

 DATA: ls_menu_entry TYPE smen_buffc,
 lt_menu_entry TYPE STANDARD TABLE OF smen_buffc,
 ls_web_link TYPE smen_buffi,
 lt_web_link TYPE STANDARD TABLE OF smen_buffi,
 lv_current_par_id TYPE smen_buffc-parent_id.

 FIELD-SYMBOLS: <entry> LIKE LINE OF gt_file,
 <menu> LIKE LINE OF lt_menu_entry,
 <link> TYPE smen_buffi.

 LOOP AT gt_file ASSIGNING <entry>.
 CLEAR: ls_menu_entry.
 ls_menu_entry-object_id = lo_counter->get_new_obj_id( ).
 ls_menu_entry-uname = sy-uname.
 ls_menu_entry-mandt = sy-mandt.

 CASE lcl_tool=>get_menu_type( <entry> ).
 WHEN lcl_tool=>cs_entry_type-top_tcode.
 ls_menu_entry-reporttype = 'TR'.
 ls_menu_entry-parent_id = lcl_counter=>cv_root.
 ls_menu_entry-report = lcl_tool=>get_tcode( <entry>-text ).
 ls_menu_entry-menu_level = lcl_counter=>cv_level1.
 ls_menu_entry-sort_order = lo_counter->get_folder_sort( ).
 APPEND ls_menu_entry-report TO gt_tcodes.
 WHEN lcl_tool=>cs_entry_type-top_wd_app.
 ls_menu_entry-reporttype = 'OT'.
 ls_menu_entry-parent_id = lcl_counter=>cv_root.
 ls_menu_entry-report = lcl_tool=>cv_wd_app_report.
 ls_menu_entry-menu_level = lcl_counter=>cv_level1.
 ls_menu_entry-sort_order = lo_counter->get_folder_sort( ).
 ls_web_link-object_id = ls_menu_entry-object_id.
 APPEND ls_web_link TO lt_web_link.
 ls_menu_entry-text = lcl_tool=>get_wd_app( <entry>-text ).
 APPEND ls_menu_entry-text TO gt_wd_app.
 WHEN lcl_tool=>cs_entry_type-folder.
 ls_menu_entry-text = <entry>-text.
 ls_menu_entry-parent_id = lcl_counter=>cv_root.

 ls_menu_entry-sort_order = lo_counter->get_folder_sort( ).
 ls_menu_entry-menu_level = lcl_counter=>cv_level1.
 lv_current_par_id = ls_menu_entry-object_id.
 lo_counter->reset_tcode_sort( ).
 WHEN lcl_tool=>cs_entry_type-child_tcode.
 ls_menu_entry-reporttype = 'TR'.
 ls_menu_entry-report = lcl_tool=>get_tcode( CONV #( <entry>-tcode ) ).
 ls_menu_entry-parent_id = lv_current_par_id.
 ls_menu_entry-sort_order = lo_counter->get_tcode_sort( ).
 ls_menu_entry-menu_level = lcl_counter=>cv_level2.
 APPEND ls_menu_entry-report TO gt_tcodes.
 WHEN lcl_tool=>cs_entry_type-child_wd_app.
 ls_menu_entry-reporttype = 'OT'.
 ls_menu_entry-report = lcl_tool=>cv_wd_app_report.
 ls_menu_entry-parent_id = lv_current_par_id.
 ls_menu_entry-sort_order = lo_counter->get_tcode_sort( ).
 ls_menu_entry-menu_level = lcl_counter=>cv_level2.
 ls_menu_entry-text = lcl_tool=>get_wd_app( CONV #( <entry>-tcode ) ).
 APPEND ls_menu_entry-text TO gt_wd_app.
 ls_web_link-object_id = ls_menu_entry-object_id.
 APPEND ls_web_link TO lt_web_link.
 WHEN OTHERS.
 WRITE: / 'Invalid record: ', <entry>-text, <entry>-tcode COLOR COL_NEGATIVE.
 RETURN.
 ENDCASE.
 APPEND ls_menu_entry TO lt_menu_entry.
 ENDLOOP.

 lcl_tool=>set_tcode_list( gt_tcodes ).
 lcl_tool=>set_wd_app_list( gt_wd_app ).

 LOOP AT lt_menu_entry ASSIGNING <menu> WHERE reporttype = 'TR'.
 <menu>-text = lcl_tool=>get_tcode_description( <menu>-report ).
 ENDLOOP.

 LOOP AT lt_web_link ASSIGNING <link>.
 <link>-mandt = sy-mandt.
 <link>-link_type = 'W'.
 <link>-uname = sy-uname.
 READ TABLE lt_menu_entry INTO ls_menu_entry WITH KEY object_id = <link>-object_id.
 CHECK sy-subrc = 0.
 TRANSLATE ls_menu_entry-text TO LOWER CASE.
 <link>-url = '0E' && ls_menu_entry-text.
 ENDLOOP.

 LOOP AT lt_menu_entry ASSIGNING <menu> WHERE reporttype = 'OT'.
 <menu>-text = lcl_tool=>get_app_description( <menu>-text ).
 ENDLOOP.

 DELETE FROM smen_buffc WHERE uname = sy-uname.
 DELETE FROM smen_buffi WHERE uname = sy-uname.

 INSERT smen_buffc FROM TABLE lt_menu_entry.
 INSERT smen_buffi FROM TABLE lt_web_link.

 COMMIT WORK AND WAIT.

 WRITE: / 'Favorite list uploaded successfully, total entries: ', lines( lt_menu_entry ) COLOR COL_POSITIVE.

总结

本文首先介绍了 SAP Area Menu 的创建方式,以及标准的收藏夹管理功能和局限性,接着分享了笔者自开发的收藏夹工具增强的功能以及全部的源代码,希望对想提高 SAPGUI 工作效率的使用者有所帮助。
原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/863aee668ab3363e8e643b3e1