SAP-ABAP-后台表数据万能导出程序

主要代码讲解

 程序总体逻辑:根据配置表构造活动sql的select语句,讲取到的数据存储到活动内表,然后对活动内表进行处理,导出数据到本地,或者sap服务器。

1.1活动sql

 sql语句由四部分组成 select ...  from ... where... into ... ,sap可以使用字符串代替这四部分,本程序运用此特性将维护表数据构造成活动sql取值

1.2活动内表

类方法cl_alv_table_create=>create_dynamic_table 传入参考的字段清单即可构造成动态内表,将结果构造成与上文的sql结构一致,即可不浪费内存,不浪费算力存储数据

1.3二进制数据流数据导出

 将数据按照格式构造成二进制数据流的方式,然后导出到sap服务器能访问的地址

1.3.1构造二进制数据流的CSV文件

二进制数据流是由一整串的字符串,在字符串中逗号代表csv文件的下一个单元格,调用方法 CL_ABAP_CHAR_UTILITIES=>CR_LF(1拼入字符串中代表csv文件的换行,所以我们只要先构造表头,从表DD03M 取表字段的描述作为表头,然后循环上文取到的内表数据,用逗号连接字段,循环完成后凭借换行符,最后就完成了文件的构造了。

1.3.2为数据转码

上文得到的数据目前是未转码的数据,需要将数据转换为二进制数据,服务器才能识别,

CALL FUNCTION 'SCMS_STRING_TO_XSTRING 为数据转码。

1.3.3将文件写入服务器

1.语句OPEN DATASET lv_file FOR OUTPUT IN BINARY MODE . 可以打开文件位置路径,路径参数为lv_file

2.将上文转码后的二进制文件写入打开的服务器地址TRANSFER ld_xstring TO lv_file.  将文件ld_xstring 写入刚刚打开的位置 lv_file

3.CLOSE DATASET lv_file.  写入完成后关闭连接,这一步必须要有,不然服务器一直会占用着这个文件,即便,数据已经写入完成了也不能再操作这个文件。

1.4导出至服务器的优缺点

导出至服务器构造的是csv格式的excel文件,该格式由一个字符串组成,空格代表下一个单元格 ,调用方法 cl_abap_char_utilities=>cr_lf(1) 代表换行,由于是服务器处理数据,且活动内表没有浪费多余的算力,数据构造速度快,但是快带来的缺点是excel的单元格格式都是默认的,无法做修改。

1.5导出至本地

导出至本地调用的是函数 GUI_DOWNLOAD ,将数据表传入参数data_tab

然后将标题数据传入参数fieldnames然后将文件地址传入参数filename这样就能将文件导出至指定目录了。

1.6导出至本地的优缺点

导出至本地优点就是操作简单,也能灵活的调整单元格格式,速度也不会很慢,缺点就是在导出程序是不能使用后台导出,只能一直占用本机的资源。在数据量非常巨大的时候时间也需要很久。

配置表

2.1配置表结构

2.2参考配置表数据如下


3选择屏幕文本

4.导出至服务器的配置
项目上要和外围系统做接口,把传过来的文件写入到sap的文件服务器或者存入表中,让外围系统过来存取,但是为了减少SAP应用服务器的负担,需要一台独立的文件服务器共享目录到SAP应用服务器,实现往SAP应用服务器上写文件,实际上是写在了这台独立的文件服务器上。

4.1让basis将文件服务器与sap服务器做连接

我们需要让Basis把文件服务器和SAP应用服务器做NFS,开放给SAP相应权限。然后在al11新增文件目录,这个目录就是上文我们需要用到的目录,当然如果没有文件服务器也可以使用sap服务器作为导出地址,al11目录下的所有地址都可以作为文件导出地址

4.2查看及下载文件

导出完成后如果想查看文件可以进事务代码AL11,双击打开导入的文件夹,就能看到之前导出的文件的清单了。下图红框框中的按钮就是导出按钮。如果不想在sap操作文件也可以直接进服务器的该目录操作该文件

利用灵活sql取配置表数据构造动态内表导出至本地及服务器,代码如下

*&---------------------------------------------------------------------*
*& Report ZFIR252
*&---------------------------------------------------------------------*
*& author 李强 Qunending 2022.02.16
*&---------------------------------------------------------------------*
REPORT zexport_table.

TABLES:sscrfields,ztexport.
DATA:ok_code LIKE sy-ucomm.
DATA:stbl TYPE lvc_s_stbl.
DATA: gt_field  TYPE lvc_t_fcat.
DATA: gt_fieldISP  TYPE lvc_t_fcat.
DATA: gt_field2 TYPE lvc_t_fcat.
DATA: gs_field  TYPE lvc_s_fcat.
DATA: GS_LAYOUT TYPE LVC_S_LAYO.
DATA: GS_VARIANT TYPE DISVARIANT.
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 .

DATA gv_selea TYPE string . ""select 哪些字段
DATA gv_from  TYPE string . ""FROM 哪个表怎么连表
DATA gv_where TYPE string . ""WHERE 哪些条件

DATA gt_exp TYPE TABLE OF ztexport .

SELECTION-SCREEN BEGIN OF BLOCK a1 WITH FRAME TITLE TEXT-001.
PARAMETERS : p_versi TYPE zeversi .

PARAMETERS : P_DISP RADIOBUTTON GROUP r2 DEFAULT 'X' USER-COMMAND uc .
PARAMETERS : P_EXPO RADIOBUTTON GROUP r2   .

PARAMETERS : p_file LIKE rlgrap-filename DEFAULT '/gacmotor/sap/' MODIF ID M1.   "/gacmotor/sap "AL11中的文件目录都可以导出,需要与basis联系询问具体地址
PARAMETERS : p_numb TYPE sy-index DEFAULT '1000000'  MODIF ID M1.
PARAMETERS : p_serv RADIOBUTTON GROUP r1 DEFAULT 'X' MODIF ID M1.
PARAMETERS : p_loca RADIOBUTTON GROUP r1  MODIF ID M1.
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 .

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_versi.
  PERFORM frm_f4_p_versi .
*************************************************************************
** INITIALIZATION
*************************************************************************
  "该事件在屏幕未显示之前执行,对程序设置值及屏幕元素进行初始化赋值。

INITIALIZATION.
  stbl-row = 'X'.
  stbl-col = 'X'.
  sscrfields-functxt_01 = '维护审计导出字段配置表'.
  "假必输
  LOOP AT SCREEN.
    IF screen-name = 'P_VERSI'.
      screen-required = '2'.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.
*************************************************************************
** AT SELECTION SCREEN
*************************************************************************
AT SELECTION-SCREEN.
  CASE sscrfields-ucomm.          "处理按钮命令
    WHEN'FC01'.

      CALL FUNCTION 'VIEW_MAINTENANCE_CALL'
        EXPORTING
          action    = 'U'
          view_name = 'ZTEXPORT'.
    WHEN OTHERS.

  ENDCASE.


*************************************************************************
** AT SELECTION SCREEN OUTPUT
*************************************************************************
AT SELECTION-SCREEN OUTPUT.

  LOOP AT SCREEN.
     CASE screen-group1.
       WHEN 'M1' .
         IF P_DISP = 'X'.
           screen-active = '0'.
         ELSE.
          screen-active = '1'.
         ENDIF.
     ENDCASE .
    IF screen-name = 'P_VERSI'.
      screen-required = '2'.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.
*************************************************************************
* EVENT START OF SELECTION
*************************************************************************
START-OF-SELECTION.
  PERFORM frm_check_exp_data .
  PERFORM bulid_select .
  IF P_EXPO = 'X'.
    PERFORM export_data_to_ser .
    PERFORM export_data_to_loc .
  ELSEIF P_DISP = 'X' .
    PERFORM FRM_DISPLAY_ALV .
  ENDIF.


*************************************************************************
**EVENT END-OF SELECTION
*************************************************************************
END-OF-SELECTION.

FORM frm_check_exp_data.
  "取配置表数据
  SELECT * FROM ztexport INTO TABLE @gt_exp WHERE versi = @p_versi .
  IF gt_exp IS INITIAL.
    MESSAGE '请先维护表ZTEXPORT' TYPE 'S' DISPLAY LIKE 'E' .
  ENDIF .
  CHECK gt_exp IS NOT INITIAL .
  "排序,删除重复维护的字段,活动取值不能有相同的字段
  SORT gt_exp BY ref_field ref_table as_table as_field xh .
  DELETE ADJACENT DUPLICATES FROM gt_exp COMPARING  ref_field as_field.
  SORT gt_exp BY xh ref_table ref_field    . "删除后按照顺序排好
ENDFORM .

FORM bulid_select .

  CLEAR : gv_selea,gv_where,gv_from,gt_field.
  LOOP AT gt_exp INTO DATA(ls_exp).
    "构造导出至服务器的动态内表的表字段
    CLEAR :gs_field .
    IF ls_exp-as_field IS NOT INITIAL.
      gs_field-fieldname = ls_exp-as_field .
    ELSE .
      gs_field-fieldname = ls_exp-ref_field .
    ENDIF.
    gs_field-ref_table = ls_exp-ref_table .
    gs_field-ref_field = ls_exp-ref_field .
    APPEND gs_field TO gt_field .

    "构造动态取值的select字段
    IF ls_exp-as_table IS NOT INITIAL.
      ls_exp-ref_table = ls_exp-as_table .
    ENDIF.

    IF gv_selea IS INITIAL.
      gv_selea = gv_selea && ls_exp-ref_table && '~' && ls_exp-ref_field .
    ELSE .
      gv_selea = gv_selea && ','  && ls_exp-ref_table && '~' && ls_exp-ref_field .
    ENDIF.

    IF ls_exp-as_field IS NOT INITIAL.
      gv_selea = gv_selea && ` AS ` && ls_exp-as_field .
    ENDIF.
  ENDLOOP .
  "构造限制条件1代表 限制单值等于某个数据,2代表限制范围
  SELECT * FROM ztexport INTO TABLE @DATA(gt_expw) WHERE versi = @p_versi .
  LOOP AT gt_expw INTO ls_exp WHERE where_typ IS NOT INITIAL .
    IF ls_exp-where_typ = '1'.
      IF gv_where IS INITIAL.
        CONCATENATE gv_where ls_exp-ref_table  '~' ls_exp-ref_field  ` = '`  ls_exp-where_low `'` INTO gv_where .
      ELSE .
        CONCATENATE gv_where  ` AND `  ls_exp-ref_table  '~' ls_exp-ref_field  ` = '`  ls_exp-where_low `'` INTO gv_where .
      ENDIF.
    ELSEIF ls_exp-where_typ = '2'.
      IF gv_where IS INITIAL.
        CONCATENATE gv_where ls_exp-ref_table  '~' ls_exp-ref_field  ` BETWEEN '`  ls_exp-where_low `' AND '` ls_exp-where_high `'` INTO gv_where .
      ELSE .
        CONCATENATE gv_where ` AND ` ls_exp-ref_table  '~' ls_exp-ref_field  ` BETWEEN '`  ls_exp-where_low `' AND '` ls_exp-where_high `'` INTO gv_where .
      ENDIF.
    ENDIF.
  ENDLOOP.

  "构造连表数据
  DATA lv_tabix TYPE sy-index .
  SELECT DISTINCT ref_table,iffrom FROM ztexport INTO TABLE @DATA(lt_reftab) WHERE versi = @p_versi.
  SORT lt_reftab BY iffrom .
  LOOP AT lt_reftab INTO DATA(ls_reftab).
    "FROM 哪个表
    IF ls_reftab-iffrom = 0.
      gv_from = ls_reftab-ref_table .
      IF ls_exp-as_table IS NOT INITIAL.
        gv_selea = gv_selea && ` AS ` && ls_exp-as_table .
      ENDIF.
      CONTINUE .
    ENDIF.
    "连接什么表
    LOOP AT gt_expw INTO ls_exp WHERE ref_table = ls_reftab-ref_table.
      IF ls_exp-join_table IS INITIAL .
        CONTINUE .
      ENDIF.
      lv_tabix = lv_tabix + 1 .
      IF lv_tabix = 1.
        gv_from = gv_from && ` ` && ls_exp-connet && ` ` &&  ls_exp-ref_table &&  ` ON ` .
      ENDIF.
      IF lv_tabix >= 2 .
        gv_from = gv_from && ` AND ` .
      ENDIF.
      gv_from = gv_from && ` `  && ls_exp-ref_table && '~' &&  ls_exp-ref_field && ` = ` && ls_exp-join_table && '~' &&  ls_exp-join_field .
    ENDLOOP.
    CLEAR : lv_tabix .
  ENDLOOP.

  "调用方法生成动态内表存储取出的数据
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_field
    IMPORTING
      ep_table        = dy_table.
  ASSIGN dy_table->* TO <itab>. "将指针分配给动态内表
  CREATE DATA dy_line LIKE LINE OF <itab>.
  ASSIGN dy_line->* TO <wa>.  "将指针分配给动态内表行

  "动态取出数据
  IF gv_selea IS NOT INITIAL.
    SELECT (gv_selea)
      FROM (gv_from)
      WHERE (gv_where)
    INTO  TABLE @<itab> .
  ENDIF.
  IF <itab> IS INITIAL.
    MESSAGE '未找到数据' TYPE 'S' DISPLAY LIKE 'E' .
  ENDIF.
ENDFORM .
FORM export_data_to_ser .

  CHECK p_serv = 'X' .

  DATA lv_lenge TYPE i .
  DATA lv_str   TYPE string . "用于字段转换位string类型
  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.

  CHECK <itab> IS NOT INITIAL .
  DATA: lv_file TYPE rlgrap-filename.
  DATA: lv_time TYPE n LENGTH 4 .
  DATA: p_filename TYPE string .
  DATA: lv_assgin TYPE c LENGTH 30 .
  DATA: lv_index TYPE sy-index .
  SELECT * FROM ztexport INTO TABLE @DATA(lt_expb) .
  SORT lt_expb BY  xh .
  DELETE ADJACENT DUPLICATES FROM lt_expb COMPARING xh .
  ""取表头描述
  SELECT tabname, fieldname, ddtext ,xh FROM dd03m AS a
    INNER JOIN  @lt_expb 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).
    CONCATENATE line1 ls_03m-ddtext ',' INTO line1 . "每个数据后面加个逗号,excel就会换单元格
  ENDLOOP.
  " APPEND <WA2> TO <ITAB2> .""函数自带表头传入参数lt_fieldname就会有表头
  DATA lv_spaece TYPE  string .
  lv_spaece = cl_abap_char_utilities=>get_simple_spaces_for_cur_cp( ) . "返回一个带有空白字符的字符串
  DO . ""
    lv_time = sy-index .
    CONCATENATE p_file  sy-datum  '-'  sy-uzeit lv_time '.CSV' INTO lv_file. "服务器保存的目录和文件名
    CONCATENATE lines line1 INTO lines . "将表头添加进表
    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_expb INTO DATA(ls_exp).
            CONCATENATE  '<WA>-'  ls_exp-ref_field INTO lv_assgin .
            ASSIGN (lv_assgin) TO FIELD-SYMBOL(<fs_value>) .
            IF <fs_value> IS ASSIGNED.
              lv_str = <fs_value> . "可能有金额字段,需要转化位字符串
              IF ls_exp-del_special = 'X'. "
                PERFORM frm_del_str CHANGING lv_str. "" 去掉特殊字符
                CONCATENATE line  lv_str  ',' INTO line . "数字加个单分号会当作文本展示每个数据后面加个逗号,excel就会换单元格
              ELSE .
                CONCATENATE line  lv_str ',' INTO line . "每个数据后面加个逗号,excel就会换单元格
              ENDIF.
            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'
        EXPORTING
          text     = lines
          encoding = '8404'
        IMPORTING
          buffer   = ld_xstring
        EXCEPTIONS
          failed   = 1
          OTHERS   = 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-8
      IF sy-subrc = 0.
        TRANSFER ld_xstring TO lv_file.
        "   TRANSFER LD_XSTRING TO LV_FILE.
        CLOSE DATASET lv_file.
        MESSAGE '已成功导出至服务器' TYPE 'S' .
      ENDIF .
      CLEAR : line,lines .

    ENDIF.
    IF <wa> IS NOT ASSIGNED .
      EXIT .
    ENDIF.
  ENDDO.
  CLEAR : lv_index .
ENDFORM .
FORM export_data_to_loc.

  CHECK p_loca  = 'X' .

  DATA lv_lenge TYPE i .
  DATA lv_str   TYPE string . "用于字段转换位string类型
  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.
  CHECK <itab> IS NOT INITIAL .
  DATA: lv_file TYPE rlgrap-filename.
  DATA: lv_time TYPE n LENGTH 4 .
  DATA: p_filename TYPE string .
  DATA: lv_assgin TYPE c LENGTH 30 .
  DATA: lv_index TYPE sy-index .
  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.

  LOOP AT gt_exp INTO DATA(ls_exp).
    "构造导出至本地的动态内表的表字段  暂时用长度128
    CLEAR :gs_field .
    IF ls_exp-as_field IS NOT INITIAL.
      gs_field-fieldname = ls_exp-as_field .
    ELSE .
      gs_field-fieldname = ls_exp-ref_field .
    ENDIF.
    gs_field-inttype   = 'C' .
    gs_field-intlen    = '128' .
    APPEND gs_field TO gt_field2 .
  ENDLOOP.
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_field2
    IMPORTING
      ep_table        = dy_table2.
  ASSIGN dy_table2->* TO <itab2>. "将指针分配给动态内表
  CREATE DATA dy_line LIKE LINE OF <itab2>.
  ASSIGN dy_line->* TO <wa2>.  "将指针分配给动态内表行

  ""取表头描述
  SELECT * FROM ztexport INTO TABLE @DATA(lt_expb) .
  SORT lt_expb BY  xh .
  DELETE ADJACENT DUPLICATES FROM lt_expb COMPARING xh .
  SELECT tabname, fieldname, ddtext ,xh FROM dd03m AS a
    INNER JOIN  @lt_expb 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).
    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_fieldname
    APPEND lt_fieldname.
  ENDLOOP.

  DO . ""
    lv_time = sy-index .
    DO p_numb TIMES. "按照凭证上的次数生成文件
      UNASSIGN <wa> .
      lv_index = lv_index + 1 .
      READ TABLE <itab> ASSIGNING <wa> INDEX lv_index  .
      IF <wa> IS ASSIGNED .
        MOVE-CORRESPONDING <wa> TO <wa2> .
        APPEND <wa2> TO <itab2> .
        UNASSIGN: <wa> .
        CLEAR :<wa2> .
      ELSE .
        EXIT .
      ENDIF.
    ENDDO.
    CONCATENATE p_file  sy-datum '-' sy-uzeit lv_time '.XLS' INTO lv_file. "服务器保存的目录和文件名
    p_filename = lv_file .
    CALL FUNCTION 'GUI_DOWNLOAD'
      EXPORTING
        filename   = p_filename
        filetype   = 'DAT' "ASC格式 1000- 不会显示为 -1000 DBF格式 字符前空格 前导0不会显示
        codepage   = '8404' "四位字符集代码 可通过表TCP00A,查询对应字符集代码
      TABLES
        data_tab   = <itab2>
        fieldnames = lt_fieldname.
    .
    MESSAGE '导出成功' TYPE 'S' .
    CLEAR: <itab2>.
    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' "用于选择本地文件,获取本地文件的路径
    EXPORTING
      def_filename     = lv_name  "默认的文件名称
*     DEF_PATH         = ' '  "默认的文件地址
*     MASK             = ',EXCEL.XLS,*.XLSX,*.XLS,TEXT.TXT,*.TXT.'
      mode             = 'O'      "S 保存  O 打开
      title            = '选择文件'  "窗口的显示名称
    IMPORTING                        "传出给选择屏幕上的文本框
      filename         = p_file
*     RC               =
    EXCEPTIONS
      inv_winsys       = 1
      no_batch         = 2
      selection_cancel = 3
      selection_error  = 4
      OTHERS           = 5.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.
ENDFORM .
FORM frm_f4_p_versi .
  DATA: gt_return TYPE TABLE OF ddshretval,
        gs_return TYPE ddshretval.

  DATA: gt_f4  TYPE TABLE OF ztexport,
        gs_f4  TYPE ztexport,
        gt_f41 TYPE TABLE OF ztexport.

  SELECT  *
  FROM  ztexport
  INTO TABLE @gt_f4.
  DELETE  ADJACENT DUPLICATES FROM gt_f4 COMPARING VERSI .

  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield        = 'VERSI'
      value_org       = 'S'
    TABLES
      value_tab       = gt_f4
      return_tab      = gt_return
    EXCEPTIONS
      parameter_error = 1
      no_values_found = 2
      OTHERS          = 3.
  IF sy-subrc = 0.
    READ TABLE gt_return  INTO gs_return INDEX 1.
    p_versi = gs_return-fieldval.
  ELSE.
  ENDIF.
ENDFORM .
FORM frm_del_str CHANGING p_str TYPE string.
  REPLACE ALL OCCURRENCES OF  ',' IN p_str  WITH  ` `  .
  REPLACE ALL OCCURRENCES OF  '#' IN p_str  WITH  ` `  .
  REPLACE ALL OCCURRENCES OF  '#' IN p_str  WITH  ` `  .
  REPLACE ALL OCCURRENCES OF  ',' IN p_str  WITH  ` `  .
  REPLACE ALL OCCURRENCES OF  ',' IN p_str  WITH  ` `  .
  REPLACE ALL OCCURRENCES OF  ',' IN p_str  WITH  ` `  .
  DATA(lv_char) = cl_abap_char_utilities=>cr_lf+1(1).
  REPLACE ALL OCCURRENCES OF  lv_char IN p_str  WITH  ` `  .
ENDFORM .

FORM FRM_DISPLAY_ALV .
  GS_LAYOUT-ZEBRA      = 'X'.
 " GS_LAYOUT-BOX_FNAME = 'SET'.
*  GS_LAYOUT-STYLEFNAME = 'STYLE'.
  GS_LAYOUT-CWIDTH_OPT = 'X'.

  GS_VARIANT-REPORT = SY-REPID.
  GS_VARIANT-HANDLE = '0001'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      I_CALLBACK_PROGRAM = SY-REPID
      IT_FIELDCAT_LVC    = GT_FIELD
      IS_LAYOUT_LVC      = GS_LAYOUT
  "    IT_EVENTS          = GT_EVENTS
      IS_VARIANT         = GS_VARIANT
*     I_CALLBACK_TOP_OF_PAGE  = 'FRM_TOP_OF_PAGE'
*     I_CALLBACK_USER_COMMAND = 'FRM_USER_COMMAND'
     I_CALLBACK_PF_STATUS_SET = 'FRM_SET_STATUS'
   "   I_SAVE             = 'A'
      I_DEFAULT          = 'X'
    TABLES
      T_OUTTAB           = <ITAB>.
ENDFORM .
FORM FRM_SET_STATUS USING P_EXTAB TYPE SLIS_T_EXTAB .
  SET PF-STATUS 'STATU'.
  SET TITLEBAR 'STATU'.
ENDFORM.

配置表如下

 参考配置表数据如下

选择屏幕文本

配置表各个字段的作用

版本VERSI及版本行项目:

        用来区别本次导出是导出什么表

版本描述:

        描述该版本是导出哪个表的数据

导出展示位置XH:

        导出的文件中表头顺序按照该数字排序

导出表格REF_TABLE及导出字段REF_FIELD:

        导出的数据从哪个表格字段取数

表别名AS_TABLE,字段别名AS_FIELD:

        动态sql不能有完全一样的字段,当字段一样时要是要别名

连表顺序(FROM为0,依次往后加)IFFROM:

        sql中连表的顺序

连表方式CONNET:

        LEFT JOIN ,INNER JOIN 等

连接的表名JOIN_TABLE,连接的字段名JOIN_FIELD:

        与连表方式共同组成连表

限制类型WHERE_TYP,限制条件LOW( WHERE_LOW),限制条件HIGH( WHERE_HIGH):

        当限制类型等于1时代表限制该字段等于限制条件low值,当限制类型等于2时,代表限制该字段为范围low至high中的数据。

X代表用空格代替特殊字符后导出DEL_SPECIAL:

        有的数据再导出是如果存在特殊字符则无法导出到excel或者格式出错,若维护了该字段等于X则代码帮助去除特殊字符,可在form中新增特殊字符。

主要代码讲解

        程序总体逻辑:根据配置表构造活动sql的select语句,讲取到的数据存储到活动内表,然后对活动内表进行处理,导出数据到本地,或者sap服务器。

活动sql

 sql语句由四部分组成 select ...  from ... where... into ... ,sap可以使用字符串代替这四部分,本程序运用此特性将维护表数据构造成活动sql取值

活动内表

类方法cl_alv_table_create=>create_dynamic_table 传入参考的字段清单即可构造成动态内表,将结果构造成与上文的sql结构一致,即可不浪费内存,不浪费算力存储数据

二进制数据流数据导出

 将数据按照格式构造成二进制数据流的方式,然后导出到sap服务器能访问的地址

CALL FUNCTION 'SCMS_STRING_TO_XSTRING 为数据转码,

 OPEN DATASET lv_file FOR OUTPUT IN BINARY MODE . 打开文件位置路径为 lv_file

 TRANSFER ld_xstring TO lv_file.  将文件ld_xstring 写入刚刚打开的位置 lv_file

 CLOSE DATASET lv_file.  写入完成后关闭连接

本文构造的是csv格式的excel文件,该格式由一个字符串组成,空格代表下一个单元格 ,调用方法 cl_abap_char_utilities=>cr_lf(1) 代表换行,数据构造速度快,但是缺点是其他的格式都是默认的无法修改。

导出至本地调用的是函数 GUI_DOWNLOAD ,比较简单在此不在赘述

常驻sap欢迎留言

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值