BSP/HowTo: Generate PDF Output from a BSP.
Have you ever heard the comment from someone, “Boy I sure would like to get this report as a PDF on my computer in order to send it to Bob over in accounting. He doesn’t have a login for this BSP application and it’d be great to send him this data.” Well I haven’t either, OK, not exactly like it but similiar. It left me with two choices, 1, give “Bob” a login or 2, figure out how to output my report as PDF.
Being a frequent visitor to SDN I remembered reading a few things about PDF and outputing so I began my searching…
BSP Programming: Handling Of Non-HTML Documents
Generate file .doc or .pdf as from a text
Well after playing around with the information, and I mean really good information given in these posts/weblogs I realized that I still had a few questions left unanswered. Namely, “How do I get the data as OTF?”.
This lead me to post a new topic in the BSP forum called PDF output and with the help my fellow SDNers I think we’ve come up with all the info needed to enlighten those stubmling around in the dark like myself.
Special thanks go out to…
So we came down to basically 3 major possibilities for doing this.
- FM: CONVERT_OTF
- FM: CONVERT_ABAPSPOOLJOB_2_PDF
- External Tools
To get started let’s create our BSP page.
Page Layout
\
This is basically the code from Brian’s weblog with a couple of new radio options.
Page Attributes
style=”width:350px;border:thin inset;background:lightgrey;background-color:lightgrey”>\ content\ TYPE\ STRING
display_type\ TYPE\ STRING
display_url\ TYPE\ STRING
file_content\ TYPE\ XSTRING
file_length\ TYPE\ STRING
file_mime_type\ TYPE\ STRING
file_name\ TYPE\ STRING
OnInputProcessing
That there will get all of the normal stuff working that Brian describes in his weblog on dealing with NON-HTML documents.
Now let’s go into each of these 3 possibilites and see which one works best for you…
FM: CONVERT_OT
This seems to be the best possible solution; to be honest with you, I like this one. Not sure why but I do. First things first is that you have to create a SmartForm (transaction SMARTFORMS) and once you create the SmartForm just in the menu click ENVIRONMENT – FUNCTION MODULE NAME. You see once you create the SmartForm and activate it it generates a function module.
Let’s make a SmartForm
I started by calling transaction SMARTFORMS, there I gave my SmartForm a name and selected “CREATE”
Once created I started to edit the SmartForm, the first step was the Form Interface, I entered my table parameters there.
Then I defined my global variables for the table and the table structure.
Then on the Initalization tab of the Global section I was able to initialize my table.
Then simply click on your Page and you can then create a table element, which then under the data table you define your table LOOP.
Then for test purposes I simply added one cell of data and one text label to the cell, then dragged from my field list box the name of one cell to the new text box.
Once that was all complete I was able to “activate” the SmartForm and then get the function module name from the menu option.
So got your SmartForm? OK, then let’s modify our code to add in for that. Go to your OnInputProcessing Event Handler and append this to the bottom of the existing code.
OnInputProcessing
As you can see we give our now selected table of data to the SmartForm for processing and then the OTF encoded results from the SmartForm to the CONVERT_OTF FM for processing.
Did you try it? Did you get your PDF file like me?
FM: CONVERT_ABAPSPOOLJOB_2_PDF
Raja provided a nice code sample to work with for this option.
sy-spono will then contain your Spool number which you can then use with the function module CONVERT_ABAPSPOOLJOB_2_PDF with the Spool number as a parameter. This will return a table, PDF STRUCTURE TLINE, which you can then save with .pdf extension. As Raja pointed out “I havent tried this myself inside a BSP application, but i feel that it should work.”
From a logic point of view I will say that since the normal ABAP write statements don’t work directly in the BSP you would have to really think hard to figure out how to get this to work. We are now attempting to do just that and will post back with an update to the weblog if we figure it out.
Another option would be if you had the spool number first, for example from a select list or something. You would be as dynamic as with the SmartForm method but it should also work, just gotta convert your PDF table to XSTRING.
I think that should work, we will keep you posted on further developments using this method.
Here is a solution from Raja: SPOOL TO PDF
External Tools
Now there are lots of these tools out there, Eddy points out HTMLDOC. Eddy goes on to tell us that all we have to is
“The way to go is to install HTMLDOC, then make an external command. In your BSP page (with extension pdf, is needed for MIE) make you HTML and write it to temp file. Call the external command with the temp file as input. Then read the pdf and set it as content and set all response headers for pdf. Clean up the temp files. It works good and fast.
There are also JAVA and ActiveX tools out there as well. Each of you will have to decide your own strategy of course. Personally if the system can already do it then why install another component that you may have to worry about compatability issues with in the future?
Where does all this leave us?
So as you can see there are often many possiblities for problems you encounter and it is just a matter of deciding which one works best for you. In this case does it make sense to create a SmartForm for each and every item you want to print out? Perhaps if you have a Corporate Identity that you must adhere to then this could be the best way.
The “spool” seems like a great choice simply because you don’t have create a SmartForm first. In fact a clever person might just have a ABAP report that runs and creates the Spool outputs and then a BSP which lets a person select an existing Spool and then retrieve it as PDF.
External tools are always available and there are lots of them out there, however, you have to ask yourself “Do you really want to add a component that may not be compatible after the next SP or Release?”. These are problems that sometimes arise as we move into the future, whereas, an internal solution such as SmartForms or ABAPSPOOL to PDF well those I think will be supported in the future.
Please consider this weblog a work in progress as I don’t think we’ve heard the end of our efforts with ABAP Spool and I’m sure there are quite a few more possible solutions out there and I hope you’ll share yours with us as well!
What the future holds!!
From Matthias Zeller, Indeed Interactive Forms is the “next generation” forms tool in SAP (and not only for interactive, but also for print forms). It is available starting with Web AS 6.40. Smart Forms and SAPscript will be continue to be available but all new development around SAP forms will be done in the new Interactive Forms. The Adobe document services (ADS) which are part of Interactive Forms can generate different output including PDF, PS, PCL and ZPL (for Zebra Label printers).
So with Interactive Forms you will be able to generate PDF in an SAP system natively by merging forms data with a form template (so you do not need to create OTF anymore and use the CONVERT_OTF libraries to generate PDF). This can be configured in ABAP using transaction SFP or with Web Dynpro for Java to create PDF documents embedded in a Web UI (and in the future also with Web Dynpro for ABAP).
The PDFs generated with ADS are actually the latest version PDF 1.6 and can be made accessible to blind people via screen readers.
Tips:
From Jonathan Bourne, Just wanted to mention that rather than hunting for the Smartforms function module name the following function module can be used:
SSF_FUNCTION_MODULE_NAME
This FM takes the Smartform name and returns the function module name. This is a more robust solution as the Smartform may receive a different FM name when it is transported to other systems.







Without any help of SMARTFORMS from ABAP programming forum(there you go!!!).
Thanks a million for the weblog, makes it so much easier.
Regards,
Subramanian V.
(Thanks for putting me in the spotlight :P)
I struggled for a few hours on the SmartForm - ok it's a very basic one but it did the trick for testing purposes 🙂
Just checked that this weblog of yours is posted in SDN (topic). Probably it should be in BSP.
Regards,
Subramanian V.
Regards,
Subramanian V.
Just wanted to mention that rather than hunting for the Smartforms function module name the following function module can be used:
SSF_FUNCTION_MODULE_NAME
This FM takes the Smartform name and returns the function module name. This is a more robust solution as the Smartform may receive a different FM name when it is transported to other systems.
Thanks again for a great article.
JB
This is an excellent post that shows the collective power of SDN.
Very nice, Mark.
I'm very familiar with getting PDF's and Excel onto our Supplier Portal...great to see we are following the same process!! We recently put "EBP Purchase Order Display" via PDF into a BSP on the SAP Portal...GREAT to see you guys using a function module I haven't used yet (CONVERT_ABAPSPOOLJOB_2_PDF), I've always used the "convert OTF" and then get that into PDF to get it to work...I must say the making a COMPLEX SmartForm is the "bottleneck" in the process...I hope SAP get SmartForms to the level of ease as creating a document using Crystal Reports (for example) one day!!
But once again great work guys!!
Lynton Grice
Lynton
Regards
Lynton
Need help with the following questions.
Hi,
1)We want to show some details in an iView pertaining to the person who has logged into the portal. We are calling a function module (when a user clicks on a workset in the portal) and passing some parameters to it. The function module pulls the data from the tables and generates a sap script which displays the data in a SAP Script Form.
Now our problem is how do we display the form in the iView?
2) We want to show some details in an iView pertaining to the person who has logged into the portal. We are calling a function module (when a user clicks on a workset in the portal) and passing some parameters to it. The function module pulls the data from the tables and converts the data into a pdf file.
How do we display the data in the .pdf format in the iView.
Thanks in advance
1) Is it possible to pass parameters dynamically (For eg userid of the person who has logged onto the portal) from webdynpro to a RFC? If yes, how?
Thanks in advance.
Jayesh
I was able to use your code (with minor changes) to convert mail forms to PDF. You can use FM MAIL_FUNCTION_MODULE_NAME to get the mail form function module name, and substitute that in the 'call function' of OnInputProcessing
Thanks, you saved me tons of work!
Brant Berg
Is the same code will work in MVC Concept????
If yes where we need to write all the code??
is it in the DO_HANDLE_EVENT or in the View page??
Expecting the reply ASAP.
Thanks,
Greetson
As for this code, yes it works fine in MVC and where you write it all depends on you and your application.
If you have specific questions take a jump over to the BSP forum, it's a much better place for helping each other out.
Still, I'm wondering which table you use for zsystems.
data: lt_sys type table of zsystems.
I cannot find this table. Would you please tell me the origin?
And which table do you use for zsystemtab? This table is referenced within the smartform
Thank you very much for your help,
Stephan
Craig
I do the test in a 6.40 UNICODE system.
Finally, I find a code to do the conversion:
data: spool_nr type TSP01-RQIDENT,
line type tline,
l_pdf_xstring type xstring,
lt_lines type table of tline,
l_pdf_len type i.
field-symbols
type X.
...code to obtain the spool_nr...
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
SRC_SPOOLID = spool_nr
NO_DIALOG = ' '
IMPORTING
PDF_BYTECOUNT = l_pdf_len
TABLES
PDF = lt_lines
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
.
clear l_pdf_xstring.
loop at lt_lines into line.
assign line to
casting type X.
concatenate l_pdf_xstring
into l_pdf_xstring in byte mode.
endloop.
l_pdf_len = xstrlen( l_pdf_xstring ).
...code to make cached_response...
This was also on a 620 system. But you can really use any tables.
SAP Note
The following error text was processed in the system:
An exception with the type CX_SY_DYN_CALL_PARAM_MISSING occurred, but was neither handled locally, nor declared in a RAISING clause
Exception Class CX_SY_DYN_CALL_PARAM_MISSING
Error Name
Program CL_O20Q0EUR89BCFKJ1CHWU5YVP65JCP
Include CL_O20Q0EUR89BCFKJ1CHWU5YVP65JCM005
ABAP Class CL_O20Q0EUR89BCFKJ1CHWU5YVP65J
Method _ONINPUTPROCESSING
BSP Application ZANU_PDF_OUTPUT
BSP Page FIRST.HTM
Line 99
Long text The call of the function /1BCDWB/SF00000571 failed: the required parameter WA_ZDPBIR was not filled.
What is the reason and possible solution?
Regards,
Anubhav Jain.
I want to convert a smartform document into pdf in my BSP Applikation.
But when it have to convert, i got the message "Data didnt begins with '%pdf-'"in the pdf reade . I dont know why???
Here is my Code from the Intialization Event:
* event handler for data retrieval
* parameters for generated function module
data: l_function_module_name type rs38l_fnam,
ls_output_options type ssfcompop,
ls_control_parameters type ssfctrlop,
ls_output_data type ssfcrescl,
l_devtype type rspoptype.
* generated result: HTML with embedded CSS
data: ls_xmloutput type ssfxmlout,
lt_html_raw type tsfixml,
l_xstring type xstring, "needed for HTTP response
l_html_xstring type xstring,
l_xlength type i.
* generated result: PDF format
data: l_pdf_xstring type xstring,
lt_lines type table of tline,
ls_line type tline,
l_pdf_len type i.
* Cookie mit Eingabewerten holen
cl_bsp_server_side_cookie=>get_server_cookie(
EXPORTING
name = 'lt_fields'
application_namespace = 'NONE'
application_name = 'NONE'
username = 'NONE'
session_id = 'NONE'
data_name = 'NONE'
"IMPORTING
"expiry_date = date
"expiry_time = time
CHANGING
data_value = lt_fields ).
* Cookie mit Equipmentdaten holen
cl_bsp_server_side_cookie=>get_server_cookie(
EXPORTING
name = 'ums_equip_ges'
application_namespace = 'NONE'
application_name = 'NONE'
username = 'NONE'
session_id = 'NONE'
data_name = 'NONE'
"IMPORTING
"expiry_date = date
"expiry_time = time
CHANGING
data_value = ums_equip ).
*-----------------------------------------------------------------------
* Get name of generated function module
*-----------------------------------------------------------------------
call function 'SSF_FUNCTION_MODULE_NAME'
exporting formname = 'Z_REPKOST_GES'
* variant = ' '
* direct_call = ' '
importing fm_name = l_function_module_name
exceptions no_form = 1
no_function_module = 2
others = 3.
if sy-subrc 0.
* error handling
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
exit.
endif.
*---------------------------------------------------------------------------
* get device type from language
*---------------------------------------------------------------------------
call function 'SSF_GET_DEVICE_TYPE'
exporting
i_language = sy-langu
* i_application = 'SAPDEFAULT'
importing
e_devtype = l_devtype
exceptions
no_language = 1
language_not_installed = 2
no_devtype_found = 3
system_error = 4
others = 5.
if sy-subrc 0.
* error handling
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
* set device type in output options
ls_output_options-tdprinter = l_devtype.
*-----------------------------------------------------------------------
* Call the generated function module
*-----------------------------------------------------------------------
call function l_function_module_name
exporting
* archive_index =
* archive_parameters =
control_parameters = ls_control_parameters
* mail_appl_obj =
* mail_recipient =
* mail_sender =
output_options = ls_output_options
user_settings = space
UMS_EQUIP = UMS_EQUIP
LT_FIELDS = LT_FIELDS
importing
* document_output_info =
job_output_info = ls_output_data
* job_output_options =
* tables
* zsystems = lt_sys
exceptions formatting_error = 1
internal_error = 2
send_error = 3
user_canceled = 4
others = 5.
if sy-subrc 0.
* error handling
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
*-----------------------------------------------------------------------
* Conversion of output format OTF into PDF format
*-----------------------------------------------------------------------
* now convert the final document (OTF format) into PDF format
call function 'CONVERT_OTF'
exporting
format = 'PDF'
* MAX_LINEWIDTH = 132
* ARCHIVE_INDEX = ' '
* COPYNUMBER = 0
importing
bin_filesize = l_pdf_len
bin_file = l_pdf_xstring " binary file
tables
otf = ls_output_data-otfdata
lines = lt_lines
exceptions
err_max_linewidth = 1
err_format = 2
err_conv_not_possible = 3
err_bad_otf = 4
others = 5
.
if sy-subrc 0.
* error handling
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
DATA: cached_response TYPE REF TO if_http_response.
DATA: guid TYPE guid_32.
DATA: fileUpload TYPE REF TO CL_HTMLB_FILEUPLOAD.
if sy-subrc EQ 0.
CREATE OBJECT cached_response TYPE CL_HTTP_RESPONSE EXPORTING add_c_msg = 1.
l_pdf_len = xstrlen( l_pdf_xstring ).
cached_response->set_data( data = l_pdf_xstring
length = l_pdf_len ).
cached_response->set_header_field( name = if_http_header_fields=>content_type
value = 'application/pdf' ).
cached_response->set_status( code = 200 reason = 'OK' ).
cached_response->server_cache_expire_rel( expires_rel = 180 ).
CALL FUNCTION 'GUID_CREATE'
IMPORTING
ev_guid_32 = guid.
CONCATENATE runtime->application_url '/' guid '.pdf'INTO display_url.
cl_http_server=>server_cache_upload( url = display_url
response = cached_response ).
ENDIF.
RETURN.
I hope you can help me.
Kind Regards
I am having some problem in generating the cached response. I am writing my code in a method of a class which is triggered from Web UI. The object runtime is not defined here so it throws an error each time. Please let me know how should I proceed.
Thanks,
Abhishek
too bad that this blog is nearly unreadable. it would still be very useful today and is cited on some pecial interest pages.
good job done long time ago. and now back to the future 🙂
Hi Anton,
This blog was submitted in the Report Your Missing Blog Content document and you may track the process via this document. The content will be repaired shortly.
Thanks,
Oxana