A quite easy way to send email in ABAP

本文介绍了一种使用ABAP编程语言发送HTML格式电子邮件的方法。通过示例代码展示了如何构造HTML内容、设置邮件属性及发送过程。该方法适用于企业级应用中需要发送复杂格式邮件的场景。

report zrich_0002.
 
data: maildata   like sodocchgi1.
data: mailtxt    like solisti1 occurs 10 with header line.
data: mailrec    like somlrec90 occurs 0  with header line.
 
start-of-selection.
  clear:    maildata, mailtxt,  mailrec.
  refresh:  mailtxt, mailrec.
 
  maildata-obj_name = 'TEST'.
  maildata-obj_descr = 'Test Subject'.
 
  mailtxt  = '<html>'.
  append mailtxt.
 
  mailtxt  = '<body>'.
  append mailtxt.
 
  mailtxt  = '<b>This is SAP</b>'.
  append mailtxt.
 
  mailtxt  = '<a href="#" target="_blank">SAP Hyperlink</a> '.
  append mailtxt.
 
  mailtxt  = '</body>'.
  append mailtxt.
 
  mailtxt  = '</html>'.
  append mailtxt.
 
  mailrec-receiver = 'you@yourcompany.com'.
  mailrec-rec_type  = 'U'.
  append mailrec.
 
  call function 'SO_NEW_DOCUMENT_SEND_API1'
       exporting
            document_data              = maildata
            document_type              = 'HTM'
            put_in_outbox              = 'X'
       tables
            object_header              = mailtxt
            object_content             = mailtxt
            receivers                  = mailrec
       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.

 

---------------------------------------------------------------------------------------------

REPORT  zsendmail.

DATA: lv_title          TYPE so_obj_des,
      send_request   TYPE REF TO CL_BCS,
      document         TYPE REF TO CL_DOCUMENT_BCS,
      conlengths        TYPE so_obj_len,
      html                  TYPE STANDARD TABLE OF w3html,
      wa_html           TYPE w3html,
      sender_id         TYPE REF TO IF_SENDER_BCS,
      recipient           TYPE REF TO IF_RECIPIENT_BCS,
      sent_to_all       TYPE os_boolean,
      bcs_exception  TYPE REF TO cx_bcs,
      bcs_message   TYPE string.

 

lv_title = 'This is the title'.

wa_html-line = '<html><body>'.
APPEND wa_html TO html.
...
wa_html-line = '</body></html>'.
APPEND wa_html TO html.


TRY.
    CLEAR send_request.
    send_request = cl_bcs=>create_persistent( ).
   
    CLEAR document .
    document =  cl_document_bcs=>create_document(
                    i_type =    'HTM'
                    i_text =     html
                    i_length =  conlengths
                    i_subject = lv_title ).

*   Add document to send request
    CALL METHOD send_request->set_document( document ).

 

*   Construct sender and receiver
    CLEAR: sender_id , recipient .
    sender_id = cl_cam_address_bcs=>create_internet_address( 'abc@zh.cn' ).
    recipient = cl_cam_address_bcs=>create_internet_address( 'bcd@zh.cn' ).

 

*   Set sender
    CALL METHOD send_request->set_sender
      EXPORTING
        i_sender = sender_id.

 

*   Add recipient with its respective attributes to send request
    CALL METHOD send_request->add_recipient
      EXPORTING
        i_recipient = recipient
        i_express   = 'X'.

 

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

 

*   Send document
    CALL METHOD send_request->send(
     EXPORTING
       i_with_error_screen = 'X'
     RECEIVING
       result = sent_to_all ).
      
    IF sent_to_all = 'X'.
      MESSAGE 'Mail sent successfully ' TYPE 'S'.
    ENDIF.
    COMMIT WORK.


  CATCH cx_bcs INTO bcs_exception.
    bcs_message = bcs_exception->get_text( ).
    MESSAGE bcs_exception TYPE 'E'.
    EXIT.
ENDTRY.

 

******************************************
 * get sender email address.

 CALL FUNCTION 'SUSR_USER_ADDRESS_READ'
    EXPORTING
        USER_NAME              = LV_BNAME
*       READ_DB_DIRECTLY       = ' '
    IMPORTING
        USER_ADDRESS           = FS_ADDR
        USER_USR03             = FS_USR03
    EXCEPTIONS
        USER_ADDRESS_NOT_FOUND = 1
        OTHERS                 = 2.

<think>嗯,用户想在ABAP中循环处理内表,过滤出不符合特定值的记录,具体需求是"LOOP WHERE field NOT IN selection"。这其实是个很典型的ABAP内表筛选需求,用户可能正在处理数据清洗或报表逻辑。 用户上次的问题涉及内表循环优化,这次继续深入条件筛选的语法细节。从"NOT IN"这个关键词看,用户应该已经掌握了基础的正向筛选(WHERE field IN),现在需要反向排除的逻辑。这类需求在财务凭证过滤、物料主数据排除特定类型时很常见。 考虑到ABAP语法特性,直接"NOT IN"确实行不通,需要转换思路。这里有三个实用方案: 1. 最直观的是用LOOP+DELETE ADJACENT DUPLICATES,适合小数据量 2. 用FILTER配合反选范围表性能更好,但需要多建一个辅助表 3. 新语法LOOP AT ... WHERE NOT ... 最简洁,但要求系统版本较新 用户没有说明系统版本,所以三种方案都需要覆盖。特别要注意范围表的结构问题——如果用户直接复制SIGN='I'的旧表会出错,需要强调SIGN='E'的反选逻辑。另外提醒用户注意DELETE后索引变化的问题,这个坑很多新手会踩。 性能方面,如果用户的内表很大,应该优先推荐FILTER方案。不过用户没提数据量,所以补充了通用性最强的LOOP+DELETE方案。最后用新语法满足现代ABAP开发需求,毕竟现在S/4 HANA已经很普及了。 引用[2]提到WHERE条件会遍历全表,这点正好佐证了方案二的FILTER效率更高。不过用户当前需求更关注语法正确性,性能提示作为补充即可。</think>在 ABAP 中,使用 `LOOP AT ... WHERE` 直接过滤字段**不在**某个值集合 (`NOT IN`) 内的记录,语法上**不支持直接使用 `NOT IN`**。但可以通过以下几种方法实现相同效果: --- ### 方法 1:使用 `LOOP` + 显式条件判断 通过 `LOOP` 遍历所有行,在循环体内用 `IF ... NOT IN ...` 显式判断并处理不符合条件的记录。 ```abap LOOP AT lt_itab INTO DATA(ls_row). IF ls_row-field NOT IN lt_selection. " 字段值不在选择表中 " 处理不符合条件的记录(例如:修改、删除、添加到新表等) APPEND ls_row TO lt_result. " 示例:添加到结果表 ENDIF. ENDLOOP. ``` --- ### 方法 2:创建反选范围表 构建一个**排除范围表**(`SIGN = 'E'`),配合 `FILTER` 或 `LOOP AT ... WHERE ... IN ...` 直接过滤: #### 步骤 1:构建排除范围表 ```abap DATA: lt_exclude TYPE RANGE OF field_type. " 字段类型需与内表字段一致 LOOP AT lt_selection INTO DATA(ls_sel). APPEND VALUE #( sign = 'E' option = 'EQ' low = ls_sel-field ) TO lt_exclude. ENDLOOP. ``` #### 步骤 2:使用 `FILTER` 过滤(推荐,高效) ```abap DATA(lt_filtered) = FILTER #( lt_itab WHERE field NOT IN lt_exclude ). " 直接过滤出符合条件记录 ``` #### 或使用 `LOOP AT ... WHERE` ```abap LOOP AT lt_itab INTO DATA(ls_row) WHERE field IN lt_exclude. " 此处处理的是**被排除**的记录(需跳过) CONTINUE. ENDLOOP. ``` --- ### 方法 3:使用 `LOOP AT ... WHERE NOT ...`(新语法) 若系统版本支持(ABAP 7.55+),可直接用 `WHERE NOT` 逻辑表达式: ```abap LOOP AT lt_itab INTO DATA(ls_row) WHERE NOT ( field IN lt_selection ). " 处理不符合条件的记录 APPEND ls_row TO lt_result. ENDLOOP. ``` --- ### 关键点总结 | **方法** | **适用场景** | **优势** | |------------------------|---------------------------------------|------------------------------| | `LOOP` + 显式 `IF` | 简单逻辑或旧系统 | 兼容性好 | | 构建排除表 + `FILTER` | 大数据量需高效过滤时[^1] | 性能最优,代码简洁 | | `WHERE NOT (...)` | 新系统(ABAP 7.55+) | 语法直观,无需额外步骤 | > ⚠️ **注意**: > - 范围表结构需包含 `SIGN`(值为 `I`/`E`)、`OPTION`(如 `EQ`)、`LOW`/`HIGH`。 > - 直接删除内表记录时,建议用 `DELETE lt_itab INDEX sy-tabix` 而非 `DELETE ADJACENT DUPLICATES`,后者需排序且可能误删[^1]。 --- ### 相关问题 1. 如何优化 ABAP 内表大数据量下的过滤性能? 2. `FILTER` 和传统 `LOOP + IF` 在性能上有何差异? 3. ABAP 中如何动态构建范围表(RANGE Table)? [^1]: 内表操作需谨慎选择算法,不当的循环或删除逻辑可能导致性能下降,尤其对 `SORTED` 或 `HASHED` 表类型影响显著。 [^2]: 显式条件判断虽灵活,但遍历全表时效率可能低于基于索引的 `FILTER` 操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值