20240723笔记-一种多报表平台的通用模式

20240723笔记-一种多报表平台的通用模式

1背景

实际业务会存在,一个业务场景,多个相关Tcode。因此,对于具体的用户来讲,一个多报表平台是很有必要的。

限制于作者的项目经验不多,有不完善的可以补充。

备注:后面的更新(如有),只更新源码,中间的那一块太散了,不想更新。

2已有的案例

作者已知的多报表平台分为两种实现方式,一种是dialog屏幕按钮点击跳转,一种是选择屏幕AT SELECTION-SCREEN OUTPUT跳转。描述的不是很清晰,看下面效果截图。

2.1方案1dialog屏幕跳转

image-20240723183712282

单击按钮,执行SUBMIT xxx VIA SELECTION-SCREEN AND RETURN。

image-20240723183818304

SUBMIT (lv_programname) VIA SELECTION-SCREEN AND RETURN.

2.2方案2AT SELECTION-SCREEN OUTPUT

image-20240723184334284

在用户点击不同的RADIOBUTTON GROUP的时候,触发事件AT SELECTION-SCREEN OUTPUT,更新选择屏幕下侧内容为实际指向程序的选择屏幕。

image-20240723185151544

2.3优缺点

优点缺点
方案1开发速度快,只需要简单了解dialog绘制屏幕无法直观查看到选择屏幕
新增或减少子功能几乎无开发量
方案2可以通过单选按钮,快速查阅选择屏幕开发量大
要求对选择屏幕非常熟悉,各种事件,以及更改screen属性
新增很麻烦,与子功能程序的选择屏幕复杂程度成正比

我就不说为啥会出现方案2了,都是泪。

3新方案

3.1需求背景

在项目推进过程中,经常需要在报表平台新增子功能。开发量非常大,因此作者想设计一个便于移植的,快速配置的模式。当然,是达不到方案1的程度。

3.2方案3基于内存的循环submit跳转方案

名字没想好,就这样。

需要增加配置表

image-20240723190742733

准备好include文件(下附代码),准备好RADIOBUTTON GROUP。

*======================================================================*
*                      Input Selection Screen
*======================================================================*
SELECTION-SCREEN BEGIN OF BLOCK zcommon_head WITH FRAME TITLE text998.

SELECTION-SCREEN:BEGIN OF LINE.
PARAMETERS:p_zzz RADIOBUTTON GROUP rg1 MODIF ID md USER-COMMAND uc1 DEFAULT 'X'.
SELECTION-SCREEN: COMMENT 3(35) text999.
SELECTION-SCREEN:END OF LINE.

SELECTION-SCREEN:BEGIN OF LINE.
PARAMETERS:p_e067  RADIOBUTTON GROUP rg1 MODIF ID a01. "
SELECTION-SCREEN: COMMENT 3(35) text029 MODIF ID a01.
PARAMETERS:p_e068  RADIOBUTTON GROUP rg1 MODIF ID a02. "
SELECTION-SCREEN: COMMENT 43(79) text030 MODIF ID a02.
SELECTION-SCREEN:END OF LINE.

SELECTION-SCREEN END OF BLOCK zcommon_head.

注意COMMENT 3(35) text999,没有使用文本元素。考虑到子功能程序可能是不同的开发做的,所以头文件不使用文本元素防止冲突。

参考SAP标准范例,文本赋值在AT SELECTION-SCREEN OUTPUT.

image-20240723191303588

平台程序代码,只用到两个事件。

AT SELECTION-SCREEN OUTPUT用于获取用户选择的RADIOBUTTON GROUP,判断是否跳转子程序。

INITIALIZATION,获取配置表信息。

REPORT ytest_kevin5.
INCLUDE zcommon_head.
"平台程序自开发模板

AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_get_selectscreen_comment."获取选择屏幕的字段值
  PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕
  PERFORM frm_common_head_jumpto."平台跳转子功能程序

INITIALIZATION.
  PERFORM frm_common_head_init."获取平台程序配置表

PERFORM frm_common_head_init."获取平台程序配置表

image-20240723191918626

FORM frm_common_head_init.
  IF sy-tcode = 'SE38'."如果用户手动执行,找当前程序名的tcode
    "1个程序可能对应多个Tcode,如果遇到这种情况,打一顿开发。打不过开发就把测试的人打一顿。
    SELECT SINGLE tcode FROM tstc
      WHERE pgmna = @sy-repid
      INTO @gv_zcommon_head_tcode.
  ELSE.
    gv_zcommon_head_tcode = sy-tcode.
  ENDIF.
  
  "DEV-test-----这是因为测试程序,没包Tcode,上一步获取不到gv_zcommon_head_tcode
  IF sy-sysid = 'EWD'.
    gv_zcommon_head_tcode = 'YTEST_KEVIN5'.
  ELSEIF AND sy-sysid = 'EWQ'.
    BREAK-POINT.
  ELSE.
  ENDIF.

  IF gv_zcommon_head_tcode IS NOT INITIAL.
    CLEAR:gt_zewmtplatform.
    SELECT *
      FROM zewmtplatform
      WHERE programkey = @gv_zcommon_head_tcode
      INTO TABLE @gt_zewmtplatform.
  ENDIF.
ENDFORM.

PERFORM frm_get_selectscreen_comment."获取选择屏幕的字段值

缺变量定义看后面的源码

FORM frm_get_selectscreen_comment.
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform ."遍历配置表
    UNASSIGN <fs_zcommon_head_linetext>.
    ASSIGN (gs_zewmtplatform-linetext) TO <fs_zcommon_head_linetext>."DEMO:assign 'TEXT029' to 
    IF <fs_zcommon_head_linetext> IS ASSIGNED.
      <fs_zcommon_head_linetext> = gs_zewmtplatform-linetextvalue."选择屏幕的文本 DEMO:ZEWM*** 
    ENDIF.
  ENDLOOP.

*  text001 = 'XXXX'.
*  text002 = 'XXXX'.
ENDFORM.

PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕

快速减少子功能

FORM frm_common_head_modify_screen.
  LOOP AT SCREEN.
    READ TABLE gt_zewmtplatform INTO gs_zewmtplatform WITH KEY linekey = screen-name."linekey举例P_E067"
    IF sy-subrc = 0.
      IF gs_zewmtplatform-zactive = abap_true.
        screen-active = '1'."显示
      ELSE.
        screen-active = '0'.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
    READ TABLE gt_zewmtplatform INTO gs_zewmtplatform WITH KEY linetext = screen-name."linetext举例TEXT029"
    IF sy-subrc = 0.
      IF gs_zewmtplatform-zactive = abap_true.
        screen-active = '1'."显示
      ELSE.
        screen-active = '0'.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.
ENDFORM .

PERFORM frm_common_head_jumpto."平台跳转子功能程序

内存ID建议使用类的常量,方便找引用。直接偷懒写固定文本的,打开发一顿。

FORM frm_common_head_jumpto.
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true."初始化,通过用户在平台程序点击决定跳转到哪个程序
    UNASSIGN <fs_zcommon_head_linekey>.
    ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
    IF <fs_zcommon_head_linekey> IS ASSIGNED.
      IF <fs_zcommon_head_linekey> = abap_true.
        gv_zcommon_head_program = gs_zewmtplatform-linevalue."获取程序名
      ENDIF.
    ENDIF.
  ENDLOOP.
  EXPORT gv_zcommon_head_program = gv_zcommon_head_program TO MEMORY ID 'KW20240723'."写入内存--因为下面是do循环,所以配合一下写入内存
  IF gv_zcommon_head_program IS NOT INITIAL ."点击了屏幕按钮
    DO.
      CLEAR:gv_zcommon_head_program.
      IMPORT gv_zcommon_head_program = gv_zcommon_head_program FROM MEMORY ID 'KW20240723'."读取内存
      IF gv_zcommon_head_program IS NOT INITIAL.
        SUBMIT (gv_zcommon_head_program) VIA SELECTION-SCREEN
          AND RETURN.
      ELSE.
        EXIT.
      ENDIF.
    ENDDO.
    LEAVE PROGRAM.
  ENDIF.
ENDFORM.

自此,平台程序结束。

子程序改造开始。

INITIALIZATION.
  PERFORM frm_common_head_init."获取全局参数
  PERFORM frm_common_line_init."根据程序名,更新选择屏幕值

AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_get_selectscreen_comment."手动更新选择屏幕的文本
  PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕
  PERFORM frm_common_head_leaveprog."判断是否退出程序

PERFORM frm_common_head_init."获取全局参数

PERFORM frm_common_line_init."根据程序名,更新选择屏幕值

FORM frm_common_line_init .
  IMPORT gv_zcommon_head_program = gv_zcommon_head_program FROM MEMORY ID 'KW20240723'."读取内存
  IF gv_zcommon_head_program IS NOT INITIAL ."点击了屏幕按钮
    LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true.
      UNASSIGN <fs_zcommon_head_linekey>.
      ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
      IF <fs_zcommon_head_linekey> IS ASSIGNED.
        IF gs_zewmtplatform-linevalue = gv_zcommon_head_program."如果程序名和配置一致,那么单选打勾"
          <fs_zcommon_head_linekey> = abap_true.
        ELSE.
          <fs_zcommon_head_linekey> = abap_false.
        ENDIF.
      ENDIF.
    ENDLOOP.

    FREE MEMORY ID 'KW20240723'.
  ENDIF.
ENDFORM.

PERFORM frm_get_selectscreen_comment."手动更新选择屏幕的文本

PERFORM frm_common_head_leaveprog."判断是否退出程序

FORM frm_common_head_leaveprog .
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true.
    UNASSIGN <fs_zcommon_head_linekey>.
    ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
    IF <fs_zcommon_head_linekey> IS ASSIGNED.
      IF <fs_zcommon_head_linekey> = abap_true.
        gv_zcommon_head_program = gs_zewmtplatform-linevalue.
      ENDIF.
    ENDIF.
  ENDLOOP.
  IF gv_zcommon_head_program IS NOT INITIAL AND gv_zcommon_head_program <> sy-repid ."点击了屏幕按钮
    FREE MEMORY ID 'KW20240723'.
    EXPORT gv_zcommon_head_program = gv_zcommon_head_program TO MEMORY ID 'KW20240723'."写入内存
    LEAVE PROGRAM.
  ENDIF.
ENDFORM.

推出后,会进入平台程序的DO循环。

综上,实际堆栈只有两层,一层平台程序,一层子功能程序。

3.3当前存在问题

目前拿测试环境试了部分功能。有以下的几个问题。

  • 屏幕操作涉及子功能程序的屏幕,也就是,尽量不要使用必填等强制校验,建议使用screen-required来实现伪必填。
  • 一个通用子功能程序,需要在多个平台程序复用。这个我正在思考怎么处理。
  • 调用标准功能,多次进入返回会出现,超过内部会话。

4源码

平台程序20240815

REPORT ytest_kevin5.
INCLUDE zcommon_head.

"平台程序自开发模板
AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_get_selectscreen_comment."获取选择屏幕的字段值
  PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕
  PERFORM frm_common_head_jumpto."平台跳转子功能程序

INITIALIZATION.
  PERFORM frm_common_head_init."获取平台程序配置表

包含文件

*&---------------------------------------------------------------------*
*&  包含                ZEWME101_HEAD
*&---------------------------------------------------------------------*

DATA:
  gt_zewmtplatform              TYPE TABLE OF zewmtplatform, "程序使用的配置表内表
  gs_zewmtplatform              TYPE zewmtplatform, "程序使用的配置表结构
  gv_zcommon_head_tcode         TYPE tcode, "程序使用的tcode,包含文件的变量要怪一点,一定不要和其他程序重复
  gv_zcommon_head_program       TYPE reposrc-progname, "子功能的程序tcode
  gv_zcommon_head_programname   TYPE reposrc-progname, "子功能的程序名称
  gv_zcommon_head_standardtcode TYPE c, "标准程序准备推出

  gggggggggg                    TYPE c. "瞎写的,懒得空行改标点符号,看不过去的自行调整

FIELD-SYMBOLS:<fs_zcommon_head_linekey>  TYPE c, "子功能缩写在具体程序中,是否选中的标识
              <fs_zcommon_head_linetext> TYPE zewmtplatform-linetextvalue, "子功能文本在程序中显示的描述


              <hhhhhhhhhhhhhh>           TYPE c. "瞎写的,懒得空行改标点符号,看不过去的自行调整

*======================================================================*
*                      Input Selection Screen
*======================================================================*
SELECTION-SCREEN BEGIN OF BLOCK zcommon_head WITH FRAME TITLE text998.

SELECTION-SCREEN:BEGIN OF LINE.
PARAMETERS:p_zzz RADIOBUTTON GROUP rg1 MODIF ID md USER-COMMAND uc1 DEFAULT 'X'.
SELECTION-SCREEN: COMMENT 3(35) text999.
SELECTION-SCREEN:END OF LINE.

SELECTION-SCREEN:BEGIN OF LINE.
PARAMETERS:p_exx1  RADIOBUTTON GROUP rg1 MODIF ID a01. "
SELECTION-SCREEN: COMMENT 3(35) text029 MODIF ID a01.
PARAMETERS:p_exx2  RADIOBUTTON GROUP rg1 MODIF ID a02. "
SELECTION-SCREEN: COMMENT 43(79) text030 MODIF ID a02.
SELECTION-SCREEN:END OF LINE.

SELECTION-SCREEN END OF BLOCK zcommon_head.

FORM frm_get_selectscreen_comment.
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform ."遍历配置表
    UNASSIGN <fs_zcommon_head_linetext>.
    ASSIGN (gs_zewmtplatform-linetext) TO <fs_zcommon_head_linetext>."DEMO:assign 'TEXT029' to
    IF <fs_zcommon_head_linetext> IS ASSIGNED.
      <fs_zcommon_head_linetext> = gs_zewmtplatform-linetextvalue."选择屏幕的文本 DEMO:ZEWM***
    ENDIF.
  ENDLOOP.
ENDFORM.

FORM frm_common_head_init.
  IF sy-tcode = 'SE38'."如果用户手动执行,找当前程序名的tcode
    "1个程序可能对应多个Tcode,如果遇到这种情况,打一顿开发。打不过开发就把测试的人打一顿。
    SELECT SINGLE tcode FROM tstc
      WHERE pgmna = @sy-repid
      INTO @gv_zcommon_head_tcode.
  ELSE.
    gv_zcommon_head_tcode = sy-tcode.
  ENDIF.

*  "DEV-test
*  IF sy-uname = '00104423' AND sy-sysid = 'EWD'.
*    gv_zcommon_head_tcode = 'YTEST_KEVIN5'.
*  ELSEIF sy-uname = '00104423' AND sy-sysid = 'EWQ'.
*    BREAK-POINT.
*  ELSE.
*  ENDIF.

  IF gv_zcommon_head_tcode IS NOT INITIAL.
    CLEAR:gt_zewmtplatform.
    SELECT *
      FROM zewmtplatform
      WHERE programkey = @gv_zcommon_head_tcode
      INTO TABLE @gt_zewmtplatform.
  ENDIF.
*  BREAK-POINT.


ENDFORM.

FORM frm_common_head_modify_screen.
  LOOP AT SCREEN.
    READ TABLE gt_zewmtplatform INTO gs_zewmtplatform WITH KEY linekey = screen-name.
    IF sy-subrc = 0.
      IF gs_zewmtplatform-zactive = abap_true.
        screen-active = '1'."显示
      ELSE.
        screen-active = '0'.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
    READ TABLE gt_zewmtplatform INTO gs_zewmtplatform WITH KEY linetext = screen-name.
    IF sy-subrc = 0.
      IF gs_zewmtplatform-zactive = abap_true.
        screen-active = '1'."显示
      ELSE.
        screen-active = '0'.
      ENDIF.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.
ENDFORM .


FORM frm_common_head_jumpto.
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true."初始化,通过用户在平台程序点击决定跳转到哪个程序
    UNASSIGN <fs_zcommon_head_linekey>.
    ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
    IF <fs_zcommon_head_linekey> IS ASSIGNED.
      IF <fs_zcommon_head_linekey> = abap_true.
        gv_zcommon_head_program = gs_zewmtplatform-linevalue."获取程序名
      ENDIF.
    ENDIF.
  ENDLOOP.
  EXPORT gv_zcommon_head_program = gv_zcommon_head_program TO MEMORY ID 'KW20240723'."写入内存--因为下面是do循环,所以配合一下写入内存
  IF gv_zcommon_head_program IS NOT INITIAL ."点击了屏幕按钮
    DO.
      CLEAR:gv_zcommon_head_program.
      IMPORT gv_zcommon_head_program = gv_zcommon_head_program FROM MEMORY ID 'KW20240723'."读取内存
      IF gv_zcommon_head_program IS NOT INITIAL.
        SELECT SINGLE pgmna
          FROM tstc
          WHERE tcode = @gv_zcommon_head_program
          INTO @gv_zcommon_head_programname.
        IF sy-subrc = 0.
          IF gv_zcommon_head_program+0(1) CA 'ZY' ."如果是自建程序
          ELSE.
            gv_zcommon_head_standardtcode = abap_true.
          ENDIF.
          SUBMIT (gv_zcommon_head_programname) VIA SELECTION-SCREEN
            AND RETURN.
          IF gv_zcommon_head_standardtcode = abap_true.
            CLEAR gv_zcommon_head_standardtcode.
            LEAVE TO SCREEN 0.
            EXPORT gv_zcommon_head_program = sy-tcode TO MEMORY ID 'KW20240723'.
          ENDIF.
        ENDIF.
      ELSE.
        EXIT.
      ENDIF.
    ENDDO.
    LEAVE PROGRAM.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_COMMON_LINE_INIT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_common_line_init .
  IMPORT gv_zcommon_head_program = gv_zcommon_head_program FROM MEMORY ID 'KW20240723'."读取内存
  IF gv_zcommon_head_program IS NOT INITIAL ."点击了屏幕按钮
    LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true.
      UNASSIGN <fs_zcommon_head_linekey>.
      ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
      IF <fs_zcommon_head_linekey> IS ASSIGNED.
        IF gs_zewmtplatform-linevalue = gv_zcommon_head_program.
          <fs_zcommon_head_linekey> = abap_true.
        ELSE.
          <fs_zcommon_head_linekey> = abap_false.
        ENDIF.
      ENDIF.
    ENDLOOP.

    FREE MEMORY ID 'KW20240723'.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_COMMON_HEAD_LEAVEPROG
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_common_head_leaveprog .
  LOOP AT gt_zewmtplatform INTO gs_zewmtplatform WHERE zactive = abap_true.
    UNASSIGN <fs_zcommon_head_linekey>.
    ASSIGN (gs_zewmtplatform-linekey) TO <fs_zcommon_head_linekey>.
    IF <fs_zcommon_head_linekey> IS ASSIGNED.
      IF <fs_zcommon_head_linekey> = abap_true.
        gv_zcommon_head_program = gs_zewmtplatform-linevalue.
      ENDIF.
    ENDIF.
  ENDLOOP.
  IF gv_zcommon_head_program IS NOT INITIAL AND gv_zcommon_head_program <> sy-repid ."点击了屏幕按钮
    FREE MEMORY ID 'KW20240723'.
    EXPORT gv_zcommon_head_program = gv_zcommon_head_program TO MEMORY ID 'KW20240723'."写入内存
    LEAVE PROGRAM.
  ENDIF.
ENDFORM.

子功能程序略,添加下面代码片段即可

INITIALIZATION.
  PERFORM frm_common_head_init."获取全局参数
  PERFORM frm_common_line_init."根据程序名,更新选择屏幕值

AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_get_selectscreen_comment."手动更新选择屏幕的文本
  PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕
  PERFORM frm_common_head_leaveprog."判断是否退出程序

效果图

image-20240815154449929
ID ‘KW20240723’.
EXPORT gv_zcommon_head_program = gv_zcommon_head_program TO MEMORY ID ‘KW20240723’."写入内存
LEAVE PROGRAM.
ENDIF.
ENDFORM.


子功能程序略,添加下面代码片段即可

```abap
INITIALIZATION.
  PERFORM frm_common_head_init."获取全局参数
  PERFORM frm_common_line_init."根据程序名,更新选择屏幕值

AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_get_selectscreen_comment."手动更新选择屏幕的文本
  PERFORM frm_common_head_modify_screen."是否隐藏选择屏幕
  PERFORM frm_common_head_leaveprog."判断是否退出程序

效果图

image-20240815154449929

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值