记一个外围系统取SAP报表相关

文章讲述了作者为了解决BI系统中频繁调整SAP数据取数问题,创建了一个统一接口,通过RFC调用报表并进行数据格式化,以提高效率和数据一致性。关键部分包括报表映射表、ZCL_BI_DATA_PROCE类及其方法实现。
摘要由CSDN通过智能技术生成

最新版本源码见我的GitHub

看效果

8d65c066bb474cc4bdab6f100c3e5246.png

为啥写这个

前段时间BI那边调整、新增了不少取SAP数据的工作,之前的取数方式都是调用的RFC,这些RFC里面有是沿用的报表的逻辑,有的是submit调用的报表,调整起来比较费时间,还不一定能保证SAP的数据和BI的一致,因此想到了做一个统一的接口供外围系统调用,这样以后新增或者调整接口也不需要开发介入,也能保证两边数据的一致性,同时为了保证返回的数据格式一致性,我也对返回数据进行了格式化处理。

相关构成

报表选择屏幕字段与外围系统入参映射表

ZTBICONFIG

6bbb4f5d73ec4dbd9fb8c5e45ec973fa.jpeg

解析调用报表的事务码和请求参数的类(SICF发布这个类)

ZCL_BI_DATA_PROCE

CLASS zcl_bi_data_proce DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_http_extension .

    METHODS get_query
      IMPORTING
        VALUE(query_string) TYPE string
        VALUE(key)          TYPE string
      EXPORTING
        VALUE(value)        TYPE string .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS ZCL_BI_DATA_PROCE IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BI_DATA_PROCE->GET_QUERY
* +-------------------------------------------------------------------------------------------------+
* | [--->] QUERY_STRING                   TYPE        STRING
* | [--->] KEY                            TYPE        STRING
* | [<---] VALUE                          TYPE        STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD get_query.
    DATA:lt_kv_tab TYPE TABLE OF string,
         BEGIN OF wa_kv,
           key   TYPE string,
           value TYPE string,
         END OF wa_kv,
         lt_kv LIKE TABLE OF wa_kv.
    CLEAR:lt_kv_tab,wa_kv,lt_kv.
    SPLIT query_string AT '&' INTO TABLE lt_kv_tab.

    LOOP AT lt_kv_tab ASSIGNING FIELD-SYMBOL(<lt_kv_tab>).
      CLEAR wa_kv.
      SPLIT <lt_kv_tab> AT '=' INTO wa_kv-key wa_kv-value.
      APPEND wa_kv TO lt_kv.
    ENDLOOP.
    READ TABLE lt_kv INTO wa_kv WITH KEY key = key.
    IF sy-subrc EQ 0.
      value = wa_kv-value.
    ENDIF.
  ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_BI_DATA_PROCE->IF_HTTP_EXTENSION~HANDLE_REQUEST
* +-------------------------------------------------------------------------------------------------+
* | [--->] SERVER                         TYPE REF TO IF_HTTP_SERVER
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD if_http_extension~handle_request.
    DATA:it_tihttpnvp TYPE tihttpnvp,
         wa_tihttpnvp TYPE ihttpnvp,
         json         TYPE string,
         rtype        TYPE bapi_mtype,
         rtmsg        TYPE bapi_msg,
         tcode_str    TYPE string,
         tcode        TYPE sy-tcode.

    CLEAR:wa_tihttpnvp,it_tihttpnvp,json,rtype,rtmsg,tcode_str,tcode.

    server->request->get_header_fields( CHANGING fields = it_tihttpnvp ).
    READ TABLE it_tihttpnvp INTO DATA(wa_tih) WITH KEY name = '~query_string' .
    IF sy-subrc EQ 0.
      CALL METHOD me->get_query
        EXPORTING
          query_string = wa_tih-value
          key          = 'tcode'
        IMPORTING
          value        = tcode_str.
      tcode = to_upper( tcode_str ).
    ENDIF.
    READ TABLE it_tihttpnvp INTO wa_tihttpnvp WITH KEY name = '~request_method' .
    CASE wa_tihttpnvp-value.
      WHEN 'GET' OR 'POST'.
        json = server->request->if_http_entity~get_cdata( ).
        CALL FUNCTION 'ZFM_BI_DATA_PROC'
          EXPORTING
            tcode    = tcode
            in_json  = json
          IMPORTING
            rtype    = rtype
            rtmsg    = rtmsg
            out_json = json.
        IF json IS INITIAL.
          json = '[]'.
        ENDIF.
      WHEN OTHERS.
        rtype    = 'E'.
        rtmsg = '方法只允许GET或者POST'.
        json = '[]'.
    ENDCASE.

    CONCATENATE `{ "rtype":"` rtype `", "rtmsg":"` rtmsg `", "data":` json `}` INTO json.
    server->response->set_header_field( name = 'Content-Type' value = 'application/json;charset=utf-8' ).
    server->response->set_cdata( EXPORTING data   = json ).

  ENDMETHOD.
ENDCLASS.

处理报表取数的RFC

FUNCTION zfm_bi_data_proc.
*"----------------------------------------------------------------------
*"*"本地接口:
*"  IMPORTING
*"     VALUE(TCODE) TYPE  SY-TCODE
*"     VALUE(IN_JSON) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(RTYPE) TYPE  BAPI_MTYPE
*"     VALUE(RTMSG) TYPE  BAPI_MSG
*"     VALUE(OUT_JSON) TYPE  STRING
*"----------------------------------------------------------------------
  IF tcode IS INITIAL.
    rtype = 'E'.
    rtmsg = 'tcode不能为空'.
    EXIT.
  ENDIF.
  SELECT SINGLE * FROM tstc
    WHERE tcode = @tcode
    INTO @DATA(wa_tstc)
          .
  IF sy-subrc NE 0.
    rtype = 'E'.
    rtmsg = 'tcode:' && tcode && '不存在'
    EXIT.
  ENDIF.
  DATA:submit_data     TYPE REF TO data,
       ls_data         TYPE REF TO data,
       seltab          TYPE TABLE OF rsparams,
       seltab_wa       LIKE LINE OF seltab,
       pri_params      TYPE pri_params,
       gt_rsparams     TYPE TABLE OF rsparams,
       gt_rsparams_255 TYPE TABLE OF rsparamsl_255,
       sign_range      TYPE RANGE OF rsparams-sign,
       option_range    TYPE RANGE OF rsparams-option.
  FIELD-SYMBOLS:<submit_data> TYPE any.
  CALL FUNCTION 'RS_REFRESH_FROM_SELECTOPTIONS'
    EXPORTING
      curr_report     = wa_tstc-pgmna
* IMPORTING
*     SP              =
    TABLES
      selection_table = gt_rsparams
*     selection_table_255 = gt_rsparams_255
    EXCEPTIONS
      not_found       = 1
      no_report       = 2
      OTHERS          = 3.
  IF sy-subrc <> 0.
    rtype = 'E'.
    rtmsg = 'tcode:' && tcode && '获取选择屏幕参数出现问题'.
    EXIT.
  ENDIF.
  CLEAR submit_data.
  UNASSIGN <submit_data>.
  /ui2/cl_json=>deserialize( EXPORTING json = in_json CHANGING data = submit_data ).
  IF submit_data IS NOT INITIAL.
    ASSIGN submit_data->* TO <submit_data>.
  ENDIF.
  CLEAR:seltab,seltab_wa.
  SELECT * FROM ztbiconfig
    WHERE tcode = @tcode
    ORDER BY selname,zindex
    INTO TABLE @DATA(gt_biconf)
          .
  IF gt_rsparams IS NOT INITIAL AND gt_biconf IS INITIAL.
    rtype = 'E'.
    rtmsg = '请配置ZTBICONFIG表tcode:' && tcode && '的选择屏幕参数后再试'.
    EXIT.
  ENDIF.
  sign_range = VALUE #( sign = 'I' option = 'EQ'
  ( low = '' )
  ( low = 'I' )
  ( low = 'E' )
    ).
  option_range = VALUE #( sign = 'I' option = 'EQ'
  ( low = '' )
  ( low = 'EQ' )
  ( low = 'NE' )
  ( low = 'GT' )
  ( low = 'LT' )
  ( low = 'GE' )
  ( low = 'LE' )
  ( low = 'CP' )
  ( low = 'NP' )
  ( low = 'BT' )
  ( low = 'NB' )
    ).

  CLEAR:seltab,seltab_wa.
  LOOP AT gt_biconf ASSIGNING FIELD-SYMBOL(<gt_biconf>).
    READ TABLE gt_rsparams ASSIGNING FIELD-SYMBOL(<gt_rsparams>) WITH KEY selname = <gt_biconf>-selname.
    IF sy-subrc NE 0.
      rtype = 'E'.
      rtmsg = 'tcode:' && tcode && '选择屏幕参数' &&  <gt_biconf>-selname && '不存在'
      RETURN.
    ENDIF.
    CLEAR:seltab_wa.
    "赋屏幕参数名称和类型
    seltab_wa-selname = <gt_rsparams>-selname.
    seltab_wa-kind = <gt_rsparams>-kind.
    IF <gt_biconf>-sign NOT IN sign_range.
      rtype = 'E'.
      rtmsg = 'tcode:' && tcode && '选择屏幕参数' &&  <gt_biconf>-selname && '的SIGN值' && <gt_biconf>-sign &&'配置不正确'.
      RETURN.
    ENDIF.
    seltab_wa-sign = <gt_biconf>-sign.
    IF <gt_biconf>-zoption NOT IN option_range.
      rtype = 'E'.
      rtmsg = 'tcode:' && tcode && '选择屏幕参数' &&  <gt_biconf>-selname && '的ZOPTION值' && <gt_biconf>-zoption &&'配置不正确'.
      RETURN.
    ENDIF.
    seltab_wa-option = <gt_biconf>-zoption.
    "判断屏幕参数有没有映射,优先以底表配置的默认值为准
    "下限
    IF <gt_biconf>-low IS NOT INITIAL.
      seltab_wa-low = <gt_biconf>-low.
    ELSE."底表没配置的默认值则取值传递值
      IF <gt_biconf>-low_map IS INITIAL."传递值和报表字段名一致的话底表无需配置映射字段名
        <gt_biconf>-low_map = <gt_biconf>-selname.
      ENDIF.
      IF <submit_data> IS ASSIGNED.
        DATA(field_low) = |<SUBMIT_DATA>-{ <gt_biconf>-low_map }->*|.
        ASSIGN (field_low) TO FIELD-SYMBOL(<submit_data_value_low>).
        IF sy-subrc EQ 0.
          seltab_wa-low = <submit_data_value_low>.
        ELSE.
          rtype = 'E'.
          rtmsg = 'tcode:' && tcode && '选择屏幕参数' &&  <gt_biconf>-selname && '的映射字段' && <gt_biconf>-low_map && '未获取到'.
          RETURN.
        ENDIF.
        UNASSIGN <submit_data_value_low>.
      ELSE.
        rtype = 'E'.
        rtmsg = 'tcode:' && tcode && '请传递选择屏幕参数' &&  <gt_biconf>-selname && '的映射字段' &&  <gt_biconf>-low_map.
        RETURN.
      ENDIF.
    ENDIF.
    "上限
    IF <gt_rsparams>-kind = 'S'.
      IF <gt_biconf>-high IS NOT INITIAL.
        seltab_wa-high = <gt_biconf>-high.
      ELSE.
        IF <gt_biconf>-high_map IS NOT INITIAL.
          IF <submit_data> IS ASSIGNED.
            DATA(field_high) = |<SUBMIT_DATA>-{ <gt_biconf>-high_map }->*|.
            ASSIGN (field_high) TO FIELD-SYMBOL(<submit_data_value_high>).
            IF sy-subrc EQ 0.
              seltab_wa-high = <submit_data_value_high>.
            ELSE.
              rtype = 'E'.
              rtmsg = 'tcode:' && tcode && '选择屏幕参数' &&  <gt_biconf>-selname && '的映射字段' && <gt_biconf>-high_map && '未获取到'.
              RETURN.
            ENDIF.
            UNASSIGN <submit_data_value_high>.
          ELSE.
            rtype = 'E'.
            rtmsg = 'tcode:' && tcode && '请传递选择屏幕参数' &&  <gt_biconf>-selname && '的映射字段' &&  <gt_biconf>-high_map.
            RETURN.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.
    "赋值选择参数
    IF seltab_wa-sign IS INITIAL.
      seltab_wa-sign = 'I'.
    ENDIF.
    CASE <gt_rsparams>-kind.
      WHEN 'P'.
        IF seltab_wa-option IS INITIAL.
          seltab_wa-option = 'EQ'.
        ENDIF.
        CLEAR:seltab_wa-high.
      WHEN 'S'.
        IF seltab_wa-high IS NOT INITIAL AND  seltab_wa-low IS NOT INITIAL.
          IF seltab_wa-high LT seltab_wa-low.
            rtype = 'E'.
            rtmsg = 'tcode:' && tcode && '传递选择屏幕参数' &&  <gt_biconf>-selname && '的上限' &&  seltab_wa-high && '不能小于下限' && seltab_wa-low.
            RETURN.
          ENDIF.
          IF seltab_wa-sign IS INITIAL.
            seltab_wa-option = 'BT'.
          ENDIF.
        ELSEIF seltab_wa-high IS NOT INITIAL AND  seltab_wa-low IS INITIAL.
          IF seltab_wa-sign IS INITIAL.
            seltab_wa-option = 'BT'.
          ENDIF.
        ELSEIF seltab_wa-high IS INITIAL AND  seltab_wa-low IS NOT INITIAL.
          IF seltab_wa-sign IS INITIAL.
            seltab_wa-option = 'EQ'.
          ENDIF.
        ELSEIF seltab_wa-high IS INITIAL AND  seltab_wa-low IS INITIAL.
          CONTINUE.
        ENDIF.
    ENDCASE.

    IF to_lower( seltab_wa-low ) = 'true'.
      seltab_wa-low = 'X'.
    ELSEIF to_lower( seltab_wa-low ) = 'false'.
      seltab_wa-low = ''.
    ENDIF.
    APPEND seltab_wa TO seltab.
  ENDLOOP.

  cl_salv_bs_runtime_info=>set( display = abap_false metadata = abap_false data  = abap_true ).

  SUBMIT (wa_tstc-pgmna) TO SAP-SPOOL SPOOL PARAMETERS pri_params WITHOUT SPOOL DYNPRO
  WITH SELECTION-TABLE seltab
  AND RETURN
    .
  TRY .
      cl_salv_bs_runtime_info=>get_data_ref(
      IMPORTING r_data = ls_data ).
    CATCH  cx_salv_bs_sc_runtime_info.
      rtype = 'E'.
      rtmsg = '无法获取' && tcode && '的数据'.
      EXIT.
  ENDTRY.
  ASSIGN ls_data->* TO FIELD-SYMBOL(<fs_tab>).
  cl_salv_bs_runtime_info=>clear_all( ).

  IF <fs_tab> IS ASSIGNED.
    rtype = 'S'.
    IF <fs_tab> IS NOT INITIAL.
      rtmsg = '成功获取' && tcode && '的数据'.
      out_json = /ui2/cl_json=>serialize( data = <fs_tab>  compress = abap_false pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
    ELSE.
      rtmsg = tcode && '空数据'.
    ENDIF.
    UNASSIGN <fs_tab>.
  ELSE.
    rtype = 'S'.
    rtmsg = tcode && '无数据'.
  ENDIF.

ENDFUNCTION.

外围系统SAP系统之间的对接可以通过以下种方式实现: IDoc(Intermediate Document):IDoc是SAP系统内部使用的标准数据交换格式,外围系统可以通过生成或解析IDoc来与SAP系统进行数据交互。外围系统将数据转换为IDoc格式后,通过与SAP系统的接口进行传输,SAP系统接收到IDoc后解析并进行相应的处理。 2. RFC(Remote Function Call):RFC是SAP系统提供的一种远程调用机制,外围系统可以通过调用SAP系统中的RFC函数模块来实现与SAP系统的交互。外围系统通过RFC接口向SAP系统发送请求,并获相应的返回结果。 3. BAPI(Business Application Programming Interface):BAPI是SAP系统提供的可重用的业务功能接口,外围系统可以通过调用BAPI来与SAP系统交互。BAPI提供了一组标准化的函数模块,用于执行特定的业务功能,外围系统可以通过调用这些函数模块来读或更新SAP系统中的数据。 4. Web服务:SAP系统可以作为Web服务的提供者,外围系统可以通过调用SAP系统中发布的Web服务来实现与SAP系统的数据交换。Web服务使用标准的HTTP协议和XML格式进行通信,外围系统通过发送SOAP请求来调用SAP系统中的Web服务,并获相应的响应数据。 5. 文件接口:外围系统可以通过生成特定格式的文件(如CSV、XML等),将数据导出到文件中,然后通过文件传输方式(FTP、SFTP等)将文件发送给SAP系统SAP系统接收到文件后进行解析和处理。 以上是常见的外围系统SAP系统对接的方式,具体选择哪种方式决于项目需求、系统能力和实施成本等因素。在对接过程中,需要确保数据的准确性、完整性和安全性,并进行必要的数据转换和映射。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值