This website is not affiliated with, sponsored by, or approved by SAP AG.

0024 - Managing User Input

Moderators: Snowy, thx4allthefish, Rich, ilya

0024 - Managing User Input

Postby Rich » Sat Mar 28, 2009 8:37 am

Managing User Input.

One of the things that all programmers should be worried about is correct input. Input into your program generally defines the results of that program. If it doesn't, then why have any input at all ?

By validating the input into your program you can prevent erroneous results, program crashes and general user dissatisfaction with the system with the program going through it's paces but producing a blank report, but validating input can be time consuming to write. One way round this is to restrict the users input in the first place by using the inbuilt functionality of SAP.

There are various ways around this and can consist of:


Domains.

Domains have been covered in a previous topic, but their use will become apparent in the paragraphs below.

Single Input Parameters.

Single input parameters are used to define a specific value to use in your program whether it be as selection criteria or for some other function within the program. Even here it's possible for users to cause your program to fail in some unexpected way.

Parameters can be declared using the 'LIKE' clause to declare a parameter like(!) a variable that has already been declared in the program, or it can be declared using the 'TYPE' clause typing it to a specific data element. I generally tend to stay away from the 'LIKE' declaration these days as that means the variable (unless it's a dictionary element) the variable is global and I hate global variables with a vengence (even going so far as to write a routine on one project that wiped them out at the start of a function module call!!)

To help the user with the various entries they can enter, there are a few techniques that can be used.

By typing a parameter using a Data Element that you have defined yourself, along with a suitable domain for your data you can validate the value entered by the user and at the same time provide them with a list of valid choices to choose from in a drop down list:

Image

The user see's both the human readable short text and the internal code for that text. By clicking on the required line, the relevant information is transferred back to the parameter field.

Other, more complicated drop down lists can be created using Search Helps. These search helps can have external function modules attached, display more than one field and can also be combined to provide various views of the data to enable the user to select the required parameters.

However, there is a problem here. Within a report program such as this,

Code: Select all
REPORT Z_Inputs
       Message-id 38
       Line-Size  80
       Line-Count 0
       No Standard Page Heading.
*
Parameter p_book type z_Book_Title.

Start-of-selection.


Even though the user can select the correct value from a drop down list, there is nothing at the moment to prevent them from entering whatever data they like into the field and clicking the process button. In other words, you could still end up with a program that crashes or produces nonsensical results.

If however, you try the same thing in a dialog screen you still have the ability to automatically produce a drop down list, but you get an error message issued when the user clicks the process button or hits the enter key stating 'Enter A Valid Value'.

How do you reproduce this behaviour in a report ?

By using the 'AT SELECTION SCREEN' event you can prevent erroneous input parameters from getting passed the input screen:

Code: Select all
Constants: True    type Boolean value 'X',
           False   type Boolean value '-',
           Unknown type Boolean value ' '.
*
Parameter p_book type z_Book_Title.

At Selection-Screen on p_Book.
*
*  Declare these variables as static to prevent database traffic if the
*  user persists in hitting the return key without changing any data...
*
   Statics: w_Book  type z_Book_Title,
            w_Valid type Boolean.
*
   Data:    t_Doma_Values type standard table of Rpy_Dval
                          initial size 0.
*
*  If we've already checked this value on the previous PAI don't bother
*  with this again
*
   If w_book <> p_Book.
      Move True to w_Valid.
      Read Table t_Doma_Values Index 1 transporting No fields.
      If sy-subrc <> 0.
         Call Function 'RPY_DOMAIN_READ'
           Exporting
             Doma_Name               = 'Z_BOOK_TITLE'
           Tables
             Doma_Values             = t_Doma_Values
           Exceptions
             Cancelled               = 1
             Not_Found               = 2
             Permission_Error        = 3
             Illegal_Type            = 4
             Others                  = 5.
         If sy-subrc <> 0.
            Move False to w_Valid.
         EndIf.
      EndIf.
      If sy-subrc = 0.
         Read table t_Doma_Values
              with key domvalue_l = p_Book
              transporting no fields.
         If sy-subrc <> 0.
            Move False to w_Valid.
         EndIf.
      EndIf.
   EndIf.
*
*  Is this a valid selection ?
*
   If w_Valid <> True.
*
*     This could be 'Enter A Valid Value' but it's nice to tell
*     the user what they've done wrong!
*
      Message E000 with p_Book 'Is Not A Valid Book'.
   EndIf.


You would of course use either Text elements or Messages rather than quoted text in a real program to facilitate translation to other languages. Also notice that where I read the Doma_Values table I am not transporting any fields - because we don't need the values we just need to know if it's there.

The last few things about the parameter command that can be used to manage user input are the 'Default' and 'Obligatory' clauses.

Defaults.

In a lot of cases, the user will be entering the same value for a given parameter. In this case it would be nice to provide the user with this field already populated so that they don't have to enter it for the nth time that day.

ABAP provides this ability by the 'DEFAULT' clause to the parameter command:

Code: Select all
Parameter p_book type z_Book_Title default 'A'.


This on it's own will provide a static default placing 'A' in the field when the user runs the program. A better idea would be to use a variable. This variable can then be modified in the initialisation event to provide a default based upon the users location, authorisation settings or a specific memory parameter id.

There is a 'gotcha' here though which means that you cannot use a variable as a default if you modify it's value prior to it's use, you have to move the value to the input parameter directly.

So, we could end up with code something like this, which defaults to the last book title on my bookshelf.

Code: Select all
Parameter p_book type z_Book_Title.
*
Initialization.
*
   Select Title
     into p_Book
     from zMyBooks
     up to 1 rows
     order by title descending.
   EndSelect.


Or this:

Code: Select all
Parameter p_book type z_Book_Title.
*
Initialization.
*
   Get Parameter Id 'ZMYB' field p_Book.


Which sets the parameter to the value assigned to the parameter id. Note that you can also assign a Memory ID directly to a parameter as you define it (Note in the Parameter command you do not use quotes to enclose the memory ID):

Code: Select all
Parameter p_book type z_Book_Title Memory ID ZMYB.


Lastly, with the default clause if you are setting a date, use the SAP internal format YYYYMMDD.

Obligatory

Ie. It's mandatory. SAP makes the user enter a value.

Radiobuttons

Radio buttons are named after the old style buttons you used to find on transistor radios where when you pushed one button in, the button that was already in popped out. These are a familiar feature in nearly every graphic based user interface.

These buttons are used to enable the user to select an option from a group of options, only one of which should be selected at any one time and this makes the programming of these type of options easier than having to program the various logic yourself.

In SAP (as in windows), radio buttons are assigned to a radio button group. Only one button of the group can be selected at any one time and selecting another button deselects the currently selected button of that group. You can have many different groups on the screen at the same time.

Radio buttons are displayed on a report selection screen by using the 'RADIOBUTTON' clause of the 'PARAMETERS' command like so:

Code: Select all
Types: Button type c.
*
Constants: True    type Boolean value 'X',
           False   type Boolean value '-',
           Unknown type Boolean value ' '.
*
Parameters: p_book type z_Book_Title Memory ID ZMYB,
            p_bauth type Button RadioButton Group Inf,
            p_bisbn type Button RadioButton Group Inf.


This results is a screen showing the two radio buttons one ontop of each other:

Image

Generally a radio button is used to denote a processing option, they can however be used to denote various input options as well. As the command applies to the entire button group you should (in fact you can only...) use it on the first occurance of the group.

Code: Select all
Parameters: p_book type z_Book_Title Memory ID ZMYB,
            p_bauth type Button RadioButton Group Inf user-command RAD,
            p_bisbn type Button RadioButton Group Inf.


You'll note that even though this is a 'User Command', pressing the a button does not trigger the 'AT USER-COMMAND.' event, but rather the 'AT SELECTION-SCREEN RADIOBUTTON GROUP' event, and then only if the radio button group has a user command associated with it. Each group that has a user command must have it's own event.

What good is this ??

Well, you can change the display for one thing. You can make fields available for input or not dependant on the state of the radio buttons:

Code: Select all
Parameters: p_book  type z_Book_Title Memory ID ZMYB ,
            p_auth  type z_Author,
            p_isbn  type z_isbn,
            p_bbook type Button RadioButton Group Inf user-command RAD,
            p_bauth type Button RadioButton Group Inf,
            p_bisbn type.
*
Initialization.
*
   Move True to p_Bbook.
*
At Selection-Screen Output.
*
   Loop at Screen.
        Case True.
             When p_Bbook.
                 If Screen-Name = 'P_AUTH' or Screen-Name = 'P_ISBN'.
                    Move '0' to Screen-Input.
                    Modify Screen.
                    Move ' ' to p_Auth.
                    Move ' ' to p_Isbn.
                 EndIf.
             When p_Bauth.
                 If Screen-Name = 'P_BOOK' or Screen-Name = 'P_ISBN'.
                    Move '0' to Screen-Input.
                    Modify Screen.
                    Move ' ' to p_Book.
                    Move ' ' to p_Isbn.
                 EndIf.
             When p_Bisbn.
                 If Screen-Name = 'P_BOOK' or Screen-Name = 'P_AUTH'.
                    Move '0' to Screen-Input.
                    Modify Screen.
                    Move ' ' to p_Book.
                    Move ' ' to p_Auth.
                 EndIf.
        EndCase.
   EndLoop.


When this is initially run, you see the following screen:

Image

However, if the user wishes to search by Author, if they click the Author Radio button, the other two fields are cleared and set to display only, and the only field that you as a programmer then have to worry about validating is the Author field:

Image

By using the 'ACTIVE' field of the screen display you can actually make fields visible or not. The only problem with this is that you also have to handle the titles and any other screen object associated with the input field such as the screens that are displayed for select-options.

You can also make use of the event triggered by the radiobutton to perform various pieces of processing, such as displaying a sub screen for instance:

Code: Select all
At Selection-Screen on Radiobutton Group Inf.
*
   Case True.
        When p_Bbook.
             Call Screen 0200.
        When p_Bauth.
             Call Screen 0100.
        When p_Bisbn.
             Call Screen 0300.
   EndCase.


Check Boxes.

Check boxes are basically the opposite of radio buttons. They allow the user to select multiple options on the input screen and are defined as follows:

Code: Select all
Parameter p_cbox as Checkbox.


In the same manner that you can assign a user command to a radio button, you can do exactly the same with the check box although you can specify a user command value for each checkbox on the screen. Again, for each checkbox to do something you must have an associated AT SELECTION-SCREEN event for that checkbox.

Select Options.

Select Options allow the user to enter either contiguous or discrete ranges with options to either include or exclude the values. The individual fields within a select option behave in the same manner as a standard parameter input with drop down lists available for the user to select specific entries from and so forth.

The code for a screen containing select-options would be something like this:

Code: Select all
Select-Options: s_Book for zMyBooks-Title,
                s_Auth for zMyBooks-Author,
                s_Isbn for zMyBooks-Isbn.
Parameters: p_Auth  type z_Author,
            p_Isbn  type z_isbn,
            p_Bbook type Button RadioButton Group Inf user-command RAD,
            p_Bauth type Button RadioButton Group Inf,
            p_Bisbn type Button RadioButton Group Inf,
            p_cBook as Checkbox User-Command BOOK,
            p_cAuth as Checkbox User-Command AUTH,
            p_cIsbn as CheckBox User-Command ISBN.
*
Initialization.
*
   Move True to p_Bbook.
*
At Selection-Screen Output.
*
   Loop at Screen.
        Case True.
             When p_Bbook.
                 If Screen-Name+0(6) = 'S_AUTH'
                    or Screen-Name+0(6) = 'S_ISBN'.
                       Move '0' to Screen-Input.
                       Modify Screen.
                       Refresh s_Auth.
                       Refresh s_Isbn.
                 EndIf.
             When p_Bauth.
                 If Screen-Name+0(6) = 'S_BOOK'
                    or Screen-Name+0(6) = 'S_ISBN'.
                       Move '0' to Screen-Input.
                       Modify Screen.
                       Refresh s_Book.
                       Refresh s_Isbn.
                 EndIf.
             When p_Bisbn.
                 If Screen-Name+0(6) = 'S_BOOK'
                    or Screen-Name+0(6) = 'S_AUTH'.
                       Move '0' to Screen-Input.
                       Modify Screen.
                       Refresh s_Book.
                       Refresh s_Auth.
                 EndIf.
        EndCase.
   EndLoop.


Note that the Selection-Screen output event has been modified to perform the same actions as it did when using a standard parameter. The main difference being that Select options are tables and the input fields have '-LOW' and '-HIGH' appended to them respectively.

We've all seen a Select Options input screen:

Image

You can restrict the select options screen easily from the main report screen. By using the 'NO-EXTENSION' clause to the you can remove the ability to enter more than one range:

Code: Select all
Select-Options: s_Book for zMyBooks-Title No-Extension,


It achieves this by removing the button that you press to get to the extentions screen.

The other clause, 'NO INTERVALS' removes the second (the 'HIGH' value) field from the select option leaving just a single parameter field. However, by clicking the 'Intervals' button that re-appeared when I replaced 'NO-EXTENSION' with 'NO INTERVALS', you have the ability to enter ranges again.

Within the Select Options extended input screen there is also the ability to include 'Conditions' within a select option:

Image

Whilst this gives the user extreme flexibility in their selections from the database, it can also cause much trouble and strife if the user does not understand what they are actually requesting.


So, what do these options mean and how can they be restricted ?


By selecting one of these options the user can specify not only a range of values using the select option but can also impose conditions within that single value such as that it is less than some value, or not equal to some value.

However, by using function module 'SELECT_OPTIONS_RESTRICT' you can control what options are displayed to the user and what they can select:

Image

This is achieved like so: (courtesy of Dany Charbonneau)

Code: Select all
*
*  Define the object to be passed to the RESTRICTION parameter
*
   DATA Restrict TYPE Sscr_Restrict.
*
*   Auxiliary Objects For Filling RESTRICT
*
   DATA: Optlist TYPE Sscr_Opt_List,
             Ass Type Sscr_Ass.
*
* Restricting The Title Selection To Only EQ And 'BT'.
*
    Optlist-Name = 'OBJECTKEY1'.
    Optlist-Options-Eq = 'X'.
    Optlist-Options-Bt = 'X'.
    APPEND Optlist TO Restrict-Opt_List_Tab.

    Ass-Kind = 'S'.
    Ass-Name = 'S_BOOK'.
    Ass-Sg_Main = 'I'.
    Ass-Sg_Addy = Space.
    Ass-Op_Main = 'OBJECTKEY1'.
    APPEND Ass TO Restrict-Ass_Tab.


    Call Function 'SELECT_OPTIONS_RESTRICT'
      Exporting
        Restriction                  = Restrict
      Exceptions
        Too_Late                     = 1
        Repeated                     = 2
        Selopt_Without_Options       = 3
        Selopt_Without_Signs         = 4
        Invalid_Sign                 = 5
        Empty_Option_List            = 6
        Invalid_Kind                 = 7
        Repeated_Kind_A              = 8
        Others                       = 9.
*


The upshot of this little lot is that by managing the users input and preventing garbage coming in, you can prevent garbage coming out.
Regards

Rich

Image
Abap KC:http://www.richard-harper.me.uk/Kb
SFMDR:http://www.se37.com
Rich
 
Posts: 7112
Joined: Thu Oct 31, 2002 4:47 pm
Location: Liverpool

Return to ABAPers

Who is online

Users browsing this forum: No registered users and 1 guest





loading...


This website is not affiliated with, sponsored by, or approved by SAP AG.