SAP报表开发

一切开发都来自于需求,需求并不决定开发。当接到需求的时候,一定要进行可行性分析,是否可以进行开发,否则将会严重影响工作效率

1.SAP报表

  • List:原始技术,直接输出数据
  • ALV:简单到复杂,也可以面向对象
  • MS Office Excel:调用excel输出数据

SAP提供多种方式开发报表,这里只介绍常用的ALV报表,其他的大家有兴趣也可以去网上找资料研究一下

2.需求

1)假设有一个客户提出需求开发一个销售订单报表,报表应该包含的字段有:销售订单(so)、行项目、工厂、物料号、库存地点、需求数量、订单数量、创建日期、交货日期等等

2)接到需求进行可行性分析,如果SAP存在可满足需求的报表则不用进行开发或则进行修改;如果不存在则考虑报表开发是否可行,如果能做就准备开发,否则再和客户进行讨论。

3)假设可行性分析OK!

3、如何下手开发

1)从需求入手,分析需求

该报表主要是关于SO,这就是我们需要重点关注的地方

2)熟悉表

报表中的数据是怎么来的?当然并不是凭空产生的,需求中的销售订单、物料号等数据都将取自于数据库。所以得分析需要哪些表。当然你有可能不熟悉SAP中的表,你可以向有经验的同事请教。通过积累,让这些也成为你的东西

T-CODE:se16n可以查询透明表

这里写图片描述

以下是需要用到的一些表和一些重点关注字段,当然在实际中可能会涉及到更多的表和字段

1.【VBAK:销售凭证】
      字段:vbeln(销售凭证)、erdat(创建日期)、ername(创建者)、auart(销售类型)、bstnk(采购订单)、bsark(采购订单类型)、bstdk(采购日期)
2.【VBAP:销售凭证行项目】
       字段:vbeln(销售凭证)、posnr(项目)、matnr(物料)、werks(工厂)、lgort(库存地点)、erdat(销售订单创建日期)、PRCTR(利润中心)、aufnr(订单)
3.【VBPA:销售凭证合作伙伴】
          字段: vbeln(销售凭证)、posnr(项目)、kunnr(客户)、lifnr(供应商)
3.【MAKT:物料描述】
          字段:matnr(物料号)、spras(语言)、maktx(描述)
4.【LIPS:SD凭证交货项目数据】
          字段:vbeln(交货)、posnr(项目)、werks(工厂)、lgort(地点)、lfimg(交货数量)
5.【VBKD:销售凭证业务数据】
          字段: vbeln(销售凭证)、posnr(项目)、bstkd(PO)、inco1(国际贸易条件)、
6.【VBEP:销售凭证计划行数据】
          字段: vbeln(销售凭证)、posnr(项目)、ETENR(计划行)、edatu(交货日期)、ezit(到达时间)、wmeng(订单数量)、lmeng(需求数量)、bmeng(确认的数量)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4、报表开发

1)se38创建程序,创建完会有一行代码

2)自定义输出表结构

REPORT  zbsdr_025.
TABLES:vbak,mara,t001w,vbap,vbep.

*--------------类型池定义
TYPE-POOLS: slis.

DATA:t_fieldcat TYPE slis_t_fieldcat_alv,
     w_fieldcat TYPE LINE OF slis_t_fieldcat_alv,
     t_layout TYPE slis_layout_alv.

*------------------定义输出表结构
TYPES:BEGIN OF ty_result,
     vbeln TYPE vbak-vbeln,   "so
     auart TYPE vbak-auart,   "销售类 型
     posnr TYPE vbap-posnr,   "项目
     bstkd TYPE vbkd-bstkd,   "po
     aufnr TYPE vbap-aufnr,
     werks TYPE vbap-werks,    "工厂
     lgort TYPE vbap-lgort,     "库存地点
     matnr TYPE vbap-matnr,    "物料
     maktx TYPE makt-maktx,
     kunnr TYPE vbpa-kunnr,    "客户
     lifnr  TYPE vbpa-lifnr,   "供应商
*    lfimg TYPE lips-lfimg,     "交货数量
     edatu  TYPE vbep-edatu,   "计划交货日期
     erdat  TYPE vbap-erdat,    "创建日期
     lmeng  TYPE vbep-lmeng,    "需求数量
     wmeng  TYPE vbep-wmeng,    "订单数量

 END OF ty_result.

*-----------------------------定义输出表和工作区域
DATA:t_result TYPE TABLE OF ty_result.
DATA:w_result TYPE ty_result.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
(1)类型池:slis 。类型池顾名思义就是个池子,池子里面有很多的类型。开发ALV报表得用到slis里面的类型,所以要引用slis这个类型池
(2)DATA:主要用于声明变量,【TYPE】表示改变量参考的类型。在报表里一般都定义两个东西:内表和工作区。
(3)内表和工作区。内表可以理解为临时表,对内表操作不影响数据库中的表。如果频繁地从数据库中取数会导致效率降低,所以可以用内表临时存放数据;工作区只能存放一条数据,对数据进行处理,一般用于循环中。
DATA:t_fieldcat TYPE slis_t_fieldcat_alv,
     w_fieldcat TYPE LINE OF slis_t_fieldcat_alv,
     t_layout TYPE slis_layout_alv.
  • 1
  • 2
  • 3
(4) se11查看类型池,如果不知道变量参考的类型可以在这里查找,比如ALV报表字段(我们取名t_fieldcat)

这里写图片描述
这里写图片描述

(5)TYPES自定义结构,可以的字段可以来自于不同的表,一般先定义输出表结构(把报表需要展示的字段都放在一个结构里),当然为了后面的操作也要定义内表和工作区,参考的类型就是该结构
DATA:t_result TYPE TABLE OF ty_result.
DATA:w_result TYPE ty_result.
  • 1
  • 2

2)声明所需表

TYPES:BEGIN OF ty_vbakp,
    vbeln TYPE vbak-vbeln,   "so
    auart TYPE vbak-auart,   "销售类型
    posnr TYPE vbap-posnr,   "项目
    werks TYPE vbap-werks,    "工厂
    lgort TYPE vbap-lgort,     "库存地点
    matnr TYPE vbap-matnr,    "物料
    erdat  TYPE vbap-erdat,    "创建日期
    bstkd TYPE vbkd-bstkd,   "po
END OF ty_vbakp.

DATA:t_vbakp TYPE TABLE OF ty_vbakp,
     w_vbakp TYPE ty_vbakp.


*----------------------------------------------
"引入makt主要是为了获取物料描述信息
DATA:t_makt TYPE STANDARD TABLE OF makt,
     w_makt TYPE makt.
DATA:rt_extab TYPE slis_t_extab.

*----------------------------------------------
"引入vbpa主要是为了获取客户和供应商
DATA:t_vbpa TYPE STANDARD TABLE OF vbpa,
     w_vbpa TYPE vbpa.
*-------------------------------------------
"为获取计划交货时间,需求数量,订单数量
data:t_vbep type STANDARD TABLE OF vbep,
     w_vbep type vbep.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
需要什么,就声明什么。比如需要获取物料描述信息就定义一个内表参考类型为物料描述表(makt),如果需要的多个表有联系,也可以定义结构,把所需字段放在结构里。如上面的结构ty_vbakp.(表vbak,vbap,vbkd都有销售凭证字段)

3)选择屏幕

*-------------------------------定义选择屏幕
SELECTION-SCREEN:BEGIN OF BLOCK a1 WITH FRAME TITLE text-001.
SELECT-OPTIONS:s_vbeln FOR vbak-vbeln,
               s_matnr FOR mara-matnr,
               s_werks FOR t001w-werks,
               s_erdat FOR vbap-erdat,      "创建日期
               s_edatu FOR vbep-edatu.      "交货日期

SELECTION-SCREEN:END OF BLOCK a1.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
(1)选择屏幕就是SAP的前台,一般是一些查询条件

这里写图片描述

(2)select-options 可以进行多值查询(有范围的),如上图会有两个输入框。比如用户想查询1000到1010工厂的销售订单。点击输入框后面的搜索按钮,会从数据库里查询,关键字【FOR】后面就是的数据源。要注意的是,select-options里的数据源表都要在TABLES里声明下不然会出错。
TABLES:vbak,mara,t001w,vbap,vbep.
SELECT-OPTIONS:s_vbeln FOR vbak-vbeln.
  • 1
  • 2
(3)parameters 用于单值查询
PARAMETERS p_matnr like mara-matnr.
  • 1

这里写图片描述

(4)设置选择屏幕的文本值

这里写图片描述
这里写图片描述

4)获取数据

START-OF-SELECTION.
*-----------------------获取数据
  PERFORM frm_get_data.

*-------------------------处理数据
  PERFORM frm_handle_data.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*

  IF t_result IS NOT INITIAL.
    PERFORM frm_alv_show.
  ELSE.
    MESSAGE '没有符合的数据,请重新查询' TYPE 'S' DISPLAY LIKE 'E'.
  ENDIF.

END-OF-SELECTION.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
(1)START-OF-SELECTION.程序的开始,PERFORM frm_get_data可以创建子程序,点击子程序名系统自动创建,选第二个,子程序会包含在当前程序里面,如下

这里写图片描述

FORM frm_get_data .
  SELECT * INTO CORRESPONDING FIELDS OF TABLE t_vbakp
           FROM vbak
                JOIN vbap ON vbak~vbeln = vbap~vbeln
                JOIN vbkd ON vbap~vbeln = vbkd~vbeln AND vbap~posnr = vbkd~posnr
                WHERE vbak~vbeln IN s_vbeln
                      AND vbap~werks IN s_werks
                      AND vbap~matnr IN s_matnr
                      AND vbap~erdat IN s_erdat.

  IF t_vbakp[] IS NOT INITIAL.
*物料描述
    SELECT * INTO TABLE t_makt
             FROM makt
             FOR ALL ENTRIES IN t_vbakp
             WHERE matnr = t_vbakp-matnr.

* 客户供应商
    SELECT * INTO CORRESPONDING FIELDS OF TABLE t_vbpa
             FROM vbpa
             FOR ALL ENTRIES IN t_vbakp
             WHERE vbpa~vbeln = t_vbakp-vbeln.
*                    AND vbpa~posnr = t_vbakp-posnr.

*计划交货时间
    SELECT *  INTO CORRESPONDING FIELDS OF TABLE t_vbep
              from vbep
              FOR ALL ENTRIES IN t_vbakp
              where vbeln = t_vbakp-vbeln
                    and posnr = t_vbakp-posnr
                    and edatu in s_edatu.
  ENDIF.

ENDFORM.                    " FRM_GET_DATA
*&---------------------------------------------------------------------*
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
(2)INTO CORRESPONDING FIELDS OF TABLE XXX:一般会把查询到的数据存放到内表对应的字段里
(3) JOIN…ON…:可以把两张表进行关联,ON后面的就是条件,但是不建议关联太多张表,会导致效率下降
(4)IS NOT INITIAL 判断不为空
(5) FOR ALL ENTRIES IN:相当于一个子查询。假设上面代码通过第一个select语句后,t_vbakp有值了。我们还想获取物料描述,当然可以直接从物料描述表(makt)里取,但是好多不是我们需要的,所以要加个条件,条件就是内表t_vbakp里的物料(matnr)即获取这些物料的物料描述。最后再把数据存放在内表t_makt里,所以t_makt就有了我们需要的物料描述
*物料描述
    SELECT * INTO TABLE t_makt
             FROM makt
             FOR ALL ENTRIES IN t_vbakp
             WHERE matnr = t_vbakp-matnr.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

5)处理数据

(1)和之前一样创建一个子程序
FORM frm_handle_data .
  CLEAR w_vbakp.
  LOOP AT t_vbakp INTO w_vbakp.
    w_result-auart = w_vbakp-auart.
    w_result-vbeln = w_vbakp-vbeln.
    w_result-werks = w_vbakp-werks.
    w_result-lgort = w_vbakp-lgort.
    w_result-posnr = w_vbakp-posnr.
    w_result-matnr = w_vbakp-matnr.
    w_result-erdat = w_vbakp-erdat.
    w_result-bstkd = w_vbakp-bstkd.

    READ TABLE t_makt INTO w_makt
          WITH  KEY matnr = w_vbakp-matnr.

    IF sy-subrc = 0.
      w_result-maktx = w_makt-maktx.
    ENDIF.

    READ TABLE t_vbep INTO w_vbep
          WITH  KEY vbeln  = w_vbakp-vbeln
                    posnr  = w_vbakp-posnr.
    IF sy-subrc = 0.
      w_result-lmeng = w_vbep-lmeng.
      w_result-wmeng = w_vbep-wmeng.
      w_result-edatu = w_vbep-edatu.
    ENDIF.


    READ TABLE t_vbpa INTO w_vbpa
             WITH  KEY vbeln  = w_vbakp-vbeln.
*                       posnr = w_vbakp-posnr.
    IF sy-subrc = 0.
      w_result-kunnr = w_vbpa-kunnr.
      w_result-lifnr = w_vbpa-lifnr.
    ENDIF.

    APPEND w_result TO t_result.
  ENDLOOP.
  CLEAR w_result.
ENDFORM.                    " FRM_HANDLE_DATA
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
(2)一般建议使用工作区前先清空工作区
(3)LOOP AT … INTO…. :主要用于循环内表,把内表数据一条一条取出来into到工作区里(马上要工作了^_^)
    w_result-auart = w_vbakp-auart.
    w_result-vbeln = w_vbakp-vbeln.
    w_result-werks = w_vbakp-werks.
    w_result-lgort = w_vbakp-lgort.
    w_result-posnr = w_vbakp-posnr.
    w_result-matnr = w_vbakp-matnr.
    w_result-erdat = w_vbakp-erdat.
    w_result-bstkd = w_vbakp-bstkd.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
(4)上面循环的内表有很多需要的数据直接赋值给工作区w_result就可以
(5)对于循环内表t_vbakp没有的,比如物料描述信息等就要从其他地方取。前面我们已经获取了物料描述信息放在了内表t_makt里, 在这一步要做的是去取出物料对应的物料描述,就用到了READ TABLE …INTO…
(6)READ TABLE …INTO…WITH KEY…:主要用于读取内表数据into到工作区间,条件就是with key后面的。假设内表t_vbakp里有个物料112,当循环到这条记录时,就以这个物料号为条件去t_makt中查,有的话就把数据取出来放在工作区w_makt里。
READ TABLE t_makt INTO w_makt
          WITH  KEY matnr = w_vbakp-matnr.

    IF sy-subrc = 0.
      w_result-maktx = w_makt-maktx.
    ENDIF.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
(7)sy-subrc = 0表示语句运行成功。如果成功就给工作区w_result的物料描述赋值,但是read table只取一条数据,什么意思呢?比如说物料112有两个物料描述,但是w_makt工作区的物料描述就取第一条,因为工作区只能放一条数据。
(8)APPEND… to…:一般把工作区的数据添加到内表里。每一次循环都是给工作区w_result里的字段赋值,赋值完再把工作区添加到内表t_result里。即每次循环都往内表存数据。

6)展示ALV

创建子程序frm_alv_show,子程序里再创建以下几个程序。子程序可以让报表可读性增强,双击程序名可以快速定位到对应的位置

FORM frm_alv_show.
  PERFORM frm_init_layout.
  PERFORM frm_set_fieldset.
  PERFORM frm_output_alv.
  PERFORM f_status USING rt_extab .
ENDFORM.                    "frm_alv_show
*&---------------------------------------------------------------------*
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
(1)PERFORM frm_init_layout.
初始化ALV布局,可以自动根据数据长度调整列宽
FORM frm_init_layout .
  t_layout-colwidth_optimize = 'X'.
  t_layout-zebra = 'X'.
*t_layout-box_fieldname = 'BOX'.
ENDFORM.  
  • 1
  • 2
  • 3
  • 4
  • 5
(2)PERFORM frm_set_fieldset:
该子程序主要用于设置ALV字段
FORM frm_set_fieldset .

  PERFORM frm_init_fieldcat USING 'VBELN' '销售凭证'.
  PERFORM frm_init_fieldcat USING 'AUART' '销售类型'.
  PERFORM frm_init_fieldcat USING 'WERKS' '工厂'.
  PERFORM frm_init_fieldcat USING 'LGORT' '库存地点'.
  PERFORM frm_init_fieldcat USING 'POSNR' '项目'.
  PERFORM frm_init_fieldcat USING 'MATNR' '物料'.
  PERFORM frm_init_fieldcat USING 'MAKTX' '物料描述'.
  PERFORM frm_init_fieldcat USING 'ERDAT' '创建日期'.
  PERFORM frm_init_fieldcat USING 'EDATU' '计划交货日期'.
  PERFORM frm_init_fieldcat USING 'KUNNR' '客户'.
  PERFORM frm_init_fieldcat USING 'LIFNR' '供应商'.
  PERFORM frm_init_fieldcat USING 'BSTKD' 'PO'.
  PERFORM frm_init_fieldcat USING 'LMENG' '订单数量'.
  PERFORM frm_init_fieldcat USING 'WMENG' '需求数量'.

ENDFORM.                    " FRM_SET_FIELDSET
*&---------------------------------------------------------------------*
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
这里的字段就是ALV报表即将显示的字段,注意这里的字段名都必须大写否则报错
可以看到该程序里面又有一个子程序frm_init_fieldcat,SAP通过USING传递参数,对应子程序的参数。
 PERFORM frm_init_fieldcat USING 'VBELN' '销售凭证'.
  • 1
FORM frm_init_fieldcat  USING    fieldcatname LIKE w_fieldcat-fieldname
                                  seltext LIKE w_fieldcat-seltext_l.
  CLEAR w_fieldcat.
  w_fieldcat-fieldname = fieldcatname .
  w_fieldcat-seltext_m = seltext.
  w_fieldcat-seltext_l = seltext.
  w_fieldcat-seltext_s = seltext.

  APPEND w_fieldcat TO t_fieldcat.

ENDFORM.     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
frm_init_fieldcat 通过using 接收参数,这里有两个参数:字段和字段描述。
(3)PERFORM frm_output_alv.
这里需要调用函数[‘REUSE_ALV_GRID_DISPLAY’]输出ALV

这里写图片描述

FORM frm_output_alv .
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
  EXPORTING
*       I_INTERFACE_CHECK                 = ' '
*       I_BYPASSING_BUFFER                = ' '
*       I_BUFFER_ACTIVE                   = ' '
    i_callback_program                = sy-repid
    i_callback_pf_status_set          = 'F_STATUS '
*       I_CALLBACK_USER_COMMAND           = ' '
*       I_CALLBACK_TOP_OF_PAGE            = ' '
*       I_CALLBACK_HTML_TOP_OF_PAGE       = ' '
*       I_CALLBACK_HTML_END_OF_LIST       = ' '
*       I_STRUCTURE_NAME                  =
*       I_BACKGROUND_ID                   = ' '
*       I_GRID_TITLE                      =
*       I_GRID_SETTINGS                   =
    is_layout                         = t_layout
    it_fieldcat                       = t_fieldcat
*       IT_EXCLUDING                      =
*       IT_SPECIAL_GROUPS                 =
*       IT_SORT                           =
*       IT_FILTER                         =
*       IS_SEL_HIDE                       =
*       I_DEFAULT                         = 'X'
*       I_SAVE                            = ' '
*       IS_VARIANT                        =
*       IT_EVENTS                         =
*       IT_EVENT_EXIT                     =
*       IS_PRINT                          =
*       IS_REPREP_ID                      =
*       I_SCREEN_START_COLUMN             = 0
*       I_SCREEN_START_LINE               = 0
*       I_SCREEN_END_COLUMN               = 0
*       I_SCREEN_END_LINE                 = 0
*       I_HTML_HEIGHT_TOP                 = 0
*       I_HTML_HEIGHT_END                 = 0
*       IT_ALV_GRAPHICS                   =
*       IT_HYPERLINK                      =
*       IT_ADD_FIELDCAT                   =
*       IT_EXCEPT_QINFO                   =
*       IR_SALV_FULLSCREEN_ADAPTER        =
*     IMPORTING
*       E_EXIT_CAUSED_BY_CALLER           =
*       ES_EXIT_CAUSED_BY_USER            =
    TABLES
      t_outtab                          = t_result
*     EXCEPTIONS
*       PROGRAM_ERROR                     = 1
*       OTHERS                            = 2
            .
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

ENDFORM.                    " FRM_OUTPUT_ALV
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
上面的t_outtab就是要输出的ALV表即t_result表。
(4)创建状态
没有状态ALV报表状态栏上的按钮都不能用

这里写图片描述

看看状态里有什么,直接双击状态名

这里写图片描述

FORM f_status USING rt_extab TYPE slis_t_extab.
  SET PF-STATUS 'STANDARD_FULLSCREEN' EXCLUDING rt_extab.
ENDFORM.                    "FRM_PLATFORM_O
  • 1
  • 2
  • 3

5.效果

这里写图片描述

你可能感兴趣的:(SAP,SAP)