Иногда возникает необходимость формировать файлы с результатами работы программы и отправлять их пользователям. Для этих целей можно воспользоваться стандартными средствами и отправлять на почту запрос в спул (https://blogs.sap.com/2012/12/11/send-spool-list-of-background-job-to-sap-inbox/), но данный способ прикрепляет результат в виде HTML/TXT или PDF, что не всегда удобно.
В связи с этим формулируется следующая задача — формировать файл Excel и отправлять его на почту.
В SAP имеется несколько способов работы с файлами Excel (https://wiki.scn.sap.com/wiki/display/ABAP/Excel+with+SAP+-+An+overview), но, к сожалению, большинство из них не работают в фоновом режиме.
Для разовой работы и минимизации зависимостей решил воспользоваться стандартными средствами, которые уже имеются в системе.
Прежде всего создаем внутреннюю таблицу с данными отчета.
1 2 3 4 5 6 |
DATA: gt_data TYPE TABLE OF ekpo. SELECT * UP TO 10 ROWS FROM ekpo INTO CORRESPONDING FIELDS OF TABLE gt_data. |
Теперь можно преобразовать её в файл Excel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
DATA: lt_fcat TYPE lvc_t_fcat, lr_data TYPE REF TO data, ls_layout TYPE lvc_s_layo, lv_version TYPE string, lo_result_data TYPE REF TO cl_salv_ex_result_data_table, lv_xstring type xstring. GET REFERENCE OF gt_data INTO lr_data. CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' EXPORTING i_structure_name = 'EKPO' CHANGING ct_fieldcat = lt_fcat. IF cl_salv_bs_a_xml_base=>get_version( ) EQ if_salv_bs_xml=>version_25 OR cl_salv_bs_a_xml_base=>get_version( ) EQ if_salv_bs_xml=>version_26. lo_result_data = cl_salv_ex_util=>factory_result_data_table( r_data = lr_data s_layout = ls_layout t_fieldcatalog = lt_fcat ). CASE cl_salv_bs_a_xml_base=>get_version( ). WHEN if_salv_bs_xml=>version_25. lv_version = if_salv_bs_xml=>version_25. WHEN if_salv_bs_xml=>version_26. lv_version = if_salv_bs_xml=>version_26. ENDCASE. CALL METHOD cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform EXPORTING xml_type = if_salv_bs_xml=>c_type_xlsx xml_version = lv_version r_result_data = lo_result_data xml_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export gui_type = if_salv_bs_xml=>c_gui_type_gui IMPORTING xml = lv_xstring. ENDIF. |
Для теста сохраним сформированный файл и откроем его в Excel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
DATA: lv_size TYPE i. DATA: lt_bintab TYPE solix_tab. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_xstring APPEND_TO_TABLE = ' ' IMPORTING output_length = lv_size TABLES binary_tab = lt_bintab. cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_size filename = 'c:\temp\1.xlsx' filetype = 'BIN' CHANGING data_tab = lt_bintab EXCEPTIONS file_write_error = 1 no_batch = 2 gui_refuse_filetransfer = 3 invalid_type = 4 no_authority = 5 unknown_error = 6 header_not_allowed = 7 separator_not_allowed = 8 filesize_not_allowed = 9 header_too_long = 10 dp_error_create = 11 dp_error_send = 12 dp_error_write = 13 unknown_dp_error = 14 access_denied = 15 dp_out_of_memory = 16 disk_full = 17 dp_timeout = 18 file_not_found = 19 dataprovider_exception = 20 control_flush_error = 21 not_supported_by_gui = 22 error_no_gui = 23 OTHERS = 24 ). |
Теперь можно и отправить сформированный файл
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
DATA: lv_size TYPE i, lt_bintab TYPE solix_tab, lv_subject TYPE so_obj_des, lt_main_text TYPE bcsy_text, lv_attachment_name TYPE sood-objdes, lv_attachment_size TYPE so_obj_len, ls_dlidata TYPE sodlidati1, lt_dli TYPE STANDARD TABLE OF sodlienti1, ls_dli LIKE LINE OF lt_dli, l_dlidata TYPE sodlidati1, lv_recipient TYPE adr6-smtp_addr, lv_send_to_all TYPE os_boolean, lo_send_request TYPE REF TO cl_bcs, lo_document TYPE REF TO cl_document_bcs, lo_recipient TYPE REF TO if_recipient_bcs, lx_bcs_exception TYPE REF TO cx_bcs. REFRESH lt_bintab. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = iv_xstring append_to_table = ' ' IMPORTING output_length = lv_size TABLES binary_tab = lt_bintab. lv_subject = 'Тема'. lv_attachment_name = 'file.xlsx'. APPEND 'Текст' TO lt_main_text. lv_attachment_size = xstrlen( iv_xstring ). TRY. lo_send_request = cl_bcs=>create_persistent( ). lo_document = cl_document_bcs=>create_document( i_type = 'RAW' i_text = lt_main_text i_subject = lv_subject ). lo_document->add_attachment( i_attachment_type = 'XLS' "#EC NOTEXT i_attachment_subject = lv_attachment_name "#EC NOTEXT i_attachment_size = lv_attachment_size "Size i_att_content_hex = lt_bintab ). " Получить адреса из списка рассылки (tr SO23) CLEAR ls_dlidata. CALL FUNCTION 'SO_DLI_READ_API1' EXPORTING shared_dli = 'X' dli_id = space dli_name = 'ZZZ' IMPORTING dli_data = ls_dlidata TABLES dli_entries = lt_dli EXCEPTIONS dli_not_exist = 1 operation_no_authorization = 2 parameter_error = 3 x_error = 4 OTHERS = 5. " добавить в получателей LOOP AT lt_dli INTO ls_dli. lv_recipient = ls_dli-member_adr. lo_recipient = cl_cam_address_bcs=>create_internet_address( lv_recipient ). TRY. CALL METHOD lo_send_request->add_recipient EXPORTING i_recipient = lo_recipient i_express = 'X'. ENDTRY . ENDLOOP. lo_send_request->set_document( lo_document ). lo_send_request->send_request->set_link_to_outbox( 'X' ). lv_send_to_all = lo_send_request->send( i_with_error_screen = 'X' ). IF lv_send_to_all = abap_true. COMMIT WORK. SUBMIT rsconn01 WITH mode = 'INT' WITH output = 'X' AND RETURN. ENDIF. CATCH cx_bcs INTO lx_bcs_exception. MESSAGE i865(so) WITH lx_bcs_exception->error_type. ENDTRY. |
К сожалению так и не нашел возможности выделять отдельные строки или поля таблицы цветом. Везде пишут, что для этого надо пользоваться библиотекой abap2xls. Однако если в ALV таблица включить суммирование по столбцу и выгрузить её в виде таблицы Excel, то строка с суммой выделена желтым цветом. При этом также используется метод cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform, так что такая возможность есть.