I have not blogged in a good while and figured if I came back, I better drop a banger (that’s what the “kids” call it, right?). Well, I guarantee you, this one is quite a doozy! (that’s what the “old folks” call it, right?). I will worry about which crowd I most appeal to later. For now.....let's do this! I am about to rock your world and show you a "new" way to make printing your FPM forms for HCM P&F a whole lot easier....like super simple easy! Don't believe me? Read on!
Background
Way back when SAP announced and released the FPM options for HCM Processes & Forms which effectively replaced Adobe Interactive Forms, the world rejoiced. When SAP said “nuh uh uh…not so fast” and let it be known that the
only way to “print” FPM forms was to develop and Adobe form/layout in parallel and assign it in the configuration, the world let out a collective sigh. That just did not sit right with us HCM P&F folks. In fact, I can say that in all of my projects implementing FPM HCM P&F processes, not a single one ever implemented the “Adobe print form option”. Not ONE! In most cases, the customers would tell their users either:
- You do not need to print anything….that is part of why we are moving to this framework.
- You can just screen capture and use that (email, save local, etc)
- You always have access to view the “history” of the process to see what the “form” looked like at any point.
- For security, we do not want you printing anything or “accidentally” printing to some other location or “leaving” it on a printer.
That was just the understood way it was for years and years…..and well…..up till now. At many times over the years in my “free” time (what a laugh!), I attempted to tackle this “print” problem for FPM form type processes. I looked at it from all kinds of ways. I would get into it for a bit and then just back away (sometimes just throwing my hands up and giving up). Recently, my current client brought up their need to print again. Once again as I had done many times in the past, I rattled off the standard answer explaining the limitation directly as stated by SAP (as did others on my project team who were now very familiar with answering this question from our business users). Just for “grins and giggles”, I decided to give it another look…..one more go of it……and low and behold, I found a solution!!!!
Before I got into the nitty gritty details, I hope you are surprised at the mere fact that there is a solution and someone bothered with solving it all these years later. Furthermore, I hope you are dismayed to hear that it actually as easy as ONE line of code. I will say that it actually was not possible till a fairly recent update (nw7.3 ehp1?) by SAP of their own standard Webdynpro ABAP (WDA) classes and interfaces (IF_WD_APPLICATION) to include a very simple but powerful method. So why did SAP not already update their code to do this?!?!?! I have my theories:
- Does SAP really think many customers use FPM HCM P&F anymore? (all the rage being Fiori and such)
- Is SAP more interested in evolving SuccessFactors and cloud HCM than going back and updating “old” stuff?
- Are the resources within the HCM P&F technical team even up to date on some of the outside changes/updates SAP has made like including this new-ish way to print a WDA page?
- Who knows? Who care? (this is the “catch all”)
Regardless, I do hope that “maybe” SAP will just include this into some coming patch or something. Until then, I know you really want to read about how it is done….here we go!
Summary of Changes
This solution requires that we make TWO simple standard SAP class enhancements. As said, the actual “fix” itself is just a simple single line of code. That is all it is. Prepare to be amazed!
Class CL_HRASR00_PROCESS_EXECUTE method GET_EVENTS_4_FORM_INIT
This method determines what “events” the framework is listening to and also will define what buttons and “form utilities” options should display in the top application menu toolbar. You can read all through it, and it is actually useful to know for other things. In this code around line 171, you will see that it starts to determine if the “Generate PDF” option should show to the user in the “form utilities” options. At line 188, you can see where it checked configuration to see if we have a “print” Adobe form defined for our process (ie. “lv_form”).
CALL METHOD cl_hrasr00_fpm_utilities=>get_form_template_addtl
EXPORTING
iv_form_scenario = ms_process_info-form_scenario
iv_form_scn_ver = ms_process_info-form_scen_vers
IMPORTING
* ev_is_ok =
ev_form_template_addtl = lv_form.
IF lv_form IS NOT INITIAL AND ls_t5asrsettings-value EQ 'X'
AND lv_form_type EQ if_hrasr00_dt_constants=>c_ot_form_type_wda_fpm.
* lv_event_desc = if_hrasr00_ui_constants=>c_event_gen_pdf.
add_event(
EXPORTING
iv_event = if_hrasr00_ui_constants=>c_event_gen_pdf
CHANGING
ct_events = et_events
).
ENDIF.
If it does not find a form, it just hides the “print”/Generate PDF option from the user. Therefore, our first step is to make the menu option available even if we do NOT have an Adobe form defined for our process.
To do this, we make an “overwrite-method” enhancement of the method GET_EVENTS_4_FORM_INIT. I will not cover how to do this as it is fairly easy to out how to do and is straightforward enough. I will say when you create the enhancement, do the following:
- When asked if you want to allow access to the classes protected blah blah blah and such, just click “yes”. This is where using “CORE_OBJECT” will come into play in just a bit.
- Copy-and-paste ALL of the code from the standard GET_EVENTS_4_FORM_INIT method into your enhancement method.
- Do a “check” on the copied code and at each point you hit an error and the cursor moves to that spot, simply paste “CORE_OBJECT->” to the beginning of it. For example, if the cursor stops at ms_process_info-form_scenario you simply modify this to be CORE_OBJECT->ms_process_info-form_scenario. Continue doing this until you no longer have errors on “check”.
- Save and compile the “unmodified”, copied standard code.
- Add your actual enhancement logic around line 219 as follows:
************ ENCHANCMENT: We can handle PRINT for FPM with or without
************ Adobe form configured
* IF lv_form IS NOT INITIAL AND ls_t5asrsettings-value EQ 'X'
* AND lv_form_type EQ if_hrasr00_dt_constants=>c_ot_form_type_wda_fpm.
** lv_event_desc = if_hrasr00_ui_constants=>c_event_gen_pdf.
* CORE_OBJECT->add_event(
* EXPORTING
* iv_event = if_hrasr00_ui_constants=>c_event_gen_pdf
* CHANGING
* ct_events = et_events
* ).
* ENDIF.
* we basically take out the check for form name being empty
IF ls_t5asrsettings value EQ 'X'
AND lv_form_type EQ if_hrasr00_dt_constants=>c_ot_form_type_wda_fpm.
CORE_OBJECT->add_event(
EXPORTING
iv_event = if_hrasr00_ui_constants=>c_event_gen_pdf
CHANGING
ct_events = et_events
).
ENDIF.
**** END ENHANCEMENT *********
ENDIF.
- Save and compile your code. Done!
Class CL_HRASR00_FPM_FEEDER method HANDLE_FORM_EVENTS
Now that we are showing the “Generate PDF” menu option, we now need a way to tell it what to do when the user clicks this option. Hence, this method as the name implies is the “event handler” for the application. If we look in the method around line 432, you can see where it catches the “PRINT_PDF” event. Similar to the method mentioned above around line 440, you can see where it checks configuration to see if we have an Adobe form configured for the process (ie. “form_name”).
CALL METHOD cl_hrasr00_fpm_utilities=>get_form_template_addtl
EXPORTING
iv_form_scenario = a_form_scenario
iv_form_scn_ver = a_form_scenario_version
IMPORTING
* ev_is_ok =
ev_form_template_addtl = form_name.
IF form_name IS INITIAL.
** message maintain form name in form scenario
* MESSAGE 'No form template assigned for form scenario' TYPE 'I'.
lv_is_ok = ''.
EXIT.
ENDIF.
lv_is_ok = 'X'.
You can also see that if it does NOT find a form, it simply exits. As you might guess now, this is where we need to say “if you do not have form assigned, go ahead and print the form in our new magic way”. This single line of code is what does EVERYTHING for us!
cl_wdr_task=>application->get_api( )->print_page( ).
Just as you did in the other method, you will create an “overwrite-method” enhancement. As before, create the overwrite of method HANDLE_FORM_EVENTS and first “cut-and-paste” the original standard method code into your enhancement. Again, “check” the code and make the necessary changes (ie. “CORE_OBJECT->”) where needed until you no longer receive syntax error warnings one “check”. Now, make the following modifications to the code:
CALL METHOD cl_hrasr00_fpm_utilities=>get_form_template_addtl
EXPORTING
iv_form_scenario = CORE_OBJECT->a_form_scenario
iv_form_scn_ver = CORE_OBJECT->a_form_scenario_version
IMPORTING
* ev_is_ok =
ev_form_template_addtl = form_name.
IF form_name IS INITIAL.
** message maintain form name in form scenario
* MESSAGE 'No form template assigned for form scenario' TYPE 'I'.
"lv_is_ok = ''.
"**** ENCHANCEMENT ****
"if no form is configured, use the WDA capability to print the web page as shown
lv_is_ok = 'X'.
cl_wdr_task=>application->get_api( )->print_page( ).
EXIT.
"**** END ENHANCEMENT **********
ENDIF.
lv_is_ok = 'X'.
Now, when the user executes the process and clicks the “Generate PDF” option without having an Adobe print form configured, they will see the following type of pop-up that looks just like their form and application window with the addition of having buttons at the top for “print” and “close”.
Upon clicking “print”, it will now generate our PDF view of the form as it appears in the application. Magic!
The only other thing to mention here is the user may have to adjust “scale” to get the entire form to save to print/pdf. This is typically the case only for very long forms. Lastly, the “print preview” display of the form will appear active (ie. the user can enter/change info in input boxes and such, however, none of the controls, buttons, etc. will respond to any action other than the “Print” and “Close” buttons at the top.)
For those that care (and dig deeper to the nTH degree as I do), the actual "print" pop-up gets generated by class CL_WDR_CLIENT_SSR_LS in method IF_WDR_CLIENT~SEND_RESPONSE around line 79 where you will see that it renders the print page, converts the WDA page to PDF, attaches the file to the window and then finally, renders the external window (ie. pop up). If you look at class CL_WDR_CLIENT_SSR_LS method RENDER_PRINT_PAGE_TEMPLATE, you can see where it creates the "Print" and "Close" buttons as well as rendering the web page area for printing.The really interesting part is you can see it injects Javascript to handle the actual printing (using the SWDA_Printing object), so there is no server side logic going on to print. Pretty clever.
Well, that’s about it…actually no…not “about”….that is it. Not much more to it than that….and again, for such a simple “fix”, maybe SAP will take it “in house” to update the standard code. To me, it actually does not matter either way. I am just personally glad to have slayed yet another dragon in the HCM P&F world and move on to the next one after “fighting” this one for many, many years. Maybe I will go rest now……..nahhhhh… who am I kidding! hahaha Till next time….