当前位置: 代码迷 >> 综合 >> SAP-ABAP-后台导出大批量数据及本地导出数据程序
  详细解决方案

SAP-ABAP-后台导出大批量数据及本地导出数据程序

热度:9   发布时间:2023-12-13 04:18:57.0

为了应对审计导出大量凭证的要求,写了此程序来导出bkpf及bseg表数据,此程序分两种导出方式,导出至本地及导出至服务器,因为数据量巨大,所以也支持后台导出至服务器(导出至本地不支持后台执行,sap服务器没办法把文件写到本地)。

经过测试导出到服务器的速度目前是,100万张凭证生成一个100兆的文件导出时间1分钟左右,但是这种方法有个弊端就是无法控制单元格格式(如果有大佬知道,欢迎留言)只能控制单元格写入的内容

程序设计的思路:

1.创建个自建表,维护两个表中需要导出的字段清单

2.取自建表清单数据,构造动态内表

3.构造动态取表字段数据

4.将动态数据存储至动态内表

5.根据自建表取表字段的描述,构造导出结构的表头

6.循环取到数据的动态内表,构造导出文件

7.导出至本地或者服务器

具体代码如下

*&---------------------------------------------------------------------*
*& Report ZFIR252
*&---------------------------------------------------------------------*
*& author 李强 Qunending 2022.01.04 18273737253 https://blog.csdn.net/Qunending?spm=1019.2139.3001.5343
*&---------------------------------------------------------------------*
REPORT ZFIR252.TABLES :BKPF,BSEG.
TABLES:SSCRFIELDS.
DATA:OK_CODE LIKE SY-UCOMM.
DATA:STBL TYPE LVC_S_STBL.
DATA: GT_FIELD  TYPE LVC_T_FCAT.
DATA: GT_FIELD2 TYPE LVC_T_FCAT.
DATA: GS_FIELD  TYPE LVC_S_FCAT.
FIELD-SYMBOLS:<ITAB> TYPE STANDARD TABLE,<WA>,<FT> TYPE LVC_T_STYL,<FV>,<F1>,<F2>,<F3>.
FIELD-SYMBOLS:<ITAB2> TYPE STANDARD TABLE,<WA2>,<FT2> TYPE LVC_T_STYL,<FV2>,<F12>,<F22>,<F32>.
DATA: DY_TABLE TYPE REF TO DATA,   ""取值的动态内表DY_LINE  TYPE REF TO DATA.
DATA: DY_TABLE2 TYPE REF TO DATA,  ""输出的动态内表,每个字段暂定char128,DY_LINE2  TYPE REF TO DATA.
FIELD-SYMBOLS: <DYN_TABLE> TYPE TABLE,<GT_TABLE>  TYPE TABLE,<DYN_WA>    TYPE ANY.
FIELD-SYMBOLS : <FS_TAB> TYPE ANY TABLE .SELECTION-SCREEN BEGIN OF BLOCK A1 WITH FRAME TITLE TEXT-001.
SELECT-OPTIONS:S_BUKRS FOR BKPF-BUKRS   . "公司代码
SELECT-OPTIONS:S_BLART FOR BKPF-BLART   . "凭证类型
SELECT-OPTIONS:S_BELNR FOR BKPF-BELNR   . "会计凭证
SELECT-OPTIONS:S_HKONT FOR BSEG-HKONT   . "会计科目
SELECT-OPTIONS:S_BUDAT FOR BKPF-BUDAT OBLIGATORY  . "过账日期
PARAMETERS : P_FILE LIKE RLGRAP-FILENAME DEFAULT '/usr/sap/tmp/'.   "/gacmotor/sap "AL11中的文件目录都可以导出,需要与basis联系询问具体地址
PARAMETERS : P_NUMB TYPE SY-INDEX DEFAULT '1000000' .
PARAMETERS : P_SERV RADIOBUTTON GROUP R1 DEFAULT 'X'.
PARAMETERS : P_LOCA RADIOBUTTON GROUP R1 .
SELECTION-SCREEN END OF BLOCK A1.
SELECTION-SCREEN FUNCTION KEY 1. "AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_FILE.PERFORM FRM_F4_P_FILE .
*************************************************************************
** INITIALIZATION
*************************************************************************"该事件在屏幕未显示之前执行,对程序设置值及屏幕元素进行初始化赋值。INITIALIZATION.STBL-ROW = 'X'.STBL-COL = 'X'.SSCRFIELDS-FUNCTXT_01 = '维护审计导出字段配置表'.SSCRFIELDS-UCOMM      = 'FC01'.
*************************************************************************
** AT SELECTION SCREEN
*************************************************************************
AT SELECTION-SCREEN.CASE SSCRFIELDS-UCOMM.          "处理按钮命令WHEN'FC01'.CALL FUNCTION 'VIEW_MAINTENANCE_CALL'EXPORTINGACTION    = 'U'VIEW_NAME = 'ZTFI252'.WHEN OTHERS.ENDCASE.*************************************************************************
** AT SELECTION SCREEN OUTPUT
*************************************************************************
AT SELECTION-SCREEN OUTPUT.*************************************************************************
** EVENT TOP OF PAGE
*************************************************************************
TOP-OF-PAGE.*************************************************************************
* EVENT START OF SELECTION
*************************************************************************
START-OF-SELECTION.PERFORM GET_DATA .*************************************************************************
**EVENT END-OF SELECTION
*************************************************************************
END-OF-SELECTION.*************************************************************************
**EVENT  END-OF PAGE
*************************************************************************
END-OF-PAGE.FORM GET_DATA .DATA LV_SELET TYPE STRING . ""select 哪些字段DATA LV_SELEB TYPE STRING . ""select 哪些字段DATA LV_SELEA TYPE STRING . ""select 哪些字段DATA LV_LENGE TYPE I .DATA LV_STR   TYPE STRING . "用于字段转换位string类型DATA LT_BKPF TYPE TABLE OF BKPF .DATA LT_BSEG TYPE TABLE OF BSEG .DATA LS_BKPF TYPE BKPF .DATA LS_BSEG TYPE BSEG .DATA LINE       TYPE STRING.""行数据DATA LINE1      TYPE STRING.""第一行表头DATA LINES      TYPE STRING.""表数据DATA LD_XSTRING TYPE XSTRING.DATA LD_STRING  TYPE STRING.DATA WF_MSG     TYPE STRING.TYPES: BEGIN OF ty_fieldname,name TYPE char20,END OF ty_fieldname.DATA: lt_fieldname TYPE TABLE OF ty_fieldname WITH HEADER LINE.FIELD-SYMBOLS: <lt_table> TYPE table."取配置表数据SELECT * FROM ZTFI252 INTO TABLE @DATA(LT_252) .IF LT_252 IS INITIAL.MESSAGE '请先维护表ZTFI252' TYPE 'S' DISPLAY LIKE 'E' .ENDIF .CHECK LT_252 IS NOT INITIAL ."排序,删除重复维护的字段,活动取值不能有相同的字段SORT LT_252 BY REF_FIELD REF_TABLE  XH .DELETE ADJACENT DUPLICATES FROM LT_252 COMPARING  REF_FIELD .SORT LT_252 BY XH REF_TABLE REF_FIELD    . "删除后按照顺序拍好CLEAR : GT_FIELD .LOOP AT LT_252 INTO DATA(LS_252)."构造导出至服务器的动态内表的表字段CLEAR :GS_FIELD .GS_FIELD-FIELDNAME = LS_252-REF_FIELD .GS_FIELD-REF_TABLE = LS_252-REF_TABLE .GS_FIELD-REF_FIELD = LS_252-REF_FIELD .APPEND GS_FIELD TO GT_FIELD .IF P_LOCA = 'X' ."构造导出至本地的动态内表的表字段  暂时用长度128CLEAR :GS_FIELD .GS_FIELD-FIELDNAME = LS_252-REF_FIELD .GS_FIELD-INTTYPE   = 'C' .GS_FIELD-INTLEN    = '128' .APPEND GS_FIELD TO GT_FIELD2 .ENDIF."构造动态取值的select字段IF LV_SELEA IS INITIAL.LV_SELEA = LV_SELEA && LS_252-REF_TABLE && '~' && LS_252-REF_FIELD .ELSE .LV_SELEA = LV_SELEA && ','  && LS_252-REF_TABLE && '~' && LS_252-REF_FIELD .ENDIF.ENDLOOP ."调用方法生成动态内表存储取出的数据CALL METHOD CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLEEXPORTINGIT_FIELDCATALOG = GT_FIELDIMPORTINGEP_TABLE        = DY_TABLE.ASSIGN DY_TABLE->* TO <ITAB>. "将指针分配给动态内表CREATE DATA DY_LINE LIKE LINE OF <ITAB>.ASSIGN DY_LINE->* TO <WA>.  "将指针分配给动态内表行IF P_LOCA = 'X'.CALL METHOD CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLEEXPORTINGIT_FIELDCATALOG = GT_FIELD2IMPORTINGEP_TABLE        = DY_TABLE2.ASSIGN DY_TABLE2->* TO <ITAB2>. "将指针分配给动态内表CREATE DATA DY_LINE LIKE LINE OF <ITAB2>.ASSIGN DY_LINE->* TO <WA2>.  "将指针分配给动态内表行ENDIF."动态取出数据IF LV_SELEA IS NOT INITIAL.SELECT (LV_SELEA) FROM BKPFINNER JOIN BSEG ON BKPF~BUKRS = BSEG~BUKRS AND BKPF~BELNR = BSEG~BELNR AND BKPF~GJAHR = BSEG~GJAHR"WHERE BKPF~BUKRS IN @S_BUKRSAND   BKPF~BLART IN @S_BLARTAND   BKPF~BELNR IN @S_BELNRAND   BSEG~HKONT IN @S_HKONTAND   BKPF~BUDAT IN @S_BUDATINTO  TABLE @<ITAB> .ENDIF.IF <ITAB> IS INITIAL.MESSAGE '未找到数据' TYPE 'S' DISPLAY LIKE 'E' .ENDIF.CHECK <ITAB> IS NOT INITIAL .DATA: LV_FILE TYPE RLGRAP-FILENAME.DATA: LV_TIME TYPE C .DATA: p_filename TYPE STRING .DATA: LV_ASSGIN TYPE C LENGTH 30 .DATA: LV_INDEX TYPE SY-INDEX .SELECT * FROM ZTFI252 INTO TABLE @DATA(LT_252B) .SORT LT_252B BY  XH .DELETE ADJACENT DUPLICATES FROM LT_252B COMPARING XH .""取表头描述SELECT TABNAME, FIELDNAME, DDTEXT ,XH FROM DD03M AS AINNER JOIN  @LT_252B AS B ON TABNAME = B~REF_TABLE AND FIELDNAME = B~REF_FIELD  AND DDLANGUAGE = '1'INTO TABLE @DATA(LT_03M) .SORT LT_03M BY  XH .DELETE ADJACENT DUPLICATES FROM LT_03M COMPARING XH .LOOP AT LT_03M INTO DATA(LS_03M).IF P_SERV = 'X' . "构造导出至服务器数据表头CONCATENATE LINE1 LS_03M-DDTEXT ',' INTO LINE1 . "每个数据后面加个逗号,excel就会换单元格ELSEIF P_LOCA = 'X' ."构造导出至本地数据表头CONCATENATE  '<WA2>-'  LS_03M-FIELDNAME INTO LV_ASSGIN .ASSIGN (LV_ASSGIN) TO FIELD-SYMBOL(<FS_VALUE>) .IF <FS_VALUE> IS ASSIGNED .<FS_VALUE> = LS_03M-DDTEXT .ENDIF.UNASSIGN <FS_VALUE> .lt_fieldname-name = LS_03M-DDTEXT.   "EXCEL表头  LOOP p_table的组件,并依次将字段中文描述赋值给lt_fieldnameAPPEND lt_fieldname.ENDIF.ENDLOOP." APPEND <WA2> TO <ITAB2> .""函数自带表头传入参数lt_fieldname就会有表头DO . ""LV_TIME = SY-INDEX .CONCATENATE P_FILE  S_BUDAT-LOW '-' S_BUDAT-HIGH '-' SY-UZEIT LV_TIME '.CSV' INTO LV_FILE. "服务器保存的目录和文件名CONCATENATE LINES LINE1 INTO LINES . "将表头添加进表CLEAR : LS_BKPF ,LS_BSEG .DO P_NUMB TIMES. "按照凭证上的次数生成文件UNASSIGN <WA> .LV_INDEX = LV_INDEX + 1 .READ TABLE <ITAB> ASSIGNING <WA> INDEX LV_INDEX  .IF <WA> IS ASSIGNED .IF P_SERV = 'X'. "构造导出到服务器的数据LOOP AT LT_252B INTO LS_252.CONCATENATE  '<WA>-'  LS_252-REF_FIELD INTO LV_ASSGIN .ASSIGN (LV_ASSGIN) TO <FS_VALUE> .IF <FS_VALUE> IS ASSIGNED.LV_STR = <FS_VALUE> . "可能有金额字段,需要转化位字符串CONCATENATE LINE LV_STR ',' INTO LINE . "每个数据后面加个逗号,excel就会换单元格ENDIF.ENDLOOP.UNASSIGN <WA> .CONCATENATE  LINES   CL_ABAP_CHAR_UTILITIES=>CR_LF(1)  LINE INTO LINES. "将换行符和这行数据加入表数据中CLEAR LINE .ELSEIF P_LOCA = 'X'.MOVE-CORRESPONDING <WA> TO <WA2> .APPEND <WA2> TO <ITAB2> .UNASSIGN: <WA> .CLEAR :<WA2> .ENDIF.ELSE .EXIT .ENDIF.ENDDO."每循环一次导出一次数据IF  P_SERV = 'X'.CALL FUNCTION 'SCMS_STRING_TO_XSTRING'EXPORTINGTEXT     = LINESENCODING = '8404'IMPORTINGBUFFER   = LD_XSTRINGEXCEPTIONSFAILED   = 1OTHERS   = 2."  DATA(utf8) = cl_abap_codepage=>convert_to( LINES ). "如果要使用AL11直接下载后台跑出的文件到本地用这个方法转码,而不是上面那个函数OPEN DATASET LV_FILE FOR OUTPUT IN BINARY MODE ."TEXT  MODE encoding UTF-8" OPEN DATASET LV_FILE FOR OUTPUT IN TEXT MODE ENCODING UTF-8 WITH BYTE-ORDER MARK."TEXT  MODE encoding UTF-8IF SY-SUBRC = 0.TRANSFER LD_XSTRING TO LV_FILE."   TRANSFER LD_XSTRING TO LV_FILE.CLOSE DATASET LV_FILE.ENDIF .CLEAR : LINE,LINES .ELSEIF P_LOCA = 'X' .CONCATENATE P_FILE  S_BUDAT-LOW '-' S_BUDAT-HIGH '-' SY-UZEIT LV_TIME '.XLS' INTO LV_FILE. "服务器保存的目录和文件名p_filename = LV_FILE .CALL FUNCTION 'GUI_DOWNLOAD'EXPORTINGfilename   = p_filenamefiletype   = 'DAT' "ASC格式 1000- 不会显示为 -1000 DBF格式 字符前空格 前导0不会显示codepage   = '8404' "四位字符集代码 可通过表TCP00A,查询对应字符集代码TABLESdata_tab   = <ITAB2>fieldnames = lt_fieldname..CLEAR: <ITAB2>.ENDIF.IF <WA> IS NOT ASSIGNED .EXIT .ENDIF.ENDDO.CLEAR : LV_INDEX .
ENDFORM .FORM FRM_F4_P_FILE .DATA LV_NAME TYPE C LENGTH 30 .LV_NAME = SY-DATUM && SY-UZEIT .CALL FUNCTION 'WS_FILENAME_GET' "用于选择本地文件,获取本地文件的路径EXPORTINGDEF_FILENAME     = LV_NAME  "默认的文件名称
*     DEF_PATH         = ' '  "默认的文件地址
*     MASK             = ',EXCEL.XLS,*.XLSX,*.XLS,TEXT.TXT,*.TXT.'MODE             = 'O'      "S 保存  O 打开TITLE            = '选择文件'  "窗口的显示名称IMPORTING                        "传出给选择屏幕上的文本框FILENAME         = P_FILE
*     RC               =EXCEPTIONSINV_WINSYS       = 1NO_BATCH         = 2SELECTION_CANCEL = 3SELECTION_ERROR  = 4OTHERS           = 5.IF SY-SUBRC <> 0.
* Implement suitable error handling hereENDIF.
ENDFORM .

自建表

 自建表数据附件excel,附件中是bkpf及 bseg两个表所有的字段,SE16N编辑进表后删除字段中带.的字段就可以了

选择屏幕文本

总结:这个程序导出速度很快,主要有以下原因

1.没有多余的取值字段,都是按照用户维护,活动内表,活动取值,不浪费算力

2.可以服务器后台处理,比本机快

3.直接sap底层转码,构造文件,速度很快

扩展:如果想批导出其他的表而不是bkpf及bseg,可以看着修改选择屏幕以及动态取出表数据的那段select就行了