This is another one of those “I have been putting this off for a long time” kind of blogs. It is a pretty basic concept of HCM P&F, but it does tend to trip up those that are new to it. Even those experienced with HCM P&F might at times “scratch their head” wondering why it is not working as expected at times. I thought someone else might have discussed this by now, but to my knowledge, no one has yet blogged about the “how’s” and “why’s” of “help” values in HCM P&F…..so I guess, much like cleaning up my office, it is just time for me to get it out of the way. haha
So first off, what the heck are we even talking about?!?!?! This is about the “help” values we present to the user on our forms to make their life (and data entry) easier. This is most often visualized on our forms as a drop-down list control as follows:
For the longest time, this was our only option. However, this has been extended a bit to allows us to use an input box control that will “pop up” a window in which we can run more complex “help” searches (such as showing more than just one values or even using a standard or custom ABAP Webdynpro application…which I have covered in previous blogs as well).
How “help” is configured?
I guess the first place to start is “where” we tell our form “for THIS field, we want help values to come from WHERE“. This can be done in one of two ways.
(1) We can set this in our form scenario’s “form fields” configuration as “input help”.
We set whether the “help” values will come from manually entered entries (ie. you config a list of value/text pairs), a standard service (like SAP_PA), from a custom generic service (one we write which I will discuss later) or from a Web Dynpro application (standard or custom).
(2) We can set it in our FPM form layout configuration in FLUID as a “search help”. This can be a standard or custom (“Z”) search help.
Where “help” is triggered?
I have covered help values from Webdynpro applications in previous blogs, so I will not rehash that here. If you help comes from search helps, that is outside what we will cover here (search helps have been around for ages, so plenty of information already out there…no need for me to add to the “noise”….for once. haha). However if your help values come from a “generic service” (standard or custom), the way in which it is done (ie. “how the magic happens”) is pretty straightforward. For our custom services, you can actually populate your “help” values from pretty much any of the “runtime” methods of your generic service (Initialize, do_operations and get_help_values). However, if you read the documentation from the IMG for the IF_HRASR00GEN_SERVICE (basic generic service), you will see that it notes:
“We recommend that you always us the GET_HELP_VALUES method to provide input help. Note that errors occur if you provide input help with the methods DO_OPERTATIONS or INITIALIZE as well as with the GET_HELP_VALUES method.”
So what does that mean? (1) choose ONE place to populate your help values from….problems do occur if you “mix and match” them (2) they say “always” use the GET_HELP_VALUES method to do this, but I disagree and will tell you why by way of “pros vs. cons” of each.
As you see, we have full control over the SERVICE_DATASETS (ie. the values of our form fields). This means that we can “adjust” our form field value related to our help values. This is useful if we want to set some default dynamically for the form field based on the help values, and the much more common scenario of “clearing” the form field if it’s value is not in our help values. For example, suppose we have the following option for something like:
form field value help values
…and then somewhere on the form, something changes so that the help values now change….
form field value help values
So as you can see, “chicken” is no longer a valid value (and will throw an error if we tried to use it). However, because we are doing this in “do operations”, we can now check the form field value against our help value list and either (1) clear the form field value since it does not exist in the help list or (2) add it to our help list as a valid value. This might sound like a very small difference but it is THE determining factor for me always when deciding whether to use either method. In some cases, you might even handle it in a “hybrid” way such as set/clear your form field in your “do operations” but then let the “get help values” actually build the list. However, this often will require a duplication of code, so I avoid it unless absolutely necessary.
Because we are now trying to control our help values via “do operations”, the downside of this approach is that we must have an “operation” defined for our help value population (which means we must do all the extra work of defining an operation, defining field for the operation, blah blah blah).
Secondly, it only gets triggered/called when the “check” event issued by the framework. This is important to note as the “order” of your backend services will very much dictate how this occurs.
Not to be a spoiler, but you should be able to guess that these are almost directly opposite of “do operations” above.
Since our help values are always “built” in this method, we do not have to define and build any specific “operations” for them. It is typical that in this method, we simply loop through all fields set/configured for us to build the help list, and we handle each one. If you are sticking to good OO programming habits, this still means that we should be doing “pass through”/handoff of the key method parameter values and calling our own methods for each help list (ie. modularized code). I mentioned this only because I have seen others attempt to place ALL of their code directly in this method to build their help values, and it becomes a mess.
Secondly, this method always gets called by the framework both after the “initialize” event and the “check” event. This means that we know exactly when/where it will happen.
Notice one glaring thing with this method’s signature? SERVICE_FIELD_VALUES (our “service dataset”) is an “import only” parameter. This means that we can read our form field values but we cannot change them. Why is this important? Please refer to the “pros” for “do operations” above. This means that we can not dynamically set/clear our form field values based on the values of our help list. This may not be an issue if you have a rather stagnant help list (ie. it does not dynamically change based on other form field value selections)
How it works behind the scenes?
Now, let us talk about how our form fields gets the help values assigned to it (ie. the “binding”). Because we configured our field to have input help, it will be added to the HELP_DATASETS structure. We should be able to see all of our fields configured to have “help” in this dataset, but here, we are looking at one particular entry. As it first “goes into” our “get help values” method, we can see it initialized as:
After being “set”, we can see the main fields have been populated. These are FIELD_CATALOG, KEYCOLUMNNAME, VALUECOLUMNNAME and DATA.
The Field Catalog, as the name suggests, is our way of being able to define dynamically what the “fields” of our help list are. The FIELDNAME column defines the data “type” of our “data” values. The first entry/row is our “value” field (ie. when the user makes a selection from the help list, this is the actual value that is stored), so here, we are defining what the data type/element of that “value” will be. Our second entry/row is our “text” field (ie. this is the one that is displayed in the help list to the user). Therefore since it is just our “display” field, I will typically set it to some long string data element. The column HEADERTITLE can really be anything you like, but I just name them the same to keep it consistent.
One very important thing to note here is that the whatever is used as our “key column” FIELDNAME value must be the same data element as the one assigned to the form field that our help is attached too.For example, if our form field “Employee Number” has data type “PERNR”, but here in our help list field catalog, we assign row 1 FIELDNAME as “CHAR8”, we will get an error/no help list created. We should have the row 1 FIELDNAME assigned as “PERNR” to match our form field’s data type. This has cause MANY people more than a few headaches before! hahaha
As our help lists are simply “key/value” pairs, you can guess what KEYCOLUMNNAME and VALUECOLUMNNAME are used for. These names tell us WHERE/WHAT are “key/value” pairs are based on our FIELD_CATALOG definition. As you might guess, these must match exactly the values used in our “field catalog”. So for example, we might have a field catalog defined with many fields…
row fieldname headertitle
1 pernr employee number
2 ename employee name
3 plans employee position
4 descr employee name+position
But from this, we might only define our “key/value” pair as …..
KEYCOLUMNNAME = pernr (matches row 1 of field catalog)
VALUECOLUMNNAME = descr (matches row 4 of field catalog)
So then our “help list” would display “descr” in the dropdown and assign key “pernr” when the user makes a selection. The cool thing here though is that if we use this in an “input control”, the pop-up window would actually show the whole “field catalog” (ie. it shows much more information that what a “drop down” list constrains us to).
Finally, we have our Data structure. Now hold on to your seat because this just might blow your mind! (haha) THIS is our actual help values/data!!!! Crazy eh?!?!?! haha As you might notice, it’s column layout is exactly what we defined in our “field catalog” (and we actually have a 3rd column for “SACHN” that we did not define in the field catalog because we want to ignore it as we know this is for a drop down and only needs 2 columns).
So we collect our data….then we build our field catalog to tell the framework how our data is laid out (ie. we tell it what data type each column of our Data is)…and finally, we tell it from the field catalog, which columns are our “key” and “value” values. See how it all ties together now? 🙂
If you spend enough time with HCM P&F, you will notice how every “get help” chunk of code all starts to look the same. Whether standard or checking out someone’s previous “custom” work, you will notice they follow a very similar pattern. Read/get data…..define field catalog….set data to “help” field….set key/value column names….wash….rinse….repeat. Here as a “standard” service with a help value being defined….
First off, we normally will the code “collect” our data (or “Data” from above). We can see this below around line 18 and onward.
Next, you will often see a “loop” through the HELP_DATASETS “looking” for our particular “help” form field. I do not like this way as we already know what field we want, so I prefer a “read” on that dataset looking for specific field…but anyways….so we find our “help dataset” field, and then you will normally define/attach the “field catalog” to it. You can see this in lines 35 through 41. Lines 43 through 51 show an example (as mentioned above) where the actual form field value is being set/cleared directly…which tells us this is called from “do operations” because “get help values” does not allows us to change the “service field values” values. From line 54 onward, you can see how it is assigning the “data” to the “help dataset” field.
Lastly, you can see how it defines/sets what the “key” and “value” columns will be based on the “field catalog”. This could be done right after defining the field catalog, but you will often see it done last as well.
How to make it easier?
Having done my share of HCM P&F projects and written my fair share of generic services, I thought there must be an easier way to do this. Now, I am not saying this is the “best” way….it is just my way of handling populating help values (most often for simple drop down lists).
As always, it starts in our “standard” HCM P&F method. In this case, this is the “get help values” method. I start by simply looping through all of my “help” fields and setting them to a field symbol to handle directly using a “case” statement.
For each of my “help fields”, a case will “catch” them to handle (nothing new or groundbreaking here)…
To keep my code easy to manage and follow good OO habits, I keep the actually “handling” of the “help” field assignment in it’s own method. I simply “pass through” the values from the “standard” method that I need. Again, nothing out of the ordinary here. However, within each of my “help” methods is where I kind of “do my own thing”…
The only “work” my specific help methods do is the data gathering/reading (and even then, if used in several process, I create another class/method for that). Lines 4 and 5 are important as they reference what my actual help data structure will look like. This might be a standard type or possibly a public type I have defined here or elsewhere….but we will be using it again later when setting our “data” to our help list field.
Remember when I said line 4 and 5 would come up again later? Well, line 27 is where this happens. We have to set what our “data” structure of our help dataset field is going to be. From here onward, actually creating/building the whole help list is handled by a “common” class that I created. In this way, it handles my help list creation across all of my process (which is nice in keeping them consistent).
In my “common” help class, I have a public “Create” method. It actually calls two other public methods. Having these other methods public allows me some flexibility if I need to set up my help list differently (for example, for use with an “input box” versus a “drop down” list control).
You can see how basic this public “initialize helplist” method is, but it does save us from a lot of redundant code in our services. Seems simple enough, but its the little things. haha You can see that I also set my field catalog columns here too, but you should be able to figure out the internals of that one too.
After “initialize” of the helplist (which just sets our “key column name”, “value column name” and field catalog), we are just assigning our “data” to our help field via some good old “dereferencing”. This code always happens and always in this order, so why not make it into a simple, reusable method call!?!?!? I did. 😛
Again, I am not gone to pat myself on the back and say that this is the “best” way to do it, but I will say it has saved me a lot of time from having to duplicate code. Saving time directly translates into money I have saved my clients, and for that, I do feel pretty proud of myself.
That is really about it. I know the blog might have seemed lengthy for such a basic topic, but I wanted to make sure I covered it well (as I could). As always, I hope it helps others and saves you some time/headaches down the road. Feel free to leave your own take on this below in the comments. For more info on HCM Processes and Forms, you can read through my other blogs ( HCM Processes & Forms: My Blogs ). I also recommend HIGHLY that you buy and read the HCM Processes & Forms book by Brandon Toombs and Justin Morgalis (rumor has it, a new edition is just around the corner covering all the “new” stuff!) With that, I am outta here! Till next time…