• SAP内表数据作为带有格式的excel附件 发送邮件


    从 Office2007开始, 当我们新建一个word、excel等文档时,后者遵循了一个开源的规范:Office openXML格式。

    所以可以使用ABAP直接创建一个符合上述规范的XML,就可以得到相应的word、excel 用于下载或者作为邮件附件。

    openXML介绍:https://baike.baidu.com/item/openXML/8399547?fr=aladdin

    ABAP解析XML:https://www.cnblogs.com/jiangzhengjun/p/4265595.html

    代码:

    *&---------------------------------------------------------------------*
    *& Report  z_test
    *&
    *&---------------------------------------------------------------------*
    *&
    *&
    *&---------------------------------------------------------------------*
    
    REPORT  z_test.
    
    TYPE-POOLS: ixml.
    
    *----------------------------------------------------------------------*
    * global variable
    *----------------------------------------------------------------------*
    DATA:
          l_xml_table_forecast    TYPE TABLE OF x255,
          l_rc                    TYPE i,
          l_xml_size              TYPE i,
          binary_content_forecast TYPE solix_tab,
          sent_to_all             TYPE os_boolean,
          main_text               TYPE bcsy_text,
          send_request            TYPE REF TO cl_bcs,
          document                TYPE REF TO cl_document_bcs,
          recipient               TYPE REF TO if_recipient_bcs,
          bcs_exception           TYPE REF TO cx_bcs,
          mailto                  TYPE ad_smtpadr VALUE 'XXXXX@163.com'. "此处填入自己的邮箱
    
    *----------------------------------------------------------------------*
    * Table
    *----------------------------------------------------------------------*
    DATA: gt_sflight              TYPE TABLE OF sflight,
          gs_sflight              TYPE sflight.
    
    *----------------------------------------------------------------------*
    * Start-of-selection.
    *----------------------------------------------------------------------*
    START-OF-SELECTION.
    
      PERFORM frm_get_flight.
    
      PERFORM frm_process_xml_data.
    
      PERFORM frm_send_email.
    
    *&---------------------------------------------------------------------*
    *&      Form  FRM_GET_FLIGHT
    *&---------------------------------------------------------------------*
    *       附件数据
    *----------------------------------------------------------------------*
    *  -->  p1        text
    *  <--  p2        text
    *----------------------------------------------------------------------*
    FORM frm_get_flight .
    
      SELECT * UP TO 10 ROWS                                    "搜10行
        FROM sflight
        INTO CORRESPONDING FIELDS OF TABLE gt_sflight.
    ENDFORM.                    " FRM_GET_FLIGHT
    *&---------------------------------------------------------------------*
    *&      Form  FRM_PROCESS_XML_DATA
    *&---------------------------------------------------------------------*
    *       附件xml
    *----------------------------------------------------------------------*
    *      -->P_1      text
    *----------------------------------------------------------------------*
    FORM frm_process_xml_data.
      DATA: l_ixml          TYPE REF TO if_ixml,
            l_streamfactory TYPE REF TO if_ixml_stream_factory,
            l_ostream       TYPE REF TO if_ixml_ostream,
            l_renderer      TYPE REF TO if_ixml_renderer,
            l_document      TYPE REF TO if_ixml_document.
    
      DATA: l_element_root  TYPE REF TO if_ixml_element,
            r_element       TYPE REF TO if_ixml_element,
            r_worksheet     TYPE REF TO if_ixml_element,
            r_table         TYPE REF TO if_ixml_element,
            r_column        TYPE REF TO if_ixml_element,
            r_row           TYPE REF TO if_ixml_element,
            r_cell          TYPE REF TO if_ixml_element,
            r_data          TYPE REF TO if_ixml_element,
            l_value         TYPE string.
    
      FIELD-SYMBOLS:<ls_flight> TYPE sflight.
    
    *  create a ixml factory
      l_ixml = cl_ixml=>create( ).
    
    *  create the DOM object model
      l_document = l_ixml->create_document( ).
    
    *  create workbook
      PERFORM create_workbook USING l_document r_worksheet r_table.
    
    *  column formatting
      PERFORM frm_forecast_column_format USING l_document r_table.
    
    *  data table
      LOOP AT gt_sflight ASSIGNING <ls_flight>.
        r_row = l_document->create_simple_element( name = 'Row' parent = r_table ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-mandt.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-carrid.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-connid.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        "这一列的cell都使用了预定义的Style:Detail
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        r_cell->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = 'Detail').
        l_value = <ls_flight>-fldate.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-price.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-currency.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-planetype.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
        r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ).
        l_value = <ls_flight>-seatsmax.
        r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ).
        r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    
      ENDLOOP.
    
    * XML作为二进制数据流保存到内表
    *   creating a stream factory
      l_streamfactory = l_ixml->create_stream_factory( ).
    
    *   connect internal xml table to stream factory
      l_ostream = l_streamfactory->create_ostream_itable( table = l_xml_table_forecast ).
    
    *   rendering the document
      l_renderer = l_ixml->create_renderer( ostream = l_ostream document = l_document ).
      l_rc = l_renderer->render( ).
    
    * saving the xml document
      l_xml_size = l_ostream->get_num_written_raw( ).
    ENDFORM.                    " FRM_PROCESS_XML_DATA
    *&---------------------------------------------------------------------*
    *&      Form  CREATE_WORKBOOK
    *&---------------------------------------------------------------------*
    *       新建工作区
    *----------------------------------------------------------------------*
    *      -->P_L_DOCUMENT  text
    *      -->P_R_WORKSHEET  text
    *      -->P_R_TABLE  text
    *----------------------------------------------------------------------*
    FORM create_workbook USING l_document  TYPE REF TO if_ixml_document
                               r_worksheet TYPE REF TO if_ixml_element
                               r_table     TYPE REF TO if_ixml_element.
    
      DATA: l_element_root        TYPE REF TO if_ixml_element,
            ns_attribute          TYPE REF TO if_ixml_attribute,
            r_element_properties  TYPE REF TO if_ixml_element,
            r_styles              TYPE REF TO if_ixml_element,
            r_style               TYPE REF TO if_ixml_element,
            r_border              TYPE REF TO if_ixml_element,
            r_format              TYPE REF TO if_ixml_element,
            l_value               TYPE string.
    
    *  create root node 'workbook'
      l_element_root = l_document->create_simple_element( name = 'Workbook' parent = l_document ).
      l_element_root->set_attribute( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:spreadsheet' ).
    
      ns_attribute = l_document->create_namespace_decl( name = 'ss' prefix = 'xmlns' 
    uri = 'urn:schemas-microsoft-com:office:spreadsheet' ). l_element_root->set_attribute_node( ns_attribute ). ns_attribute = l_document->create_namespace_decl( name = 'x' prefix = 'xmlns'
                                   uri = 'urn:schemas-microsoft-com:office:excel' ). l_element_root->set_attribute_node( ns_attribute ). * create node for document properties r_element_properties = l_document->create_simple_element( name = 'TEST_REPORT' parent = l_element_root ). l_value = sy-uname. l_document->create_simple_element( name = 'Author' value = l_value parent = r_element_properties ). * Styles(类似css,可以被cell使用) r_styles = l_document->create_simple_element( name = 'Styles' parent = l_element_root ). * 预定义表头格式:Head r_style = l_document->create_simple_element( name = 'Style' parent = r_styles ). r_style->set_attribute_ns( name = 'ID' prefix = 'ss' value = 'Head' ). "边框 r_border = l_document->create_simple_element( name = 'Borders' parent = r_style ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Bottom' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '2' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Left' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '2' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Top' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '2' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Right' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '2' ). "颜色 r_format = l_document->create_simple_element( name = 'Interior' parent = r_style ). r_format->set_attribute_ns( name = 'Color' prefix = 'ss' value = '#BFBFBF' ). r_format->set_attribute_ns( name = 'Pattern' prefix = 'ss' value = 'Solid' ). "格式居中 r_format = l_document->create_simple_element( name = 'Alignment' parent = r_style ). r_format->set_attribute_ns( name = 'Horizontal' prefix = 'ss' value = 'Center' ). r_format->set_attribute_ns( name = 'Vertical' prefix = 'ss' value = 'Center' ). r_format->set_attribute_ns( name = 'WrapText' prefix = 'ss' value = '1' ). * 预定义明细格式格式:Detail r_style = l_document->create_simple_element( name = 'Style' parent = r_styles ). r_style->set_attribute_ns( name = 'ID' prefix = 'ss' value = 'Detail' ). "边框 r_border = l_document->create_simple_element( name = 'Borders' parent = r_style ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Bottom' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '1' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Left' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '1' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Top' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '1' ). r_format = l_document->create_simple_element( name = 'Border' parent = r_border ). r_format->set_attribute_ns( name = 'Position' prefix = 'ss' value = 'Right' ). r_format->set_attribute_ns( name = 'LineStyle' prefix = 'ss' value = 'Continuous' ). r_format->set_attribute_ns( name = 'Weight' prefix = 'ss' value = '1' ). * worksheet r_worksheet = l_document->create_simple_element( name = 'Worksheet' parent = l_element_root ). r_worksheet->set_attribute_ns( name = 'Name' prefix = 'ss' value = 'Sheet1' ). * table r_table = l_document->create_simple_element( name = 'Table' parent = r_worksheet ). r_table->set_attribute_ns( name = 'FullColumns' prefix = 'x' value = '1' ). r_table->set_attribute_ns( name = 'FullRows' prefix = 'x' value = '1' ). ENDFORM. " CREATE_WORKBOOK *&---------------------------------------------------------------------* *& Form FRM_FORECAST_COLUMN_FORMAT *&---------------------------------------------------------------------* * 表头 *----------------------------------------------------------------------* * -->P_L_DOCUMENT text * -->P_R_TABLE text *----------------------------------------------------------------------* FORM frm_forecast_column_format USING l_document TYPE REF TO if_ixml_document r_table TYPE REF TO if_ixml_element. DATA: l_element_root TYPE REF TO if_ixml_element, r_column TYPE REF TO if_ixml_element, r_row TYPE REF TO if_ixml_element, r_cell TYPE REF TO if_ixml_element, r_data TYPE REF TO if_ixml_element, l_value TYPE string. DATA: lv_exe_date TYPE char10, lv_exe_time TYPE char10, lt_month_names TYPE TABLE OF t247, ls_month_name TYPE t247, lv_date_add TYPE sy-datum, lv_count TYPE i. WRITE sy-datum TO lv_exe_date. CONCATENATE sy-uzeit+0(2) ':' sy-uzeit+2(2) INTO lv_exe_time. CALL FUNCTION 'MONTH_NAMES_GET' EXPORTING language = sy-langu TABLES month_names = lt_month_names EXCEPTIONS month_names_not_found = 1 OTHERS = 2. IF sy-subrc = 0. READ TABLE lt_month_names WITH KEY mnr = sy-datum+4(2) INTO ls_month_name. ENDIF. * Format columns width based on the data length 设定sheet前8列的列宽 * line DO 1 TIMES. r_column = l_document->create_simple_element( name = 'Column' parent = r_table ). r_column->set_attribute_ns( name = 'Width' prefix = 'ss' value = '30' ). ENDDO. DO 14 TIMES. r_column = l_document->create_simple_element( name = 'Column' parent = r_table ). r_column->set_attribute_ns( name = 'Width' prefix = 'ss' value = '100' ). ENDDO. * information row 基本信息 r_row = l_document->create_simple_element( name = 'Row' parent = r_table ). r_row->set_attribute_ns( name = 'AutoFitHeight' prefix = 'ss' value = '1' ). * type r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). l_value = 'SFLIGHT_FORECAST'. r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). DO 3 TIMES. "空三个cell r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). ENDDO. * name r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). l_value = 'TEST_USER'. r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * Date r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). l_value = lv_exe_date. r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * Time r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). l_value = lv_exe_time. r_data = l_document->create_simple_element( name = 'Data' value = l_value parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * Column Headers Row 表头行 r_row = l_document->create_simple_element( name = 'Row' parent = r_table ). r_row->set_attribute_ns( name = 'AutoFitHeight' prefix = 'ss' value = '1' ). * mandt r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'mandt' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * carrid r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'carrid' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * connid r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'connid' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * fldate 这个cell使用了预定义的Style:Head r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_cell->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = 'Head'). r_data = l_document->create_simple_element( name = 'Data' value = 'fldate' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * price r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'price' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * currency r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'currency' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * planetype r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'planetype' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). * seatsmax r_cell = l_document->create_simple_element( name = 'Cell' parent = r_row ). r_data = l_document->create_simple_element( name = 'Data' value = 'seatsmax' parent = r_cell ). r_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). ENDFORM. " FRM_FORECAST_COLUMN_FORMAT *&---------------------------------------------------------------------* *& Form FRM_SEND_EMAIL *&---------------------------------------------------------------------* * 发邮件 *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM frm_send_email . DATA:ls_solix TYPE solix, lc_xls_type TYPE so_obj_tp VALUE 'XLS', lt_binary_content TYPE solix_tab. "二进制文件 LOOP AT l_xml_table_forecast INTO ls_solix-line. APPEND ls_solix TO binary_content_forecast. CLEAR ls_solix. ENDLOOP. TRY . * -------------create persistent sent request---------------- send_request = cl_bcs=>create_persistent( ). * -------------create and set document with attachment------- * create document object from internal table with text APPEND 'Mail text!' TO main_text. document = cl_document_bcs=>create_document( i_type = 'HTM' i_text = main_text i_subject = 'Test created' ). * add the spread sheet as attachment to document object * excel附件 document->add_attachment( i_attachment_type = lc_xls_type i_attachment_subject = 'SpreadSheet' i_att_content_hex = binary_content_forecast ). * send document object to send request send_request->set_document( document ). * --------------add recipient (e-mail address)-------------- * create recipient object recipient = cl_cam_address_bcs=>create_internet_address( mailto ). * add recipient object to send request send_request->add_recipient( recipient ). * --------------send document ------------------------------ CALL METHOD send_request->set_send_immediately( 'X' )."立即发送 sent_to_all = send_request->send( i_with_error_screen = 'X' ). COMMIT WORK. IF sent_to_all IS INITIAL. MESSAGE i500(sbcoms) WITH mailto. ELSE. MESSAGE s022(so). ENDIF. * ---------------exception handling ------------------------ CATCH cx_bcs INTO bcs_exception. MESSAGE i865(so) WITH bcs_exception->error_type. ENDTRY. ENDFORM. " FRM_SEND_EMAIL

    运行结果:

     

     附件:其中fldate列使用了格式

     参考:

    https://blogs.sap.com/2015/08/30/how-to-generate-a-formatted-excel-in-background-and-send-it-as-an-email-using-ixml-method/

    https://blogs.sap.com/2020/04/07/formatted-excel-using-xml/

  • 相关阅读:
    将数据保存在线程中
    OpenSmtp 的代码修正,支持中文和HTTP代理连接
    枚举.NET的基本类型
    通过HTTP代理连接到目的的协议
    程序出现了异常:应用程序无法启动,因为应用程序的并行配置不正确
    关于最近的一篇文章
    检测TextBox的回车键事件
    程序跳过trycatch地崩溃
    给程序加上UAC控制的几个链接
    Sql Server附加数据库的时候出现Operating system error 5: "5(Access is denied.)" 的错误
  • 原文地址:https://www.cnblogs.com/dy-debug/p/13920667.html
Copyright © 2020-2023  润新知