abap 通用发送邮件程序(获取alv数据,带excel附件)
REPORT z_send_email_with_excel.
*&---------------------------------------------------------------------*
*& 选择屏幕定义
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_repid TYPE syrepid OBLIGATORY, " 报表程序名
p_varnt TYPE variant OBLIGATORY, " 变式名
p_email TYPE ad_smtpadr OBLIGATORY. " 收件邮箱
SELECTION-SCREEN END OF BLOCK blk1.
SELECTION-SCREEN BEGIN OF BLOCK blk2 WITH FRAME TITLE TEXT-002.
PARAMETERS: p_test AS CHECKBOX DEFAULT 'X'. " 测试模式
SELECTION-SCREEN END OF BLOCK blk2.
*&---------------------------------------------------------------------*
*& 数据类型定义
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_config,
report_name TYPE syrepid,
variant_name TYPE variant,
email_to TYPE ad_smtpadr,
END OF ty_config.
*&---------------------------------------------------------------------*
*& 主程序逻辑
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM main.
*&---------------------------------------------------------------------*
*& Form MAIN
*&---------------------------------------------------------------------*
FORM main.
DATA: ls_config TYPE ty_config.
" 填充配置结构
ls_config-report_name = p_repid.
ls_config-variant_name = p_varnt.
ls_config-email_to = p_email.
" 调用发送功能
PERFORM send_rpt_email USING ls_config-report_name
ls_config-variant_name
ls_config-email_to.
ENDFORM. " MAIN
*&---------------------------------------------------------------------*
*& Form SEND_RPT_EMAIL
*&---------------------------------------------------------------------*
FORM send_rpt_email USING iv_repid TYPE syrepid
iv_varnt TYPE variant
iv_email TYPE ad_smtpadr.
DATA: lt_email TYPE TABLE OF ad_smtpadr.
" 将邮箱地址转换为内表格式
APPEND iv_email TO lt_email.
" 显示开始信息
WRITE: / '开始处理报表:', iv_repid.
WRITE: / '使用变式: ', iv_varnt.
WRITE: / '收件人: ', iv_email.
WRITE: / '测试模式: ', p_test.
ULINE.
" 1. 获取报表数据
DATA: lr_data TYPE REF TO data.
PERFORM get_rpt_data USING iv_repid iv_varnt
CHANGING lr_data.
IF lr_data IS NOT BOUND.
WRITE: / '错误: 无法获取报表数据'.
RETURN.
ENDIF.
" 2. 转换为 Excel
DATA: lv_xstr TYPE xstring.
PERFORM create_xstring USING lr_data iv_repid
CHANGING lv_xstr.
IF lv_xstr IS INITIAL.
WRITE: / '错误: Excel 转换失败'.
RETURN.
ENDIF.
" 3. 发送邮件(测试模式下只模拟)
IF p_test = 'X'.
PERFORM simu_email USING lt_email lv_xstr iv_repid.
ELSE.
PERFORM send_email USING lt_email lv_xstr iv_repid.
ENDIF.
ENDFORM. " SEND_RPT_EMAIL
*&---------------------------------------------------------------------*
*& Form GET_RPT_DATA
*&---------------------------------------------------------------------*
FORM get_rpt_data USING iv_repid TYPE syrepid
iv_varnt TYPE variant
CHANGING cr_data TYPE REF TO data.
" 使用 CL_SALV_BS_RUNTIME_INFO 获取 ALV 数据
CL_SALV_BS_RUNTIME_INFO=>SET(
EXPORTING
display = abap_false
metadata = abap_false
data = abap_true
).
TRY.
" 提交报表到内存
SUBMIT (iv_repid) USING SELECTION-SET iv_varnt
AND RETURN.
" 获取数据引用
CL_SALV_BS_RUNTIME_INFO=>GET_DATA_REF( IMPORTING r_data = cr_data ).
WRITE: / '成功获取报表数据'.
CATCH cx_salv_bs_sc_runtime_info.
WRITE: / '错误: 报表不是 ALV 格式或执行失败'.
CLEAR cr_data.
ENDTRY.
CL_SALV_BS_RUNTIME_INFO=>CLEAR_ALL( ).
ENDFORM. " GET_RPT_DATA
*&---------------------------------------------------------------------*
*& Form CREATE_XSTRING
*&---------------------------------------------------------------------*
FORM create_xstring USING ir_data TYPE REF TO data
iv_repid TYPE syrepid
CHANGING cv_xstring TYPE xstring.
FIELD-SYMBOLS: <lt_table> TYPE STANDARD TABLE.
DATA: lt_fcat TYPE lvc_t_fcat.
" 分配数据到字段符号
ASSIGN ir_data->* TO <lt_table>.
" 检查表是否为空
IF lines( <lt_table> ) = 0.
WRITE: / '警告: 报表数据为空'.
RETURN.
ENDIF.
TRY.
" 创建 SALV 表
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_table)
CHANGING
t_table = <lt_table> ).
" 获取字段目录
lt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog(
r_columns = lo_table->get_columns( )
r_aggregations = lo_table->get_aggregations( ) ).
" 创建结果数据对象
DATA(lo_result) = cl_salv_ex_util=>factory_result_data_table(
r_data = ir_data
t_fieldcatalog = lt_fcat ).
" 转换为 XLSX
cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform(
EXPORTING
xml_type = if_salv_bs_xml=>c_type_xlsx
xml_version = cl_salv_bs_a_xml_base=>get_version( )
r_result_data = lo_result
xml_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export
gui_type = if_salv_bs_xml=>c_gui_type_gui
IMPORTING
xml = cv_xstring ).
WRITE: / '成功生成 Excel 文件, 大小:', xstrlen( cv_xstring ), 'bytes'.
CATCH cx_root INTO DATA(lx_error).
WRITE: / 'Excel 转换错误:', lx_error->get_text( ).
CLEAR cv_xstring.
ENDTRY.
ENDFORM. " CREATE_XSTRING
*&---------------------------------------------------------------------*
*& Form SIMU_EMAIL
*&---------------------------------------------------------------------*
FORM simu_email USING it_email TYPE table
iv_xstr TYPE xstring
iv_repid TYPE syrepid.
DATA: lv_email TYPE ad_smtpadr.
WRITE: / '=== 测试模式 - 邮件发送模拟 ==='.
WRITE: / '收件人列表:'.
LOOP AT it_email INTO lv_email.
WRITE: / ' -', lv_email.
ENDLOOP.
WRITE: / '邮件主题: 报表', iv_repid, '数据导出'.
WRITE: / '附件: 已生成 Excel 文件 (不实际发送)'.
WRITE: / '如需实际发送,请取消选择"测试模式"'.
ENDFORM. " SIMU_EMAIL
*&---------------------------------------------------------------------*
*& Form SEND_EMAIL
*&---------------------------------------------------------------------*
FORM send_email USING it_email TYPE table
iv_xstr TYPE xstring
iv_repid TYPE syrepid.
DATA: lv_email TYPE ad_smtpadr,
lv_attach_size TYPE so_obj_len.
TRY.
" 计算附件大小
lv_attach_size = xstrlen( iv_xstr ).
" 创建发送请求
DATA(lo_send_request) = cl_bcs=>create_persistent( ).
" 创建邮件正文
DATA(lt_body) = VALUE bcsy_text(
( line = 'Dear Sir/Madam,' )
( line = '' )
( line = '' )
( line = |这是报表 { iv_repid } 的数据导出文件,请查收。| )
( line = '' )
( line = |生成时间:{ sy-datum } { sy-uzeit }| )
( line = '' )
( line = 'Best regards,' )
( line = 'SAP System' )
).
" 设置文档对象
DATA: lv_subject TYPE so_obj_des.
CONCATENATE '报表' iv_repid '数据导出' INTO lv_subject SEPARATED BY space.
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = lt_body
i_subject = lv_subject ).
" 添加附件
DATA: lv_attach_sub TYPE sood-objdes.
CONCATENATE iv_repid '_' sy-datum '_' sy-uzeit INTO lv_attach_sub.
lv_attach_sub = lv_attach_sub && '.xlsx'.
lo_document->add_attachment(
i_attachment_type = 'BIN'
i_attachment_size = lv_attach_size
i_attachment_subject = lv_attach_sub
i_att_content_hex = cl_bcs_convert=>xstring_to_solix( iv_xstr ) ).
" 添加文档到发送请求
lo_send_request->set_document( lo_document ).
" 设置发件人(使用默认发件人)
DATA(lo_sender) = cl_sapuser_bcs=>create( sy-uname ).
lo_send_request->set_sender( lo_sender ).
" 设置收件人
LOOP AT it_email INTO lv_email.
DATA(lo_recipient) = cl_cam_address_bcs=>create_internet_address( lv_email ).
lo_send_request->add_recipient(
i_recipient = lo_recipient
i_express = abap_true ).
ENDLOOP.
" 发送邮件
DATA(lv_sent_to_all) = lo_send_request->send( ).
COMMIT WORK.
IF lv_sent_to_all = abap_true.
WRITE: / '成功: 邮件已发送!'.
" 立即发送出站邮件
WAIT UP TO 2 SECONDS.
SUBMIT rsconn01 WITH mode = 'INT' AND RETURN.
ELSE.
WRITE: / '警告: 邮件可能未发送给所有收件人'.
ENDIF.
CATCH cx_send_req_bcs INTO DATA(lx_req_bcs).
WRITE: / '发送请求错误:', lx_req_bcs->get_text( ).
CATCH cx_document_bcs INTO DATA(lx_doc_bcs).
WRITE: / '文档创建错误:', lx_doc_bcs->get_text( ).
CATCH cx_address_bcs INTO DATA(lx_add_bcs).
WRITE: / '地址错误:', lx_add_bcs->get_text( ).
CATCH cx_root INTO DATA(lx_error).
WRITE: / '邮件发送错误:', lx_error->get_text( ).
ENDTRY.
ENDFORM. " SEND_EMAIL
*&---------------------------------------------------------------------*
*& 初始化事件
*&---------------------------------------------------------------------*
INITIALIZATION.
