‎2020 Jul 19 10:37 AM
Hello experts
I use CONVERT_ABAPSPOOLJOB_2_PDF in order to convert ABAP spool to PDF. After that I Transfer the 132-long strings to 255-long strings with the translate command.
When writing:
TRANSLATE ls_pdf_output USING ' ~'.
Then when opening the pdf Sometimes it is OK but sometimes I receive an error message 'CANNOT EXTRACT THE EMBEDDED FONT…'
When writing:
DATA: lv_translate_str TYPE string VALUE ' ~'
TRANSLATE ls_pdf_output USING lv_translate_str.
Then when opening the pdf, until now It was always ok.
Thanks in advance
Hagit
FORM convert_spool_to_pdf
USING pv_job_id TYPE tsp01-rqident
CHANGING pt_mess_att TYPE esy_tt_solisti1
.
CONSTANTS: lc_no(1) TYPE c VALUE ' '
,lc_device(4) TYPE c VALUE 'LOCL'
.
DATA: lt_pdf_output TYPE TABLE OF tline
,lv_buffer TYPE string
,ls_mess_att TYPE solisti1 "like line of pt_mess_att
.
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = pv_job_id
no_dialog = lc_no
dst_device = lc_device
* IMPORTING
* pdf_bytecount =
TABLES
pdf = lt_pdf_output
EXCEPTIONS
err_no_abap_spooljob = 1
err_no_spooljob = 2
err_no_permission = 3
err_conv_not_possible = 4
err_bad_destdevice = 5
user_cancelled = 6
err_spoolerror = 7
err_temseerror = 8
err_btcjob_open_failed = 9
err_btcjob_submit_failed = 10
err_btcjob_close_failed = 11
OTHERS = 12.
IF sy-subrc <> 0.
RAISE no_conv2pdf.
ELSE.
DATA: lv_translate_str TYPE string VALUE ' ~'
,lv_translate_back_str TYPE string VALUE '~ '
.
* Transfer the 132-long strings to 255-long strings
LOOP AT lt_pdf_output INTO DATA(ls_pdf_output).
* TRANSLATE ls_pdf_output USING ' ~'.
TRANSLATE ls_pdf_output USING lv_translate_str.
CONCATENATE lv_buffer ls_pdf_output INTO lv_buffer.
ENDLOOP.
* TRANSLATE lv_buffer USING '~ '.
TRANSLATE lv_buffer USING lv_translate_back_str.
DO.
ls_mess_att = lv_buffer.
APPEND ls_mess_att TO pt_mess_att.
SHIFT lv_buffer LEFT BY 255 PLACES.
IF lv_buffer IS INITIAL.
EXIT.
ENDIF.
ENDDO.
ENDIF.
ENDFORM. "convert_spool_to_pdf
‎2020 Jul 19 12:50 PM
DATA lv_translate_back_str TYPE string VALUE '~ '.
TRANSLATE lv_buffer USING lv_translate_back_str.
is different from
TRANSLATE lv_buffer USING '~ '.because, as explained in the ABAP documentation of TRANSLATE:
Solution: to make the two forms equivalent, define the two characters as a STRING of 2 characters, by using back quotes, the trailing space will be kept during the assignment:
DATA lv_translate_back_str TYPE string VALUE `~ `.PS: what I said is not related to PDF, it's intrinsic to ABAP. Concerning CONCATENATE, you may use the addition RESPECTING BLANKS instead of this TRANSLATE trick to keep blanks which is very dangerous because the PDF may contain tildes before use of TRANSLATE, and guess what happens...
‎2020 Jul 19 12:50 PM
DATA lv_translate_back_str TYPE string VALUE '~ '.
TRANSLATE lv_buffer USING lv_translate_back_str.
is different from
TRANSLATE lv_buffer USING '~ '.because, as explained in the ABAP documentation of TRANSLATE:
Solution: to make the two forms equivalent, define the two characters as a STRING of 2 characters, by using back quotes, the trailing space will be kept during the assignment:
DATA lv_translate_back_str TYPE string VALUE `~ `.PS: what I said is not related to PDF, it's intrinsic to ABAP. Concerning CONCATENATE, you may use the addition RESPECTING BLANKS instead of this TRANSLATE trick to keep blanks which is very dangerous because the PDF may contain tildes before use of TRANSLATE, and guess what happens...
‎2020 Jul 19 3:12 PM
sandra.rossi ,
Thanks for your perfect explanation.
In all the examples which I found in the web, translate was used.
Is the previous code equivalent to the code below?
IF sy-subrc <> 0.RAISE no_conv2pdf.ELSE.* DATA: lv_translate_str TYPE string VALUE ' ~'* ,lv_translate_back_str TYPE string VALUE `~ `** ,lv_translate_back_str TYPE string VALUE '~ ' .
* Transfer the 132-long strings to 255-long stringsLOOP AT lt_pdf_output INTO DATA(ls_pdf_output).** TRANSLATE ls_pdf_output USING ' ~'.* TRANSLATE ls_pdf_output USING lv_translate_str.* CONCATENATE lv_buffer ls_pdf_output INTO lv_buffer.CONCATENATE lv_buffer ls_pdf_output INTO lv_buffer RESPECTING BLANKS.ENDLOOP.
** TRANSLATE lv_buffer USING '~ '.* TRANSLATE lv_buffer USING lv_translate_back_str.
DO.
ls_mess_att = lv_buffer.APPEND ls_mess_att TO pt_mess_att.SHIFT lv_buffer LEFT BY 255 PLACES.IF lv_buffer IS INITIAL.EXIT.ENDIF.ENDDO.ENDIF.Thanks
Hagit
‎2020 Jul 19 3:37 PM
Please use button COMMENT. The button ANSWER is for proposing a solution.
Yes, you're correct.
Your code:
LOOP AT lt_pdf_output INTO DATA(ls_pdf_output).
TRANSLATE ls_pdf_output USING ' ~'.
CONCATENATE lv_buffer ls_pdf_output INTO lv_buffer.
ENDLOOP.
TRANSLATE lv_buffer USING '~ '.
is equivalent to:
LOOP AT lt_pdf_output INTO DATA(ls_pdf_output).
CONCATENATE lv_buffer ls_pdf_output INTO lv_buffer RESPECTING BLANKS.
ENDLOOP.
and is equivalent to:
CONCATENATE LINES OF lt_pdf_output INTO lv_buffer RESPECTING BLANKS.
By the way, if I'm not wrong, your final code can be changed to:
pt_mess_att = cl_bcs_convert=>string_to_soli( lv_buffer ).
PS: LINES OF and RESPECTING BLANKS appeared in ABAP 7.0, in 2005.
‎2020 Jul 19 4:55 PM
And most importantly, you must absolutely use the parameter pdf_bytecount to trim the extra bytes.
The problem of your code is that you only deal with characters, you must cast the characters into bytes, then you can trim the extra bytes.
In the end, your code attaches the PDF to "somewhere", and that must be done with bytes, NOT with characters. If you do it with characters, you will probably have problems.
‎2020 Jul 19 5:15 PM
‎2020 Jul 19 7:26 PM
2. As a rule-of-thumb, any one-statement is faster than the equivalent ABAP code in several lines
3. Use PDF_BYTECOUNT as I explained. But I can't give additional clues as you don't explain what you do with the PDF (formal parameter pt_mess_att) in the end.
‎2020 Jul 20 7:35 AM
3. At the end I send the pdf as an attachment in the mail.
FORM send_file_as_email_attachment TABLES it_message
it_attachUSING p_email
pv_mail_subject
p_format
p_filename
p_attdescription
p_sender_address
p_sender_addres_typeCHANGING p_reciever.
DATA: ld_mtitle LIKE sodocchgi1-obj_descr,
ld_email LIKE somlreci1-receiver,
ld_format TYPE so_obj_tp,
ld_attdescription TYPE so_obj_nam,
ld_attfilename TYPE so_obj_des,
ld_sender_address LIKE soextreci1-receiver,
ld_sender_address_type LIKE soextreci1-adr_typ,
ld_receiver LIKE sy-subrc.
DATA: t_packing_list LIKE sopcklsti1 OCCURS 0 WITH HEADER LINE,
t_contents LIKE solisti1 OCCURS 0 WITH HEADER LINE,
t_receivers LIKE somlreci1 OCCURS 0 WITH HEADER LINE,
t_attachment LIKE solisti1 OCCURS 0 WITH HEADER LINE,
t_object_header LIKE solisti1 OCCURS 0 WITH HEADER LINE,
w_cnt TYPE i,
w_sent_all(1) TYPE c,
w_doc_data LIKE sodocchgi1.
ld_email = p_email.
ld_mtitle = pv_mail_subject.
ld_format = p_format.
ld_attdescription = p_attdescription.
ld_attfilename = p_filename.
ld_sender_address = p_sender_address.
ld_sender_address_type = p_sender_addres_type.
* Fill the document data.
w_doc_data-doc_size = 1.
* Populate the subject/generic message attributes
w_doc_data-obj_langu = sy-langu.
w_doc_data-obj_name = 'SAPRPT'.
w_doc_data-obj_descr = ld_mtitle .
w_doc_data-sensitivty = 'F'.
* Fill the document data and get size of attachmentCLEAR w_doc_data.READ TABLE it_attach INDEX w_cnt.
w_doc_data-doc_size =( w_cnt - 1 ) * 255 + strlen( it_attach ).
w_doc_data-obj_langu = sy-langu.
w_doc_data-obj_name = 'SAPRPT'.
w_doc_data-obj_descr = ld_mtitle.
w_doc_data-sensitivty = 'F'.CLEAR t_attachment.REFRESH t_attachment.
t_attachment[] = it_attach[].
* Describe the body of the messageCLEAR t_packing_list.REFRESH t_packing_list.
t_packing_list-transf_bin = space.
t_packing_list-head_start = 1.
t_packing_list-head_num = 0.
t_packing_list-body_start = 1.DESCRIBE TABLE it_message LINES t_packing_list-body_num.
t_packing_list-doc_type = 'RAW'.APPEND t_packing_list.
* Create attachment notification
t_packing_list-transf_bin = 'X'.
t_packing_list-head_start = 1.
t_packing_list-head_num = 1.
t_packing_list-body_start = 1.
DESCRIBE TABLE t_attachment LINES t_packing_list-body_num.
t_packing_list-doc_type = ld_format.
t_packing_list-obj_descr = ld_attdescription.
t_packing_list-obj_name = ld_attfilename.
t_packing_list-doc_size = t_packing_list-body_num * 255.APPEND t_packing_list.
* Add the recipients email addressCLEAR t_receivers.REFRESH t_receivers.
t_receivers-receiver = ld_email.
t_receivers-rec_type = 'U'.
t_receivers-com_type = 'INT'.
t_receivers-notif_del = 'X'.
t_receivers-notif_ndel = 'X'.APPEND t_receivers.
CALL FUNCTION 'SO_DOCUMENT_SEND_API1'EXPORTING
document_data = w_doc_data
put_in_outbox = 'X'
sender_address = ld_sender_address
sender_address_type = ld_sender_address_type
commit_work = 'X'IMPORTING
sent_to_all = w_sent_allTABLES
packing_list = t_packing_list
contents_bin = t_attachment
contents_txt = it_message
receivers = t_receiversEXCEPTIONS
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 = 7OTHERS = 8.IF sy-subrc <> 0.RAISE document_send_api1.ENDIF.
* Populate zreceiver return codeLOOP AT t_receivers.
ld_receiver = t_receivers-retrn_code.ENDLOOP.ENDFORM. "send_file_as_email_attachment4. I have 3 PDF's file in various size. But the value of lv_pdf_bytecount parameter is always 79879. Can you explain in more detail how can I use this parameter?
‎2020 Jul 20 11:55 AM
SO_DOCUMENT_SEND_API1 is obsolete, but as you already use it, and it works most of the time, maybe you prefer just to do this change:
Replace:
t_packing_list-doc_size = t_packing_list-body_num * 255.with:
t_packing_list-doc_size = pdf_bytecount.NB: maybe in your current case it's 79879 bytes, but it can't be always the same size as the PDF contents will vary.
‎2020 Jul 20 1:12 PM
1. SO_DOCUMENT_SEND_API1 is obsolete- What is new?
2. When looking at job log overview I see different sizes. But in debugging the value is always 79879

‎2020 Jul 20 2:02 PM
1. Use CL_BCS (not very new by the way, must be since 2001)
2. You must have a bug in your program. Are you sure you pass the right spool number to CONVERT_ABAPSPOOLJOB_2_PDF at each loop? Do you store correctly the value of PDF_BYTECOUNT for each spool?
‎2020 Jul 23 2:20 PM
2. In debug mode (by jdbg in SM37) the value of pv_job_id is always 2602 and lv_bytecount is always 79879. It is very strange because the PDF files are different, which suggests that spool id is different in every call to 'CONVERT_ABAPSPOOLJOB_2_PDF'


‎2020 Jul 23 6:47 PM
That explains why.
Did you find out why you called convert_spool_to_pdf three times with the same spool ID as argument?
‎2020 Jul 23 8:34 PM
It is strange. In the debug it shows the same spool id , but it can not be the same spool id because the 3 PDF files are different.
‎2020 Jul 23 9:18 PM
As you can see in the attached file:
1. The main loop calls c_alv_and_mail_it
2. c_alv_and_mail_it creates the ALV and calls alv2pdf_and_mail_it
3. alv2pdf_and_mail_it calls FUNCTION 'ZALV2PDF_AND_MAIL_IT
4. in FUNCTION 'ZALV2PDF_AND_MAIL_IT - if it is batch
4.1 Calls get_job_details, which returns jobcount, jobname, stepcount by calling FUNCTION 'GET_JOB_RUNTIME_INFO'
4.2 Calls get_batch_job_id_in_spool, which returns the spool id by selecting from
tbtcp
4.3 Calls convert_spool_to_pdf, which calls CONVERT_ABAPSPOOLJOB_2_PDF with the parameter spool id
‎2020 Jul 28 6:37 AM
Hi Sandra,
The main issue 'Translate using variable via pattern' was solved, so I want to reward points. How do I reward?
Hagit‎2020 Jul 28 6:52 AM
Thanks for the feedback. If you want to "reward" me, continue following the Rules of Engagement of SAP Community. Upvote the answers that help or downvote those which don't help, choose the "Best Answer" (button "Accept", as currently done), close the question with the right reason. Thank you!
‎2020 Jul 28 9:37 AM
I looked at Rules of Engagement but did not find any reference how to reward points.
Can you explain in more details what should I do in order to reward points? In some links I saw that a star should appears next to the answer in order to reward. But I do not see any star
‎2020 Jul 28 9:47 AM
What do you mean by "Upvote the answers that help or downvote those which don't help" Do you mean just click on the arrow (yellow)? The maximum that I can give is 2. Is this what you mean? And after that I just have to close the thread?
