(原创)不带模板的DOI输出EXCEL

      前面介绍了OLE输出EXCEL有个最大的特点就是慢,因为其是基于单元格层次的一个个操作去填充数据,而DOI技术采用面向对象的方法实现,解决了这个问题。至于为什么能解决,有兴趣的可以慢慢研究。

      既然是使用面向对象的方法实现,当然离不开类与接口,下面介绍DOI中最常用的4种类与接口。

1.容器类:目前作者常用的两种类是CL_GUI_CONTAINER和CL_GUI_CUSTOMER_CONTAINER,在不画屏幕容器,直接使用整个屏幕作为容器时使用CL_GUI_CONTAINER创建容器实例,在画屏幕容器时使用CL_GUI_CUSTOM_CONTAINER创建容器实例。

2.控制器接口:I_OI_CONTAINER_CONTROL,这个接口的实例主要用来与屏幕容器绑定和创建参照接口I_OI_DOCUMENT_PROXY 的实例。

3.文档接口:I_OI_DOCUMENT_PROXY ,参照这个接口的实例主要用来打开和保存文件,还有创建参照接口I_OI_SPREADSHEET 的实例。

4.SHEET页接口:I_OI_SPREADSHEET,参照这个接口的实例主要用来在SHEET页层级填充数据,设置格式等。

   最后给出一个简单的DEMO。

输出目标:

创建的屏幕100:

源代码:

*&---------------------------------------------------------------------*
*& Report Z15540_DOI1
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT Z15540_DOI1.
TYPE-POOLS:SOI.
"数据定义
DATA:BEGIN OF GS_DATA,
       WERKS TYPE MARD-WERKS,
       LGORT TYPE MARD-LGORT,
       MATNR TYPE MARD-MATNR,
       MAKTX TYPE MAKT-MAKTX,
       LABST TYPE MARD-LABST,
       MEINS TYPE MARA-MEINS,
     END OF GS_DATA.
DATA GT_DATA LIKE TABLE OF GS_DATA.
"DOI相关定义
DATA:LCL_CONTAINER  TYPE REF TO CL_GUI_CONTAINER, "容器引用对象
     LCL_CONTROL    TYPE REF TO I_OI_CONTAINER_CONTROL, "容器控制器引用对象
     LCL_DOCUMENT   TYPE REF TO I_OI_DOCUMENT_PROXY, "对应EXCEL文档层次引用对象
     LCL_SHEET      TYPE REF TO I_OI_SPREADSHEET. "对应SHEET层次操作的接口引用对象

START-OF-SELECTION.
  CALL SCREEN 100.
*&---------------------------------------------------------------------*
*& Form FRM_CONTAINER
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM FRM_CONTAINER .
  "将CL_GUI_CONTAINER的静态属性SCREEN0付给LCL_CONTAINER,相当于以当前系统显示的整个屏幕创建一个容器实例,该例中则以屏幕100创建实例
  LCL_CONTAINER = CL_GUI_CONTAINER=>SCREEN0.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CONTAINER_CONTROL
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM FRM_CONTAINER_CONTROL .
  "实例化容器控制器
  CALL METHOD C_OI_CONTAINER_CONTROL_CREATOR=>GET_CONTAINER_CONTROL
    IMPORTING
      CONTROL = LCL_CONTROL.
  "绑定容器与容器控制器,并初始化控制器设定
  CALL METHOD LCL_CONTROL->INIT_CONTROL
    EXPORTING
*     DYNPRO_NR                = SY-DYNNR
*     GUI_CONTAINER            = ' '
      INPLACE_ENABLED          = 'X' "EXCEL可嵌入容器
*     INPLACE_MODE             = 0
*     INPLACE_RESIZE_DOCUMENTS = ' '
      INPLACE_SCROLL_DOCUMENTS = 'X' "可滚动
*     INPLACE_SHOW_TOOLBARS    = 'X' "是否展示工具栏以上
*     NO_FLUSH                 = 'X'
*     PARENT_ID                = cl_gui_cfw=>dynpro_0
      R3_APPLICATION_NAME      = 'DOI TEST'
      REGISTER_ON_CLOSE_EVENT  = 'X' "注册关闭事件
      REGISTER_ON_CUSTOM_EVENT = 'X' "注册定制事件
*     REP_ID                   = SY-REPID
*     SHELL_STYLE              = 1384185856
      PARENT                   = LCL_CONTAINER
*     NAME                     =
*     AUTOALIGN                = 'x'
*  IMPORTING
*     ERROR                    =
*     RETCODE                  =
    EXCEPTIONS
      JAVABEANNOTSUPPORTED     = 1
      OTHERS                   = 2.
  IF SY-SUBRC <> 0.
* Implement suitable error handling here
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CREATE_EXCEL
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM FRM_CREATE_EXCEL .
  "实例化LCL_DOCUMENT
  CALL METHOD LCL_CONTROL->GET_DOCUMENT_PROXY
    EXPORTING
*     DOCUMENT_FORMAT    = 'NATIVE'
      DOCUMENT_TYPE  = 'EXCEL.SHEET' "应用类型
      NO_FLUSH       = 'X'
*     REGISTER_CONTAINER = ' '
    IMPORTING
      DOCUMENT_PROXY = LCL_DOCUMENT
*     ERROR          =
*     RETCODE        =
    .
  "创建EXCEL文件
  CALL METHOD LCL_DOCUMENT->CREATE_DOCUMENT
    EXPORTING
*     CREATE_VIEW_DATA = ' '
      DOCUMENT_TITLE = 'DOI TEST'
*     NO_FLUSH       = 'X'
      OPEN_INPLACE   = 'X' "嵌入显示
*     OPEN_READONLY  = 'X' "只读
*     ONSAVE_MACRO   = 'X'
*     STARTUP_MACRO  = 'X'
*  IMPORTING
*     ERROR          =
*     RETCODE        =
    .


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_SET_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM FRM_SET_DATA .
  DATA LV_ROW TYPE I."填充数据的行数
  DATA:LS_RANGE       TYPE SOI_RANGE_ITEM,
       LT_RANGE       TYPE TABLE OF SOI_RANGE_ITEM, "为SET_RANGE_DATA方法标明填充数据的范围名及其行列数
       LS_CONTENT     TYPE SOI_GENERIC_ITEM,
       LT_CONTENT     TYPE TABLE OF SOI_GENERIC_ITEM, "为SET_RANGE_DATA方法提供填充数据
       LS_FORMATTABLE TYPE  SOI_FORMAT_ITEM, "设置范围格式
       LT_FORMATTABLE TYPE TABLE OF SOI_FORMAT_ITEM. "设置范围格式

  DATA LV_COUNT_ROW TYPE I."当前行
  DATA LV_LABST TYPE C LENGTH 18.
  FIELD-SYMBOLS:<FS_DATA_FILED>,
                <FS_CONTENT_FIELD>.
  SELECT MARD~WERKS,
         MARD~LGORT,
         MARD~MATNR,
         MAKT~MAKTX,
         MARD~LABST,
         MARA~MEINS
  INTO TABLE @GT_DATA UP TO 200 ROWS
  FROM MARD INNER JOIN MARA
  ON MARD~MATNR = MARA~MATNR
  LEFT OUTER JOIN MAKT
  ON MARD~MATNR = MAKT~MATNR
  WHERE MAKT~SPRAS = @SY-LANGU.
  DESCRIBE TABLE GT_DATA LINES LV_ROW."填充数据行数

  DATA A1 TYPE I.
  CALL METHOD LCL_DOCUMENT->HAS_SPREADSHEET_INTERFACE
    EXPORTING
      NO_FLUSH     = 'X'
    IMPORTING
*     ERROR        =
      IS_AVAILABLE = A1
*     RETCODE      =
    .
  "实例化SHEET对象
  CALL METHOD LCL_DOCUMENT->GET_SPREADSHEET_INTERFACE
    EXPORTING
      NO_FLUSH        = 'X'
    IMPORTING
*     ERROR           =
      SHEET_INTERFACE = LCL_SHEET
*     RETCODE         =
    .
  "选中SHEET1
  CALL METHOD LCL_SHEET->SELECT_SHEET
    EXPORTING
      NAME     = 'Sheet1'
      NO_FLUSH = 'X'
*  IMPORTING
*     ERROR    =
*     RETCODE  =
    .
*CALL METHOD LCL_SHEET->GET_ACTIVE_SHEET
*  EXPORTING
*    NO_FLUSH  = 'X'
**  IMPORTING
**    SHEETNAME =
**    ERROR     =
**    RETCODE   =
*    .
  "创建一个左上角为第一行第一列,共计6列200行,名叫RANGE1的范围对象
  CALL METHOD LCL_SHEET->INSERT_RANGE_DIM
    EXPORTING
      NO_FLUSH = 'X'
      NAME     = 'RANGE1'
      LEFT     = 1
      TOP      = 1
      ROWS     = LV_ROW
      COLUMNS  = 6
*     UPDATING = -1
*     SHEETNAME = ''
*  IMPORTING
*     ERROR    =
*     RETCODE  =
    .
  LT_RANGE = VALUE #( ( NAME = 'RANGE1' ROWS = LV_ROW COLUMNS = '6' ) ).
  LOOP AT GT_DATA INTO GS_DATA.
    LV_COUNT_ROW = SY-TABIX.
    DO 6 TIMES.
      ASSIGN COMPONENT SY-INDEX OF STRUCTURE GS_DATA TO <FS_DATA_FILED>.
      LS_CONTENT-ROW = LV_COUNT_ROW.
      LS_CONTENT-COLUMN = SY-INDEX.
      IF SY-INDEX = 5.
        LV_LABST = <FS_DATA_FILED>.
        CONDENSE LV_LABST NO-GAPS.
        LS_CONTENT-VALUE = LV_LABST.
      ELSE.
        LS_CONTENT-VALUE = <FS_DATA_FILED>.
      ENDIF.
      APPEND LS_CONTENT TO LT_CONTENT.
      CLEAR LS_CONTENT.
    ENDDO.
    CLEAR GS_DATA.
  ENDLOOP.
  "填充数据
  CALL METHOD LCL_SHEET->SET_RANGES_DATA
    EXPORTING
      NO_FLUSH = 'X'
      RANGES   = LT_RANGE
      CONTENTS = LT_CONTENT
*     UPDATING = -1
*     RANGESDEF =
*    IMPORTING
*     ERROR    =
*     RETCODE  =
    .
  "设置范围字体格式
  LT_FORMATTABLE = VALUE #( ( NAME = 'RANGE1' SIZE = 11 BOLD = 1 ALIGN = 1 ) )."RANGE1字体大小11 加粗 水平居中
  CALL METHOD LCL_SHEET->SET_RANGES_FORMAT
    EXPORTING
      FORMATTABLE = LT_FORMATTABLE
      NO_FLUSH    = 'X'
*     UPDATING    = -1
*    IMPORTING
*     ERROR       =
*     RETCODE     =
    .
  "设置范围边框格式
  CALL METHOD LCL_SHEET->SET_FRAME
    EXPORTING
      RANGENAME = 'RANGE1'
      TYP       = '127'
      COLOR     = 1
*     NO_FLUSH  = ' '
*    IMPORTING
*     ERROR     =
*     RETCODE   =
    .
  "设置列自动优化
  CALL METHOD LCL_SHEET->FIT_WIDEST
    EXPORTING
      NO_FLUSH = 'X'
      NAME     = 'RANGE1'
*    IMPORTING
*     ERROR    =
*     RETCODE  =
    .


  "更改SHEET名称
  CALL METHOD LCL_SHEET->SET_SHEET_NAME
    EXPORTING
      NEWNAME  = '可用库存清单'
      OLDNAME  = 'Sheet1'
      NO_FLUSH = 'X'
*    IMPORTING
*     ERROR    =
*     RETCODE  =
    .
  "保存文件(该方法会自动默认保存到c盘用户文件下的文档文件夹中)
  CALL METHOD LCL_DOCUMENT->SAVE_AS
    EXPORTING
      FILE_NAME = '可用库存清单'
      NO_FLUSH  = 'X'
*     PROMPT_USER = ' '
*     IMPORTING
*     ERROR     =
*     RETCODE   =
    .


ENDFORM.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
  SET PF-STATUS 'STANDARD'.
  SET TITLEBAR 'DOI TEST'.
  "实例化容器
  PERFORM FRM_CONTAINER.
  "创建容器控制器
  PERFORM FRM_CONTAINER_CONTROL.
  "创建EXCEL文档
  PERFORM FRM_CREATE_EXCEL.
  "填充数据
  PERFORM FRM_SET_DATA.
ENDMODULE.
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
"退出时释放实例。
  IF LCL_DOCUMENT IS NOT INITIAL.
    CALL METHOD LCL_DOCUMENT->CLOSE_DOCUMENT.
  ENDIF.
  IF LCL_CONTAINER IS NOT INITIAL.
    CALL METHOD LCL_CONTAINER->FREE.
  ENDIF.
  IF LCL_CONTROL IS NOT INITIAL.
    CALL METHOD LCL_CONTROL->DESTROY_CONTROL.
    FREE LCL_CONTROL.
  ENDIF.
  LEAVE PROGRAM.
ENDMODULE.
原文地址:https://www.cnblogs.com/jianglaizhen/p/8779036.html