[SAP ABAP开发技术总结]将文件存储到数据库表中,并可发送邮件

时间:2024-06-15 09:07:14
[SAP ABAP开发技术总结]将文件存储到数据库表中,并可发送邮件
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4265704.html

的整数倍,因为在上传的过程中使用的是xtab255类型的内表,当最后一行不满255个字节时,也会在后面补上直到255个字节,但补的都是00这样的字节,所以文件大小还是有区别的,但经过测试pdf与mp3在码流后面补00字节好像没有什么影响唯独是文件大小变大了。但如果是TXT文件,打开后发现多了很多空格(按理来说也是什么也没有,因为空格的ASCII码为32,但后面补的是00字节)
的倍数,否则编译出错个字面上的十六进制字符才能表示一个字符C,所以从c_total以十六进制方式赋值给ctab255 时,缩短了3/4
    APPEND ctab255.
    CLEAR: c_tmp1.
  ENDIF.
ENDLOOP.
"可能是奇数后,所以需要判断一下,将最后一行也要附加上去
IF c_tmp1 IS NOT INITIAL.
  <x> = c_tmp1.
  APPEND ctab255.
ENDIF.

发送邮件

FORM send_email.
  DATA: BEGIN OF addr_email OCCURS 0,
      smtp_addr(241),
    END OF addr_email.

  DATA: i_receivers LIKE somlreci1 OCCURS 0 WITH HEADER LINE,
    i_message LIKE solisti1 OCCURS 0 WITH HEADER LINE.

  DATA: l_subject       TYPE so_obj_des,
        l_filename TYPE string.

  SELECT smtp_addr FROM zmm_invtr_email INTO TABLE addr_email.
  CHECK addr_email[] IS NOT INITIAL.

  LOOP AT addr_email.
    CLEAR:i_receivers.
    i_receivers-receiver = addr_email-smtp_addr.
    i_receivers-rec_type = 'U'.
    i_receivers-com_type = 'INT'.
*     i_receivers-copy = 'X'."CC
*     i_receivers-blind_copy = 'X'."BCC
    i_receivers-express = 'X'."TO
    APPEND i_receivers.
  ENDLOOP.

  l_subject = `hi,baby`."邮件标题
  l_filename = 'attach.txt'."附件文件名

  i_message-line = `邮件的内容`.
  APPEND i_message.

  DATA: t_atthead  TYPE STANDARD TABLE OF string,
        return TYPE bapiret1.

  PERFORM send_email_with_att_xls TABLES i_receivers
                                         i_message
                                         t_atthead
                                         <stat_tab>
                                  USING  l_subject
                                         sy-uname
                                         l_filename
                                         return.
*  MESSAGE return-message TYPE 'S' DISPLAY LIKE return-type.
ENDFORM.                    "export_xls

*&---------------------------------------------------------------------*
*&      Form  send_email_with_att_xls
*&---------------------------------------------------------------------*
*       带XLS附件的邮件发送
*----------------------------------------------------------------------*
*      -->T_RECEIVERS  邮件接收者
*      -->T_MESSAGE    邮件内容
*      -->T_ATTHEAD    XLS附件中标题(XLS首行内容)
*      -->T_ATTTAB     附件内容
*      -->IM_SUBJECT   邮件标题
*      -->IM_UNAME     邮件发送者
*      -->IM_FILENAME  附件名称
*      -->RETURN       返回信息
*----------------------------------------------------------------------*
FORM send_email_with_att_xls TABLES t_receivers STRUCTURE somlreci1
                                    t_message STRUCTURE solisti1
                                    t_atthead
                                    t_atttab
                             USING  im_subject TYPE so_obj_des
                                    im_uname TYPE uname
                                    im_filename TYPE string
                                    return TYPE bapiret1.
  CONSTANTS: c_tab  TYPE c VALUE cl_abap_char_utilities=>horizontal_tab,
             "回车换行,实质上对应 Xstring: 000D000A
             c_crlf(2) TYPE c VALUE cl_abap_char_utilities=>cr_lf.

  DATA: xstr TYPE xstring,
        it_binary_attach TYPE solix_tab.

************************将内表所有的内容存储到一个字符串中

  DATA: lc_descr_ref TYPE REF TO cl_abap_structdescr,
        lv_value     TYPE char128,
        lv_temp      TYPE string,
        lv_mid       TYPE string.

  FIELD-SYMBOLS: <fs_table> TYPE ANY.
  FIELD-SYMBOLS: <intable_wa> TYPE abap_compdescr.

  CLEAR lv_temp.
  "将头内表拼接成一个字符串
  IF t_atthead[] IS NOT INITIAL.
    LOOP AT t_atthead.
      IF sy-tabix = 1.
        lv_temp = t_atthead.
        CONTINUE.
      ENDIF.
      CONCATENATE lv_temp t_atthead
             INTO lv_temp SEPARATED BY c_tab.
    ENDLOOP.
    CONCATENATE lv_temp c_crlf INTO lv_mid.
  ENDIF.

  "将主体内表拼接成一个字符串
  LOOP AT t_atttab.
    lc_descr_ref ?= cl_abap_typedescr=>describe_by_data( t_atttab ).
    LOOP AT lc_descr_ref->components ASSIGNING <intable_wa>.
      ASSIGN COMPONENT sy-tabix OF STRUCTURE  t_atttab TO <fs_table>.
      "如果是数字类型时
      IF <intable_wa>-type_kind = 'P' OR <intable_wa>-type_kind = 'F'
        OR <intable_wa>-type_kind = 'I' OR <intable_wa>-type_kind = 'b'
        OR <intable_wa>-type_kind = 's'.
        IF <fs_table> = 0.
          CLEAR lv_value.
        ELSE.
          WRITE <fs_table> TO lv_value.
          CONDENSE lv_value NO-GAPS.
          IF <fs_table> < 0."将负号提前
            CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
              CHANGING
                value = lv_value.
            CONDENSE lv_value NO-GAPS.
          ENDIF.
        ENDIF.
      ELSE.
        lv_value = <fs_table>.
        CONDENSE lv_value.
      ENDIF.

      IF sy-tabix = 1.
        lv_temp = lv_value.
        CONTINUE.
      ENDIF.
      CONCATENATE lv_temp lv_value
             INTO lv_temp SEPARATED BY c_tab.
    ENDLOOP.
    CONCATENATE lv_mid lv_temp c_crlf INTO lv_mid.
  ENDLOOP.
************************将字符进行编码转换,转换为二进制字节码流
  DATA:  l_codepage(4) TYPE n .
  DATA:  l_encoding(20).

  "将外部字符集名转换为内部编码
  CALL FUNCTION 'SCP_CODEPAGE_BY_EXTERNAL_NAME'
    EXPORTING
      external_name = 'UTF-8'
    IMPORTING
      sap_codepage  = l_codepage.
  l_encoding = l_codepage.

  DATA: convout TYPE REF TO cl_abap_conv_out_ce.
  "创建编码对象
  convout = cl_abap_conv_out_ce=>create( encoding = l_encoding ).
  convout->write( data = lv_mid )."编码
  xstr =  convout->get_buffer( )."获取码流

************************接口转换:将码流按使用的参数接口要求进行重组转换
  "将 xstring 的字符串存储到行结构为 X 类型的内表中,以适合于邮件发
  "送接口。该函数并不是将 xstring 字符转换为 二进制(因为xstring本身就
  "是原生态,从函数名上看容易误导)。
  CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
    EXPORTING
      buffer     = xstr
    TABLES
      binary_tab = it_binary_attach.

*另外,也可以将行结构为 X 类型的内表中所有HEX内容拼接成一个Xstring并存储在l_xstr变量中,也不要被函*数名给迷糊了:并不是将二进制什么的转换为Xstring类型了,而只不过是将将内表结构转换为单一的字符串了

*data: l_xstr type xstring.
*  clear l_xstr.
*  call function 'SCMS_BINARY_TO_XSTRING'
*    exporting
*      input_length = l_len
*    importing
*      buffer       = l_xstr
*    tables
*      binary_tab   = it_binary_attach.
*-----------------------------------------------------------------------
* Send Email
*-----------------------------------------------------------------------

  DATA: lv_title      TYPE so_obj_des,             " Email Title
        lv_email      TYPE adsmtp-smtp_addr,  " Receiver
        lv_attitle    TYPE char50.           " Attachment Title

  DATA: send_request  TYPE REF TO cl_bcs,
        document      TYPE REF TO cl_document_bcs,
        conlengths    TYPE so_obj_len,
        html          TYPE TABLE OF w3html,
        recipient     TYPE REF TO if_recipient_bcs,
        sent_to_all   TYPE os_boolean,
        bcs_exception TYPE REF TO cx_bcs,
        bcs_message   TYPE string.
  DATA:   sender        TYPE REF TO cl_sapuser_bcs.

  TRY.
*     创建发送请求
      CLEAR send_request.
      send_request = cl_bcs=>create_persistent( ).
      CLEAR: lv_title.
      lv_title = im_subject.

*     创建并设置邮件文档
      CLEAR html.
      REFRESH html.
      html = t_message[].

      CLEAR document .
      document  =  cl_document_bcs=>create_document(
                                    i_type    =  'RAW'
                                    i_text    =  html
                                    i_length  =  conlengths
                                    i_subject =  lv_title ).

      CALL METHOD send_request->set_document( document ).
****************这里也可以从数据库表中读取码流
*      DATA: BEGIN OF xtab255 OCCURS 0,
*              x(255) TYPE x,
*            END OF xtab255.
*      FIELD-SYMBOLS: <cc> TYPE c.
*
*      DATA: ctab255 TYPE STANDARD TABLE OF solisti1 WITH HEADER LINE.
*
*      DATA: BEGIN OF pdf_table OCCURS 0,
*          mandt TYPE zjzjpdf-mandt,
*          row_order TYPE zjzjpdf-row_order,
*          chr_count TYPE zjzjpdf-chr_count,
*          content_hex(510),
*        END OF pdf_table.
*
*      CLEAR: pdf_table[].
*      SELECT  * INTO TABLE pdf_table FROM zjzjpdf.
*      SORT pdf_table BY row_order.
*
*      CLEAR:  xtab255[].
*      LOOP AT pdf_table.
*        "将字面上的HEX转换为真正的HEX
*        xtab255-x =  pdf_table-content_hex.
*        APPEND xtab255.
*      ENDLOOP.
****************************

*     添加附件:如果有多个,则需要调用该方法多次
      lv_attitle = im_filename.
      CALL METHOD document->add_attachment
        EXPORTING
 *          i_attachment_type    = 'BIN'"在邮件中点击附件会弹出文件保存对话框。其他类型请参考SAPFSSOA程序include文件RSSOCONS
*          i_attachment_type    = 'PDF'
*          i_attachment_type    = 'TXT'
          i_attachment_type    = 'XLS'"文件类型,在邮件中就可以打开文件,不会弹出保存对话框
          i_attachment_subject = lv_attitle
          i_att_content_hex    = it_binary_attach.
*          i_att_content_hex    = xtab255[].

*     设置发送者
      sender = cl_sapuser_bcs=>create( im_uname ).
      CALL METHOD send_request->set_sender
        EXPORTING
          i_sender = sender.

*     设置接收者
      CLEAR recipient.
      LOOP AT t_receivers.
        CLEAR lv_email.
        lv_email = t_receivers-receiver.
        recipient =
          cl_cam_address_bcs=>create_internet_address( lv_email ).
        CALL METHOD send_request->add_recipient
          EXPORTING
            i_recipient  = recipient
            i_express    = t_receivers-express
            i_copy       = t_receivers-copy
            i_blind_copy = t_receivers-blind_copy.
      ENDLOOP.

*     E-mail
      CALL METHOD send_request->set_status_attributes
        EXPORTING
          i_requested_status = 'E'
          i_status_mail      = 'E'.
      CALL METHOD send_request->set_send_immediately( 'X' ).

*     发送邮件
      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'.
        return-message = 'E-mail send successfully'.
        return-type = 'S'.
      ELSE.
        return-message = 'E-mail send unsuccessfully'.
        return-type = 'E'.
      ENDIF.

    CATCH cx_bcs INTO bcs_exception.
      bcs_message = bcs_exception->get_text( ).
      return-message = bcs_message.
      return-type = 'E'.
      EXIT.
  ENDTRY.
ENDFORM.