2014-08-11
ABAP
Email
So, you know how to send e-mails, even with attachments. But how do you send out nice PDFs instead of ugly text files? In this post, I’ll explain how to programmatically convert the output of a report to PDF so that it’s available for download or to send as an e-mail attachment.
Recommended Now
All-new Echo Dot Smart speaker with Alexa
This bundle includes Echo Dot (3rd Gen) Charcoal and Philips Hue White A19 Medium Lumen Smart Bulb, 1100 Lumens. Built in Smart Home hub. Ask Alexa to control Zigbee-compatible devices. No additional Philips Hue hub required. Two choices for easy smart lighting — Start setting the mood with Hue Smart bulbs and your Echo device, supporting up to 5 Hue Bluetooth & Zigbee smart bulbs. Add the Hue Hub for whole-home smart lighting (up to 50 light points) and bonus features.
Check it out on amazon.com →
Creating PDFs from a report with ABAP
After you have learned how to send an e-mail from SAP and how to attach a document to an e-mail, it’s time to discuss how to take this concept a little further. I’m describing a fairly common scenario here; often it is required to send out monthly reporting e-mails with PDF documents attached.
I will explain the process by discussing bits of a sample program. You can find the program in its entirety on the second page of this blog post. Creating a PDF from a report in ABAP consists of three steps:
- Submit the report to the spool to create a new spool request that contains the desired output
- Identify the correct spool request
- Convert the spool request to PDF
Submitting an ABAP report to the spool
Let’s start with the first step right away. The key to this is the ABAP instruction SUBMIT TO SAP-SPOOL. Before we can do that however, we need to featch the print parameters for the spool. This is done by calling the function module GET_PRINT_PARAMETERS with certain input values. The execution of the target report is done cirectly afterwards.
* Import the current print parameters CALL FUNCTION 'GET_PRINT_PARAMETERS' EXPORTING expiration = 1 immediately = space no_dialog = 'X' IMPORTING out_parameters = ls_pri_params EXCEPTIONS archive_info_not_found = 1 invalid_print_params = 2 invalid_archive_params = 3 OTHERS = 4. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * Submit the report program into the spool SUBMIT zoutput TO SAP-SPOOL SPOOL PARAMETERS ls_pri_params WITHOUT SPOOL DYNPRO AND RETURN.
Looking at this code sample, you can see that the print parameters are imported into a local structure. We then execute the target report (I called it zoutput in my example) by calling the SUBMIT instruction with certain additions:
- SPOOL PARAMETERS provides the print parameters to the report that are needed to create a spool request
- WITHOUT SPOOL DYNPRO tells the spool to not show the printer popup
- AND RETURN tells the program to return to the calling report after the execution has finished
Here, no parameters are passed to the executed report. This can however easily be achieved by using the WITH addition or by using import/export parameters.
Finding the correct spool request
Finding the spool request number after you’ve submitted the report is not hard. Unfortunately, it’s not returned as a parameter, but there’s a function module to find it. This function module is RSPO_FIND_SPOOL_REQUESTS . Let’s look at the code:
* Get a list of the current user's spool requests CALL FUNCTION 'RSPO_FIND_SPOOL_REQUESTS' EXPORTING rqowner = sy-uname TABLES spoolrequests = lt_spool_requests EXCEPTIONS no_permission = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * Sort and read the first (newest) spool request SORT lt_spool_requests BY rqcretime DESCENDING. READ TABLE lt_spool_requests INTO ls_spool_requests INDEX 1. lv_spool_id = ls_spool_requests-rqident.
All of the current user’s spool requests are imported in the internal table lt_spool_requests. All we need to do in addition is sort them by date in descending order and then reading the first line of the table to get the spool number.
Convert the spool request to PDF
Another easy job is to generate the actual PDF data from that spool request: the function module CONVERT_ABAPSPOOLJOB_2_PDF does that for us. The call is easy:
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF' EXPORTING src_spoolid = lv_spool_id IMPORTING pdf_bytecount = lv_pdf_bytecount TABLES pdf = lt_pdf EXCEPTIONS OTHERS = 12. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF.
We just provide the spool number and take two parameters back: the size of the PDF (which is needed if the PDF is to be sent as an e-mail attachment) and the binary PDF data itself, which is imported into an internal table.
That’s everything that is needed – you now know how to generate a PDF from an ABAP report! You could use this now to attach it to an e-mail or to make it available to the user by using a GUI download. The entire sample program is listed on the next page. Happy coding!
Sample program to create a PDF from an ABAP report
REPORT zreport2pdf. DATA ls_pri_params TYPE pri_params. DATA lt_spool_requests TYPE STANDARD TABLE OF rsporq. DATA ls_spool_requests TYPE rsporq. DATA lv_param TYPE char40. DATA lv_spool_id TYPE rspoid. DATA lt_pdf TYPE STANDARD TABLE OF tline. DATA lv_pdf_bytecount TYPE i. * Import the current print parameters CALL FUNCTION 'GET_PRINT_PARAMETERS' EXPORTING expiration = 1 immediately = space no_dialog = 'X' IMPORTING out_parameters = ls_pri_params EXCEPTIONS archive_info_not_found = 1 invalid_print_params = 2 invalid_archive_params = 3 OTHERS = 4. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * Submit the report program into the spool SUBMIT zoutput TO SAP-SPOOL SPOOL PARAMETERS ls_pri_params WITHOUT SPOOL DYNPRO AND RETURN. * Get a list of the current user's spool requests CALL FUNCTION 'RSPO_FIND_SPOOL_REQUESTS' EXPORTING rqowner = sy-uname TABLES spoolrequests = lt_spool_requests EXCEPTIONS no_permission = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * Sort and read the first (newest) spool request SORT lt_spool_requests BY rqcretime DESCENDING. READ TABLE lt_spool_requests INTO ls_spool_requests INDEX 1. lv_spool_id = ls_spool_requests-rqident. * Use that request to create a PDF CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF' EXPORTING src_spoolid = lv_spool_id IMPORTING pdf_bytecount = lv_pdf_bytecount TABLES pdf = lt_pdf EXCEPTIONS OTHERS = 12. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * Now the PDF binary data is in the variable lt_pdf * and the length in variable lv_pdf_bytecount. * Go ahead and attach that to an e-mail!
Всем привет!
Сегодня я расскажу о том, как довольно легко сделать выгрузку файла из Web Dynpro приложения.
Предположим, что вы создали программу, которая выгружает документ Word или Excel в SAP GUI. Для выгрузки вы использовали инструмент ZWWW. Через некоторое время к вам поступает требование от бизнеса реализовать возможность выгрузки этих документов через личный кабинет руководителя. Личный кабинет построен на некогда популярной технологии Web Dynpro (сократим до WD).
Общая часть.
Для выгрузки из WD приложения создадим в нашем отчете новую подпрограмму execute_from_web.
FORM execute_from_web USING iv_pernr TYPE pernr_d iv_date TYPE datum iv_format TYPE char1. DATA: lv_filenm_pdf TYPE fpname. p_pernr = iv_pernr. p_date = iv_date. p_format = iv_format. * Заполняем выходную структуру gs_outstruc и преобразовываем ее в таблицу gtd_values PERFORM get_data. CASE iv_format. WHEN 1. PERFORM print_file USING gc_invoice_word. " имя шаблона Word в smw0 WHEN 2. PERFORM print_file USING gc_payment_order_excel. " имя шаблона Excel в smw0 WHEN 3. PERFORM call_pdf USING gc_payment_order_pdf. " имя Pdf-формуляра в sfp . WHEN OTHERS. ENDCASE. ENDFORM.
Эту подпрограмму будем вызывать в методе-обработчике событий WD приложения (будет рассмотрен ниже).
Инструмент ZWWW умеет выгружать документ через web. Поэтому, в данном случае, нам нет необходимости тем или иным способом получать xstring чтобы выгрузить файл. Это есть хорошо.
FORM print_file USING uv_form_name TYPE wwwdatatab-objid. CALL FUNCTION 'ZWWW_OPENFORM' EXPORTING form_name = uv_form_name protect = '' TABLES it_values = gtd_values EXCEPTIONS printcancel = 1 OTHERS = 2. IF sy-subrc <> 0. MESSAGE ID 'ZHR_TEST' TYPE 'E' NUMBER 001. ENDIF. " sy-subrc <> 0. 'ZWWW_OPENFORM' ENDFORM. " print_file.
Таблица gtd_values в моем случае была заполнена в подпрограмме get_data.
PDF.
Для получение pdf-файла создадим форму call_pdf.
FORM call_pdf USING uv_filenm TYPE fpname. DATA: lv_fname TYPE funcname, ls_outputparams TYPE sfpoutputparams, ls_formoutput TYPE fpformoutput, lo_cx_fp_api TYPE REF TO cx_fp_api, lv_msg TYPE string. CHECK gs_outstruc IS NOT INITIAL. TRY. CALL FUNCTION 'FP_FUNCTION_MODULE_NAME' EXPORTING i_name = uv_filenm IMPORTING e_funcname = lv_fname. CATCH cx_fp_api_internal cx_fp_api_repository cx_fp_api_usage INTO lo_cx_fp_api. lv_msg = lo_cx_fp_api->get_text( ). MESSAGE lv_msg TYPE wctpm_msgtyp-error. ENDTRY. * Обратите внимание! ls_outputparams-nodialog = 'X'. ls_outputparams-getpdf = 'X'. CALL FUNCTION 'FP_JOB_OPEN' CHANGING ie_outputparams = ls_outputparams EXCEPTIONS usage_error = 1 system_error = 2 internal_error = 3 OTHERS = 4. CHECK sy-subrc = 0. CALL FUNCTION lv_fname EXPORTING is_data = gs_outstruc IMPORTING /1bcdwb/formoutput = ls_formoutput EXCEPTIONS usage_error = 1 system_error = 2 internal_error = 3 OTHERS = 4. CHECK sy-subrc = 0. CALL FUNCTION 'FP_JOB_CLOSE' EXCEPTIONS usage_error = 1 system_error = 2 internal_error = 3 OTHERS = 4. CHECK sy-subrc = 0. cl_wd_runtime_services=>attach_file_to_response( i_filename = |{ uv_filenm }_{ sy-timlo }.pdf'| i_content = ls_formoutput-pdf i_mime_type = 'application/pdf' ) ##NO_TEXT. ENDFORM. " call_pdf.
Самое интересное.
В методе do_operations на событии «PRINT» вызываем подпрограмму печати документа execute_from_web, созданную нами выше.
METHOD if_hrasr00gen_service~do_operations. DATA: lo_fpm TYPE REF TO cl_fpm, lv_event TYPE fpm_event_id, lv_pernr TYPE pernr_d, lv_date TYPE dats, lv_format TYPE char1. * Получаем параметры из полей в браузере lv_pernr = ctd_service_dataset[ fieldname = 'PERNR' ]-fieldvalue. lv_date = ctd_service_dataset[ fieldname = 'DATE' ]-fieldvalue. lv_format = ctd_service_dataset[ fieldname = 'FORMAT' ]-fieldvalue. "Формат файла(1-word,2-excel,3-pdf) * Получаем событие lo_fpm ?= cl_fpm=>get_instance( ). IF lo_fpm IS BOUND. lv_event = lo_fpm->mo_current_event->mv_event_id. CASE lv_event. WHEN 'PRINT'. PERFORM execute_from_web IN PROGRAM zhr_test USING lv_pernr lv_date lv_format. ENDCASE. ENDIF. ENDMETHOD.
Результат:
Ниже приведен скриншот выгрузки файла pdf.
Для Word и Excel файлов результат такой же.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Не все умеют виртуозно пользоваться Adobe LiveCycle Designer. Или, например, вам предоставили образец шаблона в Word/Excel. Есть способ как быстро создать PDF формуляр из Word или Excel.
Word
Открываем Adobe LiveCycle Designer как отдельное приложение(отдельный ярлык в папке). После чего выбираем файл WORD
LiveCycle Designer самостоятельно все переделал в PDF формат. Остается только сохранить в формате *.XDP
Заходим в транзакцию SFP, открываем или создаем формуляр, в который хотим импортировать шаблон.
Импортируем файл.
Примечание:
Вот тут может возникнуть особая ситуация CX_FP_UI_WORKBENCH. надо разбираться с ADS.
Готово. Осталось только забиндить контекст.
Excel
C Excel все не так красиво. Нативно LiveCycle Designer, как я понял, не умеет конвертировать в PDF. Поэтому путь будет чуть сложнее, а результат не такой красивый(Вместо таблиц, мы получим рисунок линиями). Но для прототипирования пойдет.
Сохраняем EXCEL как PDF
После этого все как с WORD. Открываем LiveCycle Designer как самостоятельное приложение и открываем сохраненный в прошлом шаге PDF
Теперь сохраняем как *.XDP
Заходим в транзакцию SFP, открываем или создаем формуляр, в который хотим импортировать шаблон.
Импортируем файл.
Результат:
Recently I had a development where the client wanted a PDF download of an ALV grid. Since no forms were involved with the development, getting the OTF data was a problem. I did the following workaround to get the OTF data: print the internal table, sending it to the spool, from where the OTF data could be obtained. Below are the function modules used to achieve this.
GET_PRINT_PARAMETERS —- To determine spool print parameters
CONVERT_ABAPSPOOLJOB_2_PDF —- To get OTF data from screen output
GUI_DOWNLOAD —- To download PDF file to PC
The orientation of the PDF was landscape, so that it could contain all the fields of the output. This can be achieved by playing around with the parameter ‘LINE_SIZE’ of the function module ‘GET_PRINT_PARAMETERS’.
(This would have been an easy workaround if the client had not asked me to work in detail on the PDF download later, in which case designing a form would be the more sensible option.)
"Data Declaration:
DATA: lv_val TYPE c,
lv_pripar TYPE pri_params,
lv_arcpar TYPE arc_params,
lv_spoolid LIKE tsp01-rqident,
lv_no_of_bytes TYPE i ##NEEDED,
lv_pdf_spoolid LIKE tsp01-rqident ##NEEDED,
lv_jobname LIKE tbtcjob-jobname ##NEEDED,
lv_jobcount LIKE tbtcjob-jobcount ##NEEDED,
lfl_final TYPE t_final,
lv_amount TYPE dmbtr,
lv_total TYPE string,
lit_pdf TYPE TABLE OF tline,
lv_file TYPE string.
FUNCTION 'GET_PRINT_PARAMETERS'
EXPORTING
in_archive_parameters = lv_arcpar
in_parameters = lv_pripar
layout = 'X_65_132'
line_count = 35
line_size = 260
no_dialog = 'X'
IMPORTING
out_archive_parameters = lv_arcpar
out_parameters = lv_pripar
valid = lv_val.
IF lv_val NE space.
lv_pripar-prrel = space.
lv_pripar-primm = space.
NEW-PAGE PRINT ON NEW-SECTION PARAMETERS
lv_pripar ARCHIVE PARAMETERS lv_arcpar NO DIALOG.
ENDIF.
"Write Internal Table
LOOP AT git_final INTO lfl_final.
WRITE:/ '|',lfl_final-index,'|', lfl_final-ubknt,'|', lfl_final-name1,'|',
lfl_final-bankn,'|', lfl_final-banka,'|', lfl_final-brnch,'|'.
CLEAR lfl_final.
WRITE: sy-uline.
ENDLOOP.
NEW-PAGE PRINT OFF.
CALL FUNCTION 'ABAP4_COMMIT_WORK'.
lv_spoolid = sy-spono.
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = lv_spoolid
no_dialog = ' '
IMPORTING
pdf_bytecount = lv_no_of_bytes
pdf_spoolid = lv_pdf_spoolid
btc_jobname = lv_jobname
btc_jobcount = lv_jobcount
TABLES
pdf = lit_pdf. "OTF Data
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
filename = lv_file "File Path
filetype = 'BIN'
TABLES
data_tab = lit_pdf
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
OTHERS = 22.
Просмотр нерешенных тем
Сообщения без ответов | Активные темы
Правила форума
ВНИМАНИЕ!
Вопросы по SAP Query и Quick View — сюда
Автор | Сообщение | ||
---|---|---|---|
Заголовок сообщения: Конвертер HTML в PDF на ABAP Добавлено: Сб, июн 01 2019, 12:59 |
|||
|
Время от времени возникает задача сформировать какую-нибудь печатную форму. В общем случае нет проблем сформировать любой документ в любом редакторе не приходя в сознание, но есть проблема, это все не устраивает заказчика, потому что конечные пользователи имеют возможность внести изменения в документ. Потому почти всегда это должен быть PDF. Видимо конечные пользователи не знают о существовании PrintScrin и MsPaint. Потому на выбор у нас следующие варианты 1) конвертировать смартформу все эти варианты имеют свои недостатки. Есть техническая возможность написать конвертер HTML в PDF на ABAP, проблема в том что для этого нужно написать примерно полтора мегабайта текста. Прежде чем в это ввязаться я хотел бы узнать кому вообще это все надо и как вы генерируете PDF. Время от времени можно проверять этот репозитарий https://github.com/AntonSikidin/zcl_aba … _converter
|
||
Вернуться к началу |
|
||
ArmAnn |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Вс, июн 02 2019, 20:30 |
|
Для того чтобы понять ‘кому это надо’ — хотелось бы понять ‘зачем?’.
|
Вернуться к началу |
|
Kengur |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Пн, июн 03 2019, 09:24 |
|
А просто распечатать в PDF не пробовали?
|
Вернуться к началу |
|
thebestsaper |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Пн, июн 03 2019, 09:37 |
||
|
Цитата: но есть проблема, это все не устраивает заказчика, потому что конечные пользователи имеют возможность внести изменения в документ. интересно, а как конечные пользователи могут внести изменения в смартформу? Это что за смартформа такая?
|
||
Вернуться к началу |
|
||
DKiyanov |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Ср, июн 05 2019, 13:19 |
|
смартформ не использовал на счёт html->pdf не думаю что это будет востребовано
|
Вернуться к началу |
|
Kuranov.Dmitry |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Ср, июн 05 2019, 15:10 |
|
в виду старой версии системы, пользуюсь смартформами.
|
Вернуться к началу |
|
AntonSikidin |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Сб, июн 08 2019, 13:35 |
||
|
DKiyanov написал: смартформ не использовал на счёт html->pdf не думаю что это будет востребовано чем конвертируете ворд в пдф? Html генерировать легче чем ворд
|
||
Вернуться к началу |
|
||
AntonSikidin |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Сб, июн 08 2019, 13:46 |
||
|
ArmAnn написал: Для того чтобы понять ‘кому это надо’ — хотелось бы понять ‘зачем?’. формы бывают разные, мне обычно попадаютсе те которые анкета, это примерно 38 пунктов, каждый второй из которых это таблица. Рисовать смартформы та еще боль, объявить все входящие параметры определить строки таблиц. Самая боль начинается когда тебе предлагают поиграть со шрифтами, нарисовать в смартформе чекбоксы, добавить пару столбцов в имеющуюся таблицу, и сделать так чтобы это все вмещалось. Каждый пункт это ручное изменение в интерфесе, содержимом, а еще вставить столбец в таблицу так чтоб итоговая строка не превышала ширину строки, проще набрать заново, в итоге изменить строку таблицы сравнимо по затратам с тем чтоб нарисовать ее заново. С хтмл проблем меньше, набираете любой документ в любом редакторе, хоть конвертируете из ворда в хтмл, осталось только конвертировать в пдф.
|
||
Вернуться к началу |
|
||
AntonSikidin |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Сб, июн 08 2019, 13:48 |
||
|
Kuranov.Dmitry написал(а): в виду старой версии системы, пользуюсь смартформами. его еще пока нет, это просто пример как легко и просто должно быть в итоге, в общем случае можно написать совместимым с версией 6.20
|
||
Вернуться к началу |
|
||
Besa |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Пн, июн 10 2019, 09:49 |
|
AntonSikidin, не берусь утверждать будет ли полезна Ваша разработка или нет, но в моем понимании, нужно четко разделять две вещи: На любом, более или менее нормальном проекте, ИМХО, просто так Z утилиту для массового использования, непонятно чьего происхождения и какой потенциальный вред оно будет нести, никто не пропустить…
|
Вернуться к началу |
|
pberezin |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Вт, июн 18 2019, 07:46 |
||
|
если смартформу отправить на печать адресату на внешний адрес электронки (должна быть соответствующая настройка в SCOT), то там автоматический конвертер срабатывает, и прилетает емайл уже с пдф-кой.
|
||
Вернуться к началу |
|
||
Parazit |
Заголовок сообщения: Re: Конвертер HTML в PDF на ABAP Добавлено: Вт, июл 16 2019, 01:20 |
|
AntonSikidin написал(а): … Если сделаете, то по любому этим будут пользоваться — кому-нибудь да пригодится. Несмотря на то, что PDF защищает от редактирования печатных форм ничуть не лучше, например, MS Office, иногда заказчик (а чаще PM или консультант) настолько упоротый, что проще сделать, чем переубедить. Я в таких случаях пользуюсь стандартной возможностью MS Office сохранять в формате PDF. Правда старые версии этого не умеют.
|
Вернуться к началу |
|
Кто сейчас на конференции |
Сейчас этот форум просматривают: Ahrefs [Bot], Yandex [Bot] |
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения |