ABAP 发送带EXCEL邮件

前言

没啥特殊需求,就是有个库龄报表用户想整邮件发送

实现

用的最简单的XLS文件作为excel附件发送出去

观察XLS文件的纯文本格式,每列之间用TAB制表符分隔,每行之间用回车符分隔

思路也比较明确,在SAP中实现这种格式,再转二进制流就好了

下面的代码替换掉lt_data就可以直接使用,用的动态内表自动将内表转成纯文本

abap 复制代码
*&---------------------------------------------------------------------*
*& Form frm_2023122702
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_2023122702 .

  TYPES: BEGIN OF ty_mrtab,
           matnr TYPE mara-matnr,
           maktx TYPE makt-maktx,
           mtart TYPE mara-mtart,
         END OF ty_mrtab.
  FIELD-SYMBOLS: <gt_table> TYPE table.         "DYNAMIC TABLE INDICATE
  " 容器字段
  FIELD-SYMBOLS: <fs_data>      TYPE any,
                 <fs_cell_data> TYPE any.
  DATA: lr_data            TYPE REF TO data,
        lo_descr           TYPE REF TO cl_abap_typedescr,
        lo_str_descr_in    TYPE REF TO cl_abap_structdescr,
        ls_abap_comp_descr TYPE abap_compdescr.

  "附件参数
  DATA: lt_otf    TYPE TABLE OF itcoo,
        lt_tline  TYPE TABLE OF tline,
        lt_record TYPE TABLE OF solisti1,
        ls_otf    TYPE itcoo,
        ls_tline  TYPE tline,
        ls_record TYPE solisti1.
  "邮件参数
  DATA: lv_size      TYPE i, "邮件附件大小
        lv_lines_txt TYPE i, "邮件文本行数
        lv_lines_bin TYPE i, "邮件附件行数
        lv_benfile   TYPE xstring,
        lv_object    TYPE char50, "邮件主题
        lv_filename  TYPE char50,
        lt_objpack   TYPE TABLE OF sopcklsti1 , "邮件内容 正文+附件
        lt_objtxt    TYPE TABLE OF solisti1   , "正文内容
        lt_objbin    TYPE TABLE OF solisti1   , "附件内容
        lt_reclist   TYPE TABLE OF somlreci1  , "收件人
        ls_doc_chng  TYPE sodocchgi1, "邮件属性
        ls_objpack   TYPE sopcklsti1,
        ls_objtxt    TYPE solisti1,
        ls_objbin    TYPE solisti1,
        ls_reclist   TYPE somlreci1.

  DATA: lv_str  TYPE string,
        lv_cell TYPE string.

* 需要转excel的内表
  DATA: lt_data TYPE TABLE OF ty_mrtab.
  lt_data = VALUE #( ( matnr = '100' maktx = '硅粉621,纯度≥99.1%,P<80ppm;B<50ppm' mtart = '1000' )
                     ( matnr = '200' maktx = '硅粉621,纯度≥99.1%,P<80ppm;B<50ppm' mtart = '1000' ) ).

  " 转动态内表以符合各种场景
  ASSIGN lt_data TO <gt_table>.

*&--获取lt_data的表结构
  CREATE DATA lr_data LIKE LINE OF <gt_table>.
  ASSIGN lr_data->* TO <fs_data>.

  " EXCEL表头
*  LOOP AT gt_fieldcat_alv INTO DATA(ls_fieldcat_alv).
*    " 单元格 + TAB符
*    lv_str = lv_str && ls_fieldcat_alv-seltext_l && cl_abap_char_utilities=>horizontal_tab.
*  ENDLOOP.
*  " 最后使用回车符换行
*  lv_str = lv_str && cl_abap_char_utilities=>cr_lf.

*&--获取内表列字段
  CALL METHOD cl_abap_structdescr=>describe_by_data
    EXPORTING
      p_data      = <fs_data>
    RECEIVING
      p_descr_ref = lo_descr.

  lo_str_descr_in ?= lo_descr.

*&--EXCEL表体
  LOOP AT <gt_table> ASSIGNING <fs_data>.
*    CLEAR: lv_str,lv_start,lv_end.

    " 循环每行的每个单元格
    LOOP AT lo_str_descr_in->components INTO ls_abap_comp_descr.

      " 根据字段名找到字段
      ASSIGN COMPONENT ls_abap_comp_descr-name OF STRUCTURE <fs_data> TO <fs_cell_data>.

      " 去除首尾引号,否则xls文件中tab符会有问题
      lv_cell = <fs_cell_data>.
      REPLACE ALL OCCURRENCES OF REGEX '^"*|"*$' IN lv_cell WITH ''.

      " 单元格 + TAB符
      lv_str = lv_str && lv_cell && cl_abap_char_utilities=>horizontal_tab.

    ENDLOOP.

    " 最后使用回车符换行
    lv_str = lv_str && cl_abap_char_utilities=>cr_lf.

  ENDLOOP.

  "string类型-> XSTRING
  CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
    EXPORTING
      text     = lv_str
*     mimetype = 'XLS'
      encoding = '8404' "防止中文乱码
    IMPORTING
      buffer   = lv_benfile
    EXCEPTIONS
      failed   = 1
      OTHERS   = 2.

  IF lv_benfile IS NOT INITIAL.
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = lv_benfile
      IMPORTING
        output_length = lv_size
      TABLES
        binary_tab    = lt_record.
  ENDIF.

  "将转换后的文件添加到邮件附件
  APPEND LINES OF lt_record TO lt_objbin.

*  &---邮件处理

  " 获取收件人
  SELECT DISTINCT
    smtp_addr
  FROM zmmt045
  INTO TABLE @DATA(lt_receiver).
  lv_size = lines( lt_objbin ) * 255.

  "添加邮件正文
  ls_objtxt = 'ZMMR011报表已导出,请查看附件'. "
  APPEND ls_objtxt TO lt_objtxt.

  "邮件正文行数
  lv_lines_txt = lines( lt_objtxt ).
  lv_object = 'ZMMR011导出'. " 标题:ZMMR011报表
  lv_filename = 'ZMMR011.XLS'.  " 附件XLS命名
  ls_doc_chng-obj_langu = sy-langu.
  ls_doc_chng-obj_name = 'Email'.  " Email
*        ls_doc_chng-expiry_dat = sy-datum + 10.  " 邮件过期日,在此日期后邮件将无法被查看
  ls_doc_chng-obj_descr = lv_object.  "邮件标题
*        ls_doc_chng-sensitivty = 'F'.  " 邮件保密等级
  ls_doc_chng-doc_size = lv_lines_txt * 255 + lv_size.
  ls_doc_chng-priority = '3'. " 1:低优先级 3:普通优先级 5:高优先级

  CLEAR ls_objpack-transf_bin.
  ls_objpack-head_start = 1.
  ls_objpack-head_num = 0.
  ls_objpack-body_start = 1.
  ls_objpack-body_num = lv_lines_txt.
  ls_objpack-doc_type = 'RAW'.
  APPEND ls_objpack TO lt_objpack.

  CLEAR:lv_lines_bin.
  ls_objpack-transf_bin = 'X'.
  ls_objpack-head_start = 1.
  ls_objpack-head_num = 1.
  ls_objpack-body_start = 1.

  lv_lines_bin = lines( lt_objbin ).

  ls_objpack-doc_size = lv_size .
  ls_objpack-body_num = lv_lines_bin.
  ls_objpack-doc_type = 'XLS'.
  ls_objpack-obj_descr = lv_filename.
  APPEND ls_objpack TO lt_objpack.

  lt_reclist = VALUE #( FOR lw_receiver IN lt_receiver
                        ( receiver = lw_receiver  " 收件人邮箱
                          rec_type = 'U' ) ).

  CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
    EXPORTING
      document_data              = ls_doc_chng  " 邮件属性
      put_in_outbox              = ''
      commit_work                = 'X'
    TABLES
      packing_list               = lt_objpack  " 邮件内容
      contents_bin               = lt_objbin   " 附件内容(二进制)
      contents_txt               = lt_objtxt   " 邮件内容(直接填入)
      receivers                  = lt_reclist  " 收件箱地址
    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.
*    es_return-type = 'S'.
*    es_return-message = es_return-message && TEXT-m19. " 邮件发送成功
    WAIT UP TO 1 SECONDS.
    " 立即发送邮件
    SUBMIT rsconn01                                      "#EC CI_SUBMIT
    WITH mode = 'INT' WITH output = '' AND RETURN. ".
  ELSE.
*    es_return-type = 'S'.
*    es_return-message = es_return-message && TEXT-m20. " 邮件发送失败
  ENDIF.

ENDFORM.
相关推荐
SAP-nkGavin8 天前
简单说一说Modern ABAP这个概念
sap·abap
爱喝水的鱼丶11 天前
SAP-ABAP:在DEBUG过程中修改内表中的数据的方法详解
运维·开发语言·sap·异常处理·abap·修改内表
爱喝水的鱼丶18 天前
SAP-ABAP:ABAP异常处理与SAP现代技术融合—— 面向云原生、微服务与低代码场景的创新实践
开发语言·低代码·微服务·云原生·sap·abap
爱喝水的鱼丶18 天前
SAP-ABAP:SAP的BAPI_PO_CHANGE功能详解
开发语言·sap·abap·bapi·采购订单修改
IT小白农民工24 天前
SAP Business One(B1)打开自定义对象报错【Failed to initialize document numbering:】
经验分享·sap
清风雅雨1 个月前
SAP 交货单行项目含税金额计算报cx_sy_zerodivide处理
sap
IT小白农民工1 个月前
如何用postman进行批量操作
测试工具·postman·sap
清风雅雨1 个月前
VPN访问SAP组服务器报登陆负载均衡错误88:无法连接到消息服务器(RC=9)
运维·sap
syounger2 个月前
Oracle在ERP市场击败SAP
oracle·sap
-样样-2 个月前
SAP系统交货已完成标识
sap