My Super-awesome Selection Screen
Friday, July 31, 2009
For a long time I was pretty happy with plain and simple selection screens and, even though I was aware that they could be manipulated, I’ve never ventured there myself. But I guess there is time for everything.
Recently we got a request for practically the same report from two different users. One of them wanted to see the information for the whole year in monthly “buckets” (i.e. one month = one column in the report), but the other wanted to run the report for any period of time and get the total number for the period. My first reaction was to ask the second guy to export the report to Excel and run the total there, but that wouldn’t be very nice, would it?
So I decided it was time for me to learn how to create a somewhat dynamic selection screen to make both users happy with one report. An obvious quick and dirty solution would be to have two parameters on the screen with a validation that at least one of them (but not both) must be entered. But I wanted something more elegant and decided to explore an option of opening and hiding the parameters. The users would be provided with 2 mutually exclusive options (radio button): full year and any period. Depending on the choice, an additional parameter for either the year or a period would open (see the picture on the left).
After just a couple of hours of research and scratching my head I came to this prototype (the commentary follows):
TABLES: sscrfields.
DATA: lv_spmon TYPE spmon.
PARAMETERS:
rb_year TYPE flag RADIOBUTTON GROUP g1 DEFAULT 'X' USER-COMMAND radio,
p_year TYPE gjahr MODIF ID yr,
rb_mth TYPE flag RADIOBUTTON GROUP g1.
SELECT-OPTIONS: s_period FOR lv_spmon NO-EXTENSION MODIF ID mth.
AT SELECTION-SCREEN ON RADIOBUTTON GROUP g1.
PERFORM change_screen.
AT SELECTION-SCREEN.
IF sscrfields-ucomm = 'ONLI'.
IF rb_year = 'X' AND p_year IS INITIAL.
MESSAGE 'Enter Year' TYPE 'E'.
ENDIF.
IF rb_mth = 'X' AND s_period[] IS INITIAL.
MESSAGE 'Enter Period' TYPE 'E'.
ENDIF.
ENDIF.
AT SELECTION-SCREEN OUTPUT.
PERFORM change_screen.
START-OF-SELECTION.
WRITE 'Hello world'.
*&---------------------------------------------------------------------*
*& Form change_screen
*&---------------------------------------------------------------------*
FORM change_screen.
LOOP AT SCREEN.
IF screen-group1 = 'MTH'.
IF rb_year = 'X'.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
MODIFY SCREEN.
ELSEIF screen-group1 = 'YR'.
IF rb_mth = 'X'.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
ENDFORM. "change_screen
OK, so here we have a routine change_screen that is called either before the selection screen is displayed or when a user clicks on the radio button. Note that RB_YEAR (i.e. whole year option) is the default choice and in this case we have to declare the default value ‘X’ explicitly, because otherwise RB_YEAR value will be initial on the first pass (i.e. before displaying the screen).
Help on MODIF ID command kind of implies that you have to use it to be able to modify the field. Well, this is not entirely accurate. MODIF ID simply provides a convenient way to modify not just the parameter field itself but all the related fields as well. For example, I started with using SCREEN-NAME field, but quickly realized that P_YEAR means only the actual input field. The corresponding label is actually a separate field. So at first I ended up with a hidden input field, but the label was still displayed. True, you could use SCREEN-NAME CP ‘*P_YEAR*’, but modification ID makes it much cleaner and easier.
Surprisingly, the most challenging piece was to make sure that the correct parameter would be required. My first idea was to use SCREEN-REQUIRED, but it turned out that I couldn’t modify this field at the right moment – for example, S_PERIOD would still be required after the user clicked on the RB_YEAR radio button. I did discover an unexpected benefit of this option though: it can make both “from” and “to” fields in a selection option required.
After that failed, I moved the validation to the AT SELECTION-SCREEN event. But I still wasn’t happy because it kicked in even when the user just hit the Enter key and I wanted it to work only when the user would click the Execute button to actually run the report. Fortunately, I was able to use SSCRFIELDS-UCOMM field to check the Execute button’s OK code. Note that SSCRFIELDS had to be declared with TABLES. Normally I’m trying to avoid this kind of declaration because it’s usually not necessary and is just a waste of space. I hate when people declare the whole table with 200 fields when they really need just a few variables – it’s just lazy. Often developers use TABLES to be able to refer to a field in SELECT-OPTIONS, but, as you see in this example, this is not required either – you can actually use any variable in SELECT-OPTIONS.
A word of caution – this kind of validation on selection screen won’t work if the user starts the report in the background mode, that's why in the actual program I’ve added some default values (e.g. current year for P_YEAR) in case the validation gets bypassed.
There are some more things you can do with the selection screens (or any screens, for that matter) using the SCREEN structure. For example, by using SCREEN-HIDDEN the input field may be covered with asterisks, like the password field on the logon screen. If you set SCREEN-INTENSIFIED to 1, the field will be displayed in a brighter color. Sadly, the SCREEN-COLOR doesn’t do anything. There is a good reason for it though: each user could have his/her own color theme, so if we started coloring the fields explicitly it would not make much sense.
A good demo of all the SCREEN possibilities is the report DEMO_DYNPRO_MODIFY_SCREEN. You will also find it in the ABAP Examples (in the ABAP Editor go to the menu Environment -> Examples -> ABAP Examples). In fact, there are very many excellent code examples there; I highly recommend exploring that area.
posted by Your Friendly ABAPer @ 19:13, Direct link to this post
1 Comments:
- At 17/8/12 21:39, Mithun Kumar said...
-
This is a nice blog indeed, but somehow was hidden from ABAP beginners to find. I hope google lists this higher than the super-complex code jams that comes up in the search.