In order to print a SAP Scrip, Smart Form or Adobe Form you need a print program and an entry point into that program. The entry point is actually a form that gets the data passed in a standardized manner by the calling program. All calling programs use the same way to pass data to the print programs, i.e. in the global variables of the print program. If you need to find out how your caller is passing the data to the print program, take a look into the standard print program.
After the data is passed, the form will read it from the global variables defined in the print program, gather the rest of the data by various means (FM calls, selects and so on), and then call a function module that is automatically generated by the Smart Form when activated. The data is also passed in a standard manner from the form in the print program to the FM generated by the Smart Form, together with control data and user preferences that will instruct the generated FM’s behavior. The generated FM will then actually print, send data via EDI or send it as an email, depending on the instructions received. The communication with the generated FMs is also standardized.
The print program
A print program can be a standard report (executable) that contains forms that can be called externally by programs that need to have their data printed. Only the form will be executed, not the whole program. The program can be also be non executable, but in order to test it easily, an executable is preferred (type 1).
In our example we need to print and/or send via email a form’s output.
The print program’s form can process the data received from the calling program in order to gather other data that needs to be printed out. The data from the calling program is received, in our case, in structures and tables defined in the standard include RVADTABL
, so we used the same one in our ***TOP
include of the print program. This standard include looks like this:
***INCLUDE RVADTABL . TABLES: NAST, "Messages *NAST, "Messages TNAPR, "Programs & Forms ITCPO, "Communicationarea for Spool ARC_PARAMS, "Archive parameters TOA_DARA, "Archive parameters ADDR_KEY. "Adressnumber for ADDRESS TYPE-POOLS SZADR. *************************Start of Note changes 1508474********************************* DATA: gv_inupd TYPE i, gv_fp_outputparams type sfpoutputparams. " Output parameters.. *External Send DATA: gv_comm_type TYPE ad_comm, gv_comm_values TYPE szadr_comm_values, gs_recipient TYPE swotobjid, gs_sender TYPE swotobjid, gs_intnast TYPE snast, gv_xdevice(10), gv_xprogramm TYPE tdprogram, gv_xdialog. * sending output vai mail DATA: gv_pdf_content TYPE solix_tab. *************************End of Note changes 1508474*********************************
The ***TOP
include file will reference this include file and contain also the rest of the global data declarations that will be used for the actual functionality, i.e. selecting the data and sending it to the form in order to be printed).
*&---------------------------------------------------------------------* *& Report ZMM_POPRINT *&---------------------------------------------------------------------* *& *&---------------------------------------------------------------------* INCLUDE ZMM_POPRINT_TOP. " Global Data INCLUDE ZMM_POPRINT_F01. INCLUDE ZMM_POPRINT_F02.
In order to test our functionality we needed the input parameter passed by the calling program in the NAST-OBKJY
that contains in our case the Process Order Number and the name of the form that was set in the customizing passed by the same program in the TNAPR-SFORM
variable. Note that the name of the form will be later used to find the actual function module name to be called, because every time you activate a form the name of the FM might be changed. Also if you transport the objects in another system the FM name can also changed.
*&---------------------------------------------------------------------* *& Include ZMM_POPRINT_TOP - Report ZMM_POPRINT *&---------------------------------------------------------------------* REPORT ZMM_POPRINT. * Default printing interface INCLUDE rvadtabl. DATA: retcode LIKE sy-subrc. DATA: xscreen(1) TYPE c. "Output on printer or screen * set a default PO for testing here PARAMETERS: pa_docnr TYPE ekpo-ebeln DEFAULT '4500000256', pa_email AS CHECKBOX DEFAULT 'X'. * when running the report, the parameters will overwrite the form structure input nast-objky = pa_docnr. tnapr-sform = 'ZMM_PO'. * this code is executed only by running the report IF pa_email = 'X'. PERFORM entry_email USING retcode xscreen. ELSE. PERFORM entry USING retcode xscreen. ENDIF.
In our case the form entry
only prints the Smart Form (it is not listed here because it only has a call to the smartform_print
form) and the entry_email
form can print and also send an email depending on the buttons pressed by the user prior to the call. The smartform_email
form calls another form to receive the email address where the email should be sent. Both of this forms (entry
and entry_email
) are the actual entry points that have to be set in the configuration of the calling program (in our case the calling program is the transaction ME23N
). This should be known by the functional consultant and he/she should set the program name, the form name and the Smart Form name to be used.
FORM entry_email USING return_code TYPE sysubrc us_screen TYPE c. CLEAR retcode. return_code = 0. xscreen = us_screen. " Check what is the return code of the pressed button. " In case of the print preview, one of these values might come IF SY-UCOMM = 'VIEW' OR SY-UCOMM = 'PREVOUTPUT' OR SY-UCOMM = 'PREV' OR SY-UCOMM = 'PRINT'. " call to print OR PREVIEW PERFORM smartform_print. ELSEIF SY-UCOMM is INITIAL. " send the form on email now PERFORM smartform_email. ENDIF. ENDFORM.
Passing the data to the Smart Form
The Smart Form generates a Function Module when activated. That FM will be called with some standard parameters that all FMs of this kind have and custom defined parameters defined by the developer when designing the Smart Form.
Before calling the generated FM we first need to find its name because SAP in its wisdom decided that the name of the function module sould be random. So we need to use the function SSF_FUNCTION_MODULE_NAME
to find the actual name of the Smart Form’s generated FM. After we have the name we can call it. In our case the real name of the generated FM is (at one point) /1BCDWB/SF00000006
.
FORM smartform_email. DATA: xebeln LIKE ekpo-ebeln. " data for form print DATA: lv_form TYPE tdsfname, fm_name TYPE rs38l_fnam. " data for email control DATA: control_parameters TYPE ssfctrlop, output_options TYPE ssfcompop, email_subject(50) TYPE c, email_po_number(10) TYPE c. DATA: email_recipient TYPE swotobjid, email_sender TYPE swotobjid, g_mail_app_obj TYPE swotobjid. " dummy work area for email function DATA: is_vendor_adrc TYPE adrc, is_vendor_adr6 TYPE adr6. " get PO number xebeln = nast-objky. email_po_number = xebeln. " SmartForm name from customizing table TNAPR lv_form = tnapr-sform. PERFORM get_vendor_details USING xebeln CHANGING is_vendor_adrc is_vendor_adr6. " build the email objects PERFORM mail_recipient_object USING is_vendor_adr6-smtp_addr CHANGING email_recipient. PERFORM mail_sender_object CHANGING email_sender. control_parameters-device = 'MAIL'. control_parameters-no_dialog = abap_true. control_parameters-preview = abap_false. CONCATENATE 'PO No. ' email_po_number INTO email_subject RESPECTING BLANKS. output_options-tdtitle = email_subject. output_options-tdnoprint = abap_false. output_options-tdnoprev = abap_false. * find the generated FM name CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME' EXPORTING formname = lv_form * variant = ' ' * direct_call = ' ' IMPORTING fm_name = fm_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. * now call the generated function module CALL FUNCTION fm_name EXPORTING * BEGIN of standard parameters * archive_index = * archive_parameters = control_parameters = control_parameters mail_appl_obj = g_mail_app_obj mail_recipient = email_recipient mail_sender = email_sender output_options = output_options user_settings = 'X' * END of standard parameters * BEGIN of customer designed parameters iv_ebeln = xebeln * END of customer designed parameters * BEGIN of returning standard parameters * importing document_output_info = * job_output_info = * job_output_options = * END of returning standard parameters 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. ENDFORM.
The function call to the generated FM has some interesting control parameters that will instruct the function to send an email, send to a printer or return the printed document in OTF format in one of the returning parameters. You can find out more if you check this function out.
In the case of the form smartform_print
we do not pass the email and control related parameters because the generated FM is set to generate a print as default.
FORM smartform_print." CHANGING job_output TYPE ssfcrescl. DATA lv_form TYPE tdsfname. DATA fm_name TYPE rs38l_fnam. DATA xebeln LIKE ekpo-ebeln. * SmartForm from customizing table TNAPR lv_form = tnapr-sform. * print data CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME' EXPORTING formname = lv_form * variant = ' ' * direct_call = ' ' IMPORTING fm_name = fm_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. xebeln = nast-objky. * now call the generated function module CALL FUNCTION fm_name EXPORTING * archive_index = * archive_parameters = * control_parameters = control_parameters * mail_appl_obj = * mail_recipient = * mail_sender = * output_options = * user_settings = 'X' iv_ebeln = xebeln " only send the document number to the Smart Form * IMPORTING * document_output_info = * job_output_info = job_output * job_output_options = 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. ENDFORM.
The email source and destination are build as follows:
FORM mail_recipient_object USING email_address TYPE ad_smtpadr CHANGING email_recipient. CALL FUNCTION 'CREATE_RECIPIENT_OBJ_PPF' EXPORTING *IP_COUNTRY = *IP_FAXNO = ip_mailaddr = email_address ip_type_id = 'U' IMPORTING ep_recipient_id = email_recipient *EP_ADDRESS = *ET_RECIPIENT = EXCEPTIONS invalid_recipient = 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. ENDFORM. " mail_recipient_object FORM mail_sender_object CHANGING email_sender. CALL FUNCTION 'CREATE_SENDER_OBJECT_PPF' EXPORTING ip_sender = sy-uname IMPORTING ep_sender_id = email_sender EXCEPTIONS invalid_sender = 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. ENDFORM. " mail_sender_object
References: