Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
tamas_hoznek
Product and Topic Expert
Product and Topic Expert


When creating flavors with custom fields on the screen, it is often requested that a standard search help feature be available for a new field. For instance, an input field is needed which is in fact for a cost center number, and as such, the user would like to take advantage of the usual search help for cost centers. The same request can come for fields that are part of the standard transaction and don’t have a search help assigned but the company is using them for specific purposes so searching is a nice-to-have.

Standard Personas doesn’t offer this functionality, but this can be done (although my solution is arguably a little convoluted). The process requires some ABAP programming knowledge as it involves coding a couple of WebRFCs and also an enhancement, so the assumption is that you know how to handle these. For performing a WebRFC from Personas there are excellent guides and blog posts available on SCN.  Apart from this, only Personas scripting is necessary, there is no need to modify anything.

Below I will explain how to do this in a flavor for the Easy Access Menu (transaction SMEN), although this method should be reusable for most other screens as well.

The basic idea is to somehow activate the necessary search help processing on the backend screen. One way to do this is calling a standard function module that‘s used when we test a search help from the Data Dictionary. This function module is F4_SHLP_SIMULATION. With this, we can call up whichever search help we want. Like for cost centers, it looks like this:





This serves our purpose well, because we only have to script skipping over the first popup screen to get to the Restrictions. From here the user can see the list of available cost centers and pick the desired one just like in a regular transaction.

To call this function module, we need to enhance the command field handling of the underlying screen (in our example, this is the SMEN 100 screen). We will enter a custom command (such as ZZ_PERS_SH) into the command field and then intercept the processing of this command to call the search help test function module.

The intercepted command processing has to know which search help should be passed on to function module F4_SHLP_SIMULATION. Since the backend has no way to access information in our Personas flavor, we need to store the search help name (and any additional information) in a backend table where the ECC process can read it from. This can be accomplished with performing a WebRFC from the flavor.

So let’s see how this looks in our use case. We define a flavor for the Easy Access Menu screen, with new input fields like one for a cost center (and another one for a material number so we will have multiple search help calls in our screen).



Pressing the script button next to our cost center field will do a WebRFC to tell the backend what search help we want to use plus initiates the search help processing by entering a specific command into the command field. The WebRFC code is the following:
FUNCTION z_webrfc_store_data_sh.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" TABLES
*" QUERY_STRING STRUCTURE W3QUERY
*" HTML STRUCTURE W3HTML
*" MIME STRUCTURE W3MIME
*" CHANGING
*" REFERENCE(CONTENT_TYPE) LIKE W3PARAM-CONT_TYPE DEFAULT
*" 'application/json'
*" REFERENCE(CONTENT_LENGTH) LIKE W3PARAM-CONT_LEN
*" REFERENCE(RETURN_CODE) LIKE W3PARAM-RET_CODE
*"----------------------------------------------------------------------
DATA: l_shlp TYPE shlpname,
l_field TYPE char30,
l_shlpkey TYPE indx_srtfd.
DATA: htmldoc LIKE LINE OF html.
READ TABLE query_string WITH KEY name = '_shlp'.
CHECK sy-subrc = 0.
l_shlp = query_string-value.
CONCATENATE 'SHLP_' sy-uname INTO l_shlpkey.
READ TABLE query_string WITH KEY name = '_field'.
IF sy-subrc = 0.
l_field = query_string-value.
ENDIF.
EXPORT shlpname FROM l_shlp
fieldname FROM l_field
TO DATABASE indx(zz) ID l_shlpkey.
IF sy-subrc = 0.
CONCATENATE '{"results":[{"key": "shlpname", "value": "' l_shlp '"}]}' INTO htmldoc-line.
INSERT htmldoc INTO TABLE html.
ENDIF.
ENDFUNCTION.

This code takes two parameters: one of them is the actual search help name (_shlp) and the other one is an indicator for the target field (_field). Since we can have multiple fields with associated search helps (but use the same way to call up the search help dialog), our process needs to know where the user-selected value should be pasted to. This field indicator will be used for that purpose. In our example, CC indicates the cost center target. We'd use a different one (like MAT) for the material master search.

The script for the search help button is like this:





The first step is just to clear out our work field storing the target field indicator. In case we only have a single custom field with our search help process, this can be omitted.

The next thing is to perform our WebRFC above. Step 2 is needed because Personas caches a lot of things, including WebRFCs and if we happen to request the same search help multiple times, it will not actually do the WebRFC but supply the result of the previous call. This is a problem because storing of the desired search help name doesn’t happen then and we may end up getting the search help dialog for another field if in the meantime a second such search help process was also used. In order to make each WebRFC unique to Personas (and thereby force the call), we just pass a random number - generated by a javascript command - to the function module which will be ignored, but then the call will be always different from any previous one.

The complete WebRFC (Step 3) looks like this:

http://server:port/sap/bc/webrfc?_FUNCTION=Z_WEBRFC_STORE_DATA_SH&_shlp=KOSTN&_field=CC&_rand={rand}
Step 4 will enter our custom command in the OK_CODE field. This will be processed by the backend and the result is to call the requested search help dialog, via some additional coding (detailed at the end of this guide, under "Handling the search help call command"). Step 5 is just to press ENTER on the first screen of the search help so that we immediately get to the Restrict Value Range window. Then it is regular search help processing where the user will pick and choose the desired cost center by double-clicking on this screen:



From here, we will get back to the popup window showing the selected cost center value and several other things we don’t really need.



In a regular SAP transaction, the selected value is written immediately into the target field, but in our case, this intermediate screen actually helps because it allows us to have a script that will place the selected value into the intended target field. We have our cost center (2420) so we’ll customize this screen in our flavor to show only what we are interested in, plus add a script button that will paste 2420 into our custom cost center field. The result can be something like this:



Edit 11-Aug-2014: If you have the latest Pesonas client patch applied, you could attach the 'Continue' script button to the OnCreateHandler event of the popup window's UserArea, thereby this screen wouldn't appear at all, and the user doesn't have to click on the button to get the selected value. At the time this blog post was written, this was not possible due to a bug in the Silverlight client which has been corrected since. This means that then there is no need to customize this popup window either.

The ‘Continue’ script button’s definition:



The first step grabs the cost center from the screen, the second step presses the ‘Cancel’ button so that we get out of the search help simulation and back to our Easy Access Menu.

Then, we have to figure out what our target field is. Again, if we only have a single custom field in our flavor with a search help, then this is easy, the value from step 1 can be directly pasted into the target. However if we have more than one possible targets (like in our example), then we need to know where the search help process was initiated from. This is where a second WebRFC is necessary, because during our previous WebRFC, we stored this target
identifier in the backend, along with the search help name.



In step 4, we do the same ‘randomization’ to ensure that our WebRFC is always called (instead of getting a cached result), and step 5 calls a second function module that retrieves the target field ID:
http://server:port/sap/bc/webrfc?_FUNCTION=Z_WEBRFC_READ_DATA_SH&_rand={rand}

The function module code:
FUNCTION z_webrfc_read_data_sh.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" TABLES
*" QUERY_STRING STRUCTURE W3QUERY
*" HTML STRUCTURE W3HTML
*" MIME STRUCTURE W3MIME
*" CHANGING
*" REFERENCE(CONTENT_TYPE) LIKE W3PARAM-CONT_TYPE DEFAULT
*" 'application/json'
*" REFERENCE(CONTENT_LENGTH) LIKE W3PARAM-CONT_LEN
*" REFERENCE(RETURN_CODE) LIKE W3PARAM-RET_CODE
*"----------------------------------------------------------------------
DATA: l_shlp TYPE shlpname,
l_field TYPE char30,
l_shlpkey TYPE indx_srtfd.
DATA: htmldoc LIKE LINE OF html.
CONCATENATE 'SHLP_' sy-uname INTO l_shlpkey.
IMPORT shlpname TO l_shlp
fieldname TO l_field
FROM DATABASE indx(zz) ID l_shlpkey.
CONCATENATE '{"results":[{"key": "shlpname", "value": "' l_shlp '"},{"key": "fieldname", "value": "' l_field '"}]}' INTO htmldoc-line.
INSERT htmldoc INTO TABLE html.
ENDFUNCTION.

Then in step 6 we write this field ID into our work field on the screen. This is used in IF statements to decide where the selected cost center should go:



And the result is:




Handling the search help call command


The only thing remaining is the process that takes place in the backend, which actually calls up the search help dialog. Remember that in the script which initiated the search help process, we entered a custom string into the command field? Obviously, this has to be handled somehow and this is where an enhancement comes in.

Essentially we need to intercept this command before the standard OK code processing kicks in because we would likely end up with an error message that such a command doesn’t exist, or in our case (SMEN) the system would try to execute transaction ZZ_PERS_SH. Since every screen can have a different process handling OK codes, we have to analyze the actual screen we are on and find out how to intervene in the command field processing before anything else happens. In our test case with the Easy Access Menu, this is very simple since there is an easy-to-locate subroutine where this is done. In some other cases this may be a bit more complicated to accomplish, depending on the technique used.

For SMEN, the command field processing is in subroutine UCOMM_USER_COMMAND of module pool SAPLSMTR_NAVIGATION. Here, we are going to implement our code using the implicit enhancement point at the beginning of the subroutine.



The actual code to be implemented is:
data: zz_SHLPNAME type SHLPNAME,
zz_shlpkey TYPE indx_srtfd.
if okcode = 'ZZ_PERS_SH'. "Personas search help was selected
clear okcode. "Delete custom command value
CONCATENATE 'SHLP_' sy-uname INTO zz_shlpkey. "build key for INDX access
IMPORT shlpname TO zz_shlpname "find out which search help to call
FROM DATABASE indx(zz) ID zz_shlpkey.
IF sy-subrc = 0 AND zz_shlpname IS NOT INITIAL.
CALL FUNCTION 'F4_SHLP_SIMULATION' "call selected search help in test mode
EXPORTING
shlpname = zz_SHLPNAME.
ENDIF.
EXIT. "no further user command processing needed
endif.

And that’s pretty much it.
Again, this last piece may have to be tailored according to how the actual screen logic is coded, but the principle remains the same.


31 Comments