欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SO_DOCUMENT_SEND_API1发送邮件EXCEL附件存在乱码以及cl_bcs方式解决

程序员文章站 2022-03-18 20:41:24
...

使用SO_DOCUMENT_SEND_API1发送邮件的时候发现可能存在附件Excel文件有中文乱码的情况,这个时候可以考虑用cl_bcs的方式来实现邮件发送的功能。

首先第一个是原先的方式:

*&---------------------------------------------------------------------*
*& Report ZR_EXAMPLE_11
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zr_example_11.

DATA:doc_chng LIKE sodocchgi1, "邮件标题及优先级
     objtxt   LIKE solisti1 OCCURS 10 WITH HEADER LINE, "邮件内容
**********邮件类型(内容大小、附件类型)
     objpack  LIKE sopcklsti1 OCCURS 2 WITH HEADER LINE, "附件名称
     objhead  LIKE solisti1 OCCURS 1 WITH HEADER LINE, "附件数据
     objbin   LIKE solisti1 OCCURS 10 WITH HEADER LINE, "附件数据
     reclist  LIKE somlreci1 OCCURS 5 WITH HEADER LINE. "收件人

DATA:tab_lines LIKE sy-tabix.
*DATA:lspfli LIKE STANDARD TABLE OF spfli WITH HEADER LINE.
DATA:lt_zsdt0019b TYPE TABLE OF zsdt0019b,
     ls_zsdt0019b TYPE zsdt0019b.

PARAMETERS:mailadd(50).

doc_chng-obj_descr = '邮件标题'."邮件标题
doc_chng-priority = 1."邮件的优先级,1为*

"定义邮件主体内容
objtxt = '最新的'.
APPEND objtxt.

objtxt = '这个是第二行的内容'.
APPEND objtxt.

"根据邮件主题内容计算其行数
DESCRIBE TABLE objtxt LINES tab_lines.
CLEAR objpack-transf_bin.
objpack-head_start = 1.
objpack-head_num = 1.
objpack-body_start = 1.
objpack-body_num = tab_lines.
objpack-doc_type = 'RAW'.
APPEND objpack.

"调用子程序获取需要传输数据并存入附件内表
PERFORM getfieldvalue.
DESCRIBE TABLE objbin LINES tab_lines.

"设置附件名称
objhead = 'REPORT.XLS'.
APPEND objhead.

"计算附件大小分配空间
objpack-transf_bin = 'X'.
objpack-head_start = 1.
objpack-head_num = 1.
objpack-body_start = 1.
objpack-body_num = tab_lines.
objpack-doc_type = 'xls'."附件可以支持XLS、txt、dat等格式的文件
objpack-doc_size = tab_lines."255
APPEND objpack.

*reclist-receiver = '[email protected]'."定义收件人
*reclist-rec_type = 'U'."定义Mail地址类型,U表示的是Internet地址
*APPEND reclist.
reclist-receiver = '[email protected]'."定义收件人
reclist-rec_type = 'U'."定义Mail地址类型,U表示的是Internet地址
APPEND reclist.

DATA et_vsi_error LIKE  bapiret2 OCCURS 1 WITH HEADER LINE.

"调用发送邮件的函数
CALL FUNCTION 'SO_DOCUMENT_SEND_API1'
  EXPORTING
    document_data              = doc_chng
    put_in_outbox              = 'X'
    sender_address             = 'MAILSERVER'
    sender_address_type        = 'B'
*   COMMIT_WORK                = ' '
*   IP_ENCRYPT                 =
*   IP_SIGN                    =
*   IV_VSI_PROFILE             =
* IMPORTING
*   SENT_TO_ALL                =
*   NEW_OBJECT_ID              =
*   SENDER_ID                  =
  TABLES
    packing_list               = objpack
    object_header              = objhead
    contents_bin               = objbin
    contents_txt               = objtxt
*   CONTENTS_HEX               =
*   OBJECT_PARA                =
*   OBJECT_PARB                =
    receivers                  = reclist
    et_vsi_error               = et_vsi_error
  EXCEPTIONS
    too_many_receivers         = 1
    document_not_sent          = 2
    document_type_not_exist    = 3
    operation_no_authorization = 4
    parameter_error            = 5
    x_error                    = 6
    enqueue_error              = 7
    OTHERS                     = 8.
IF sy-subrc <> 0.
* Implement suitable error handling here
ELSE.
  COMMIT WORK.
  DATA c_dev TYPE sy-sysid.
  c_dev = sy-sysid.

  IF sy-sysid = c_dev.
    WAIT UP TO 1 SECONDS.
*      SUBMIT RSCONN01 WITH MODE = 'INT'
*      WITH OUTPUT = 'X'
*      AND RETURN.
    SUBMIT rsconn01 WITH mode = 'INT'
*      WITH OUTPUT = 'X'
    AND RETURN.
  ENDIF.
ENDIF.







FORM getfieldvalue.
  DATA:wrepid TYPE sy-repid.
  wrepid = sy-repid.

  CONSTANTS:
    con_tab TYPE c VALUE cl_abap_char_utilities=>horizontal_tab, "TAB制表符
    con_cr  TYPE c VALUE cl_abap_char_utilities=>cr_lf, "换行
    con_lf  TYPE c VALUE cl_abap_char_utilities=>newline. "创建新的一行

  SELECT * FROM zsdt0019b
    INTO CORRESPONDING FIELDS OF TABLE lt_zsdt0019b.
  CLEAR objbin.

  DEFINE  header.
    objbin-line = &1.
    APPEND objbin.
    objbin-line = con_tab.
    APPEND objbin.
  END-OF-DEFINITION.
  objbin-line = con_lf.
  APPEND objbin.
  objbin-line = con_tab.
  APPEND objbin.


  objbin-line = '123'.
  APPEND objbin.
  objbin-line = con_tab.
  APPEND objbin.
  objbin-line = '234'.
  APPEND objbin.

  objbin-line = con_lf.
  APPEND objbin.

  LOOP AT lt_zsdt0019b INTO ls_zsdt0019b.
    CLEAR:objbin.
    "在输出数据前面加入一空格有利于调整格式
    CONCATENATE ' ' objbin-line INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    "将输出内容转移到附件内表,附件内表中只有一行用来保存数据,注意,每行最大字符数为255个
    CONCATENATE  con_tab ls_zsdt0019b-stat INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-statdetail INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-udate INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-erdat INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-kunnr INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-vkorg INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-vtweg INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.
    CONCATENATE  con_tab ls_zsdt0019b-spart INTO objbin-line.
    APPEND objbin.
    CLEAR objbin.

    "在每行结尾加入换行
    CONCATENATE objbin-line con_lf INTO objbin-line.
    APPEND objbin.
    CLEAR ls_zsdt0019b.
  ENDLOOP.



ENDFORM.

上面会出现中文乱码的问题,下面的是使用cl_bcs的方式:

*&---------------------------------------------------------------------*
*& Report ZHKALV2
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zhkalv2.
* This report provides an example for sending an Excel
* attachment in Unicode Systems

CONSTANTS:
  gc_tab  TYPE c VALUE cl_bcs_convert=>gc_tab,
  gc_crlf TYPE c VALUE cl_bcs_convert=>gc_crlf.

PARAMETERS:
mailto TYPE ad_smtpadr
DEFAULT '[email protected]'.                               "#EC *

DATA send_request   TYPE REF TO cl_bcs.
DATA document       TYPE REF TO cl_document_bcs.
DATA recipient      TYPE REF TO if_recipient_bcs.
DATA: bcs_exception TYPE REF TO cx_bcs,
      lo_sender     TYPE REF TO cl_sapuser_bcs.

DATA main_text      TYPE bcsy_text.
DATA binary_content TYPE solix_tab.
DATA size           TYPE so_obj_len.
DATA sent_to_all    TYPE os_boolean.

START-OF-SELECTION.
  PERFORM create_content.
  PERFORM send.

*&---------------------------------------------------------------------*
*&      Form  send
*&---------------------------------------------------------------------*
FORM send.

  TRY.

*     -------- create persistent send request ------------------------
      send_request = cl_bcs=>create_persistent( ).

*     -------- create and set document with attachment ---------------
*     create document object from internal table with text
      APPEND '你好' TO main_text.                             "#EC NOTEXT
      document = cl_document_bcs=>create_document(
      i_type    = 'RAW'
      i_text    = main_text
      i_subject = '这个是测试' ).        "#EC NOTEXT

*     add the spread sheet as attachment to document object
      document->add_attachment(
      i_attachment_type    = 'xls'                          "#EC NOTEXT
      i_attachment_subject = '附件'                           "#EC NOTEXT
      i_attachment_size    = size
      i_att_content_hex    = binary_content ).
*     发件人
*     前提是这个邮箱地址能发邮件,并且不需要密码
      lo_sender = cl_sapuser_bcs=>create( 'MAILSERVER' ).
      send_request->set_sender( lo_sender ).
*     add 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 ).
      recipient = cl_cam_address_bcs=>create_internet_address( '[email protected]' ).
      send_request->add_recipient( recipient ).
*     ---------- send document ---------------------------------------
*      sent_to_all = send_request->send( i_with_error_screen = 'X' ).

      send_request->set_send_immediately( 'X' ).  "设置立即发送
      send_request->send_request->set_link_to_outbox( 'X' ). "与outbox关联
      CALL METHOD send_request->set_document( document ).
      CALL METHOD send_request->send(
        EXPORTING
          i_with_error_screen = 'X'
        RECEIVING
          result              = sent_to_all ).
      COMMIT WORK AND WAIT.

      IF sent_to_all = 'X'.
        MESSAGE '发送成功' TYPE 'S'.
      ELSE.
        ROLLBACK WORK.
        MESSAGE '发送失败' TYPE 'S' DISPLAY LIKE 'E'.
        STOP.
      ENDIF.

*   ------------ exception handling ----------------------------------
*   replace this rudimentary exception handling with your own one !!!
    CATCH cx_bcs INTO bcs_exception.
      MESSAGE i865(so) WITH bcs_exception->error_type.
  ENDTRY.

ENDFORM.                    "send

*&---------------------------------------------------------------------*
*&      Form  create_content
*&---------------------------------------------------------------------*
* Create Example Content
* 1) Write example text into a string
* 2) convert this string to solix_tab
*----------------------------------------------------------------------*
FORM create_content.

  DATA lv_string TYPE string.
  DATA ls_zsdt0019b TYPE zsdt0019b.

* --------------------------------------------------------------
* as example content we use some system messages out of t100
* get them for all installed languages from db
* and write one line for each language into the spread sheet

* columns are separated by TAB and each line ends with CRLF

  CONCATENATE '这个是报表'                                       "#EC NOTEXT
  gc_crlf gc_crlf
  INTO lv_string.

* header line
  CONCATENATE lv_string
  '订单状态'    gc_tab
  '订单状态描述'    gc_tab
  '二审日期'    gc_tab
  '创建日期'    gc_tab
  '售达方'    gc_tab
  '销售组织'    gc_tab
  '分销渠道'    gc_tab
  '产品组'    gc_tab
  '检索项'    gc_tab
  '实际客户'    gc_tab

  '业务员'    gc_tab
  '业务员名称'    gc_tab
  '订单类型'    gc_tab
  '订单类型描述'    gc_tab
  '单据号'    gc_tab
  '付款方式'    gc_tab
  '产品编号'    gc_tab
  '行号'    gc_tab
  '产品名称'    gc_tab
  '规格型号'    gc_tab
  '包装规格'    gc_tab
  '基本计量数量'    gc_tab

  '基本计量单位'    gc_tab
  '销售数量'    gc_tab
  '销售单位'    gc_tab
  '折前单价'    gc_tab
  '价税合计'    gc_tab
  '计划行类型'    gc_tab
  '内部交货日期'    gc_tab
  'ATP答复日期'    gc_tab
  '出库量'    gc_tab
  '制单人'    gc_tab
  '非限制库存'    gc_tab
  '物料中类名称'    gc_crlf "#EC NOTEXT                                        "#EC NOTEXT
  INTO lv_string.
  DATA:lv_kwmeng(30),
       lv_kwmeng2(30),
       lv_kbetr(30),
       lv_netwr(30),
       lv_rfmng(30),
       lv_kalab(30).

* data lines
  SELECT * FROM zsdt0019b INTO ls_zsdt0019b UP TO 20 ROWS.
    CLEAR:
    lv_kwmeng,
    lv_kwmeng2,
    lv_kbetr,
    lv_netwr,
    lv_rfmng,
    lv_kalab.

    lv_kwmeng = ls_zsdt0019b-kwmeng.
    lv_kwmeng2 = ls_zsdt0019b-kwmeng2.
    lv_kbetr = ls_zsdt0019b-kbetr.
    lv_netwr = ls_zsdt0019b-netwr.
    lv_rfmng = ls_zsdt0019b-rfmng.
    lv_kalab = ls_zsdt0019b-kalab.

    CONCATENATE lv_string
    ls_zsdt0019b-stat gc_tab
    ls_zsdt0019b-statdetail gc_tab
    ls_zsdt0019b-udate gc_tab
    ls_zsdt0019b-erdat gc_tab
    ls_zsdt0019b-kunnr gc_tab
    ls_zsdt0019b-vkorg gc_tab
    ls_zsdt0019b-vtweg gc_tab
    ls_zsdt0019b-spart gc_tab
    ls_zsdt0019b-bu_sort1 gc_tab
    ls_zsdt0019b-kunnr2 gc_tab

    ls_zsdt0019b-kunn2 gc_tab
    ls_zsdt0019b-name_org1 gc_tab
    ls_zsdt0019b-auart gc_tab
    ls_zsdt0019b-bezei gc_tab
    ls_zsdt0019b-vbeln gc_tab
    ls_zsdt0019b-text1 gc_tab
    ls_zsdt0019b-matwa gc_tab
    ls_zsdt0019b-posnr gc_tab
    ls_zsdt0019b-maktx gc_tab
    ls_zsdt0019b-groes gc_tab
    ls_zsdt0019b-atwrt gc_tab
    lv_kwmeng gc_tab

    ls_zsdt0019b-meins gc_tab
    lv_kwmeng2 gc_tab
    ls_zsdt0019b-vrkme gc_tab
    lv_kbetr gc_tab
    lv_netwr gc_tab
    ls_zsdt0019b-ettyp gc_tab
    ls_zsdt0019b-znbjhq gc_tab
    ls_zsdt0019b-zatpdfrq gc_tab
    lv_rfmng gc_tab
    ls_zsdt0019b-name_text gc_tab
    lv_kalab gc_tab
    ls_zsdt0019b-wgbez  gc_crlf
    INTO lv_string.

  ENDSELECT.

*  SELECT * FROM t100 INTO ls_t100
*  WHERE arbgb = 'SO' AND msgnr = '316'.
*
*    CONCATENATE lv_string
*    ls_t100-arbgb gc_tab
*    ls_t100-msgnr gc_tab
*    ls_t100-sprsl gc_tab
*    ls_t100-text  gc_crlf
*    INTO lv_string.
*
*  ENDSELECT.

* --------------------------------------------------------------
* convert the text string into UTF-16LE binary data including
* byte-order-mark. Mircosoft Excel prefers these settings
* all this is done by new class cl_bcs_convert (see note 1151257)

  TRY.
      cl_bcs_convert=>string_to_solix(
      EXPORTING
        iv_string   = lv_string
        iv_codepage = '4103'  "suitable for MS Excel, leave empty
        iv_add_bom  = 'X'     "for other doc types
      IMPORTING
        et_solix  = binary_content
        ev_size   = size ).
    CATCH cx_bcs.
      MESSAGE e445(so).
  ENDTRY.

ENDFORM.                    "create_content