When you write a report you should as a matter of course validate the input that the user has provided to make sure that the request thay have made is at least sane.

This validation generally takes place in the “AT SELECTION-SCREEN ON parameter” event where if the value in the parameter is incorrect in some way and an error message is displayed the relevant field is highlighted and made ready for input again.  The processing of the report is stopped at that point.

One of the things to check for is that a parameter is populated and this can be done automatically using the ‘OBLIGATORY’ clause of the ‘PARAMETERS’ statement,  however,  when the selection screen is interactive,  this in itself can cause problems.

An interactive selection screen could for example have a series of radio buttons that diefine different aspects of the report,  and selecting a specific radio button means that a specific parameter should be used.  Rather than keep all these other fields visible I tend to put a user-command function on the radio button and then in the AT SELECTION-SCREEN OUTPUT event hide those fields that are not relevant to the current radio button state.  With the ‘OBLIGATORY’ parameter set on other fields this process is interrupted when a mandatory field is not populated leading to incorrect information or fields being displayed.

Also,  I am of the opinion that checks should not happen until the user has made all their entries and have clicked the ‘Online’ button.

Something like this:

At Selection-Screen On p_Matnr.
*
   Data: l_Count Type i.
*
   If sy-UComm = c_Ok_Online.
      If p_Matnr Is Initial.
         Message E018.
      Else.
         Select Count(*)
           Into l_Count
           From Mara
          Where Matnr = p_Matnr And
                LvOrm = Space.
         If sy-Subrc <> 0.
            Message E007 With p_Matnr.
         EndIf.
      EndIf.
   EndIf.

This checks to see if the material number is populated and that it is valid.  If not an error message is issued.

This type of code though has a little ‘Gotcha’.  I don’t know about you,  but If I have to correct an erroneous field,  I make a new entry and then rather than clicking the ‘Online’ button again I hit the ‘Enter’ key.  This then re-validates the fields and processes the report….but hitting the ‘Enter’ key sets sy-ucomm to initial and the validation code is not run.  This means that if I entered an invalid material number again it would not be picked up – as would any other field with an invalid entry.

Now you say “But users would always click the online button” in which case the code would always work,  but I would say “Well – there might be others like myself who do otherwise”.

The fix is simple – keep a copy of the previous function code and if the current code is initial use that instead:

At Selection-Screen On p_Matnr.
*
   Data: l_Count Type i,
         l_UComm Type UiFunc.
*
   If sy-Ucomm Is Not Initial.
      l_UComm = sy-UComm.
   Else.
      l_UComm = g_UComm.
   EndIf.
   If l_UComm = c_Ok_Online.
      If p_Matnr Is Initial.

         g_UComm = sy-UComm.
         Message E018.
      Else.
         Select Count(*)
           Into l_Count
           From Mara
          Where Matnr = p_Matnr And
                LvOrm = Space.
         If sy-Subrc <> 0.
            g_UComm = sy-UComm.

            Message E007 With p_Matnr.
         EndIf.
      EndIf.
   EndIf.

Set the value of g_UComm prior to issuing an error message.

To report this post you need to login first.

10 Comments

You must be Logged on to comment or reply to a post.

  1. Raymond Giuseppi

    Richard, nice example of small code to create more user-friendly transactions at low cost. Nevertheless could you just replace SY-UCOMM with SSCRFIELDS-UCOMM and also check for UCOMM value ‘PRIN’ as for ‘ONLI’.

    (0) 
    1. Richard Harper Post author

      Now that’s another good example of an easy mistake – because I always use reports online rather than printing them directly I didn’t include that function code in my code.

      I use a macro to do these checks so it’s not too painful for me to add them in,  however,  I would question SSCRFIELDS-UCOMM. To my understanding (and if I’m wrong – say so),  you only need to use this structure when you want to check the ok-code returned used when a PAI is generated by a check-box or radio button.  sy-ucomm will always hold the ‘standard’ buttons function code so why (given that you have to also decalre it) if you’re only interested in ONLI and PRIN do you need it ?

      Rich

      (0) 
      1. Raymond Giuseppi

        Once defined with a TABLES statement SSCRFIELDS-UCOMM is always available in SELECTION-SCREEN PAI, when sometimes SY-UCOMM isn’t (CALL SCREEN or tabbed subscreen effects if I remember). So I always use SSCRFIELDS (as OK_CODE for module pool) more serenity.


        In theory SSCRFIELDS is required to set the OK_CODE in program but not “required”, just “suggested” by SAP documentation to read it. So you could consider keeping your macro 😉 and don’t bother on adding a TABLES: SSCRFIELDS with another macro or in default initial code of a report type program.


        During research, review lessons, for the old (3.0) version note, I find this document AT SELECTION-SCREEN, where SAP suggested as me (SSCRFIELDS, ONLI & PRIN 😎 ) but also use of FM RS_SUBMIT_INFO which is also able to identify user who are maintaining a variant for example, so prevent even more unnecessary executions of costly statements


        Regards,

        Raymond

        (0) 
    2. Shai Sinai

      Correct.

      Don’t foregt to check also function code SJOB – “Execute in Background” and maybe also SPOS – “Save As Variant” (Depends on your business requirement).

      (0) 
      1. Richard Harper Post author

        This is what I have ended up with:

        *
        *      For AT SELECTION-SCREEN ON validation checks
        *
        Constants: c_Ok_Onli Type Ui_Func Value ‘ONLI’,
                   c_OK_Prin Type Ui_Func Value ‘PRIN’,
                   c_OK_Subm Type Ui_Func Value ‘SJOB’,
                   c_ok_SVar Type Ui_Func Value ‘SPOS’..
        *
        Define If_Check_Required.
               Data: l_UComm Type UiFunc.
        *
               If syUcomm Is Not Initial.
                  l_UComm = syUComm.
               Else.
                  l_UComm = g_UComm.
               EndIf.
               If l_UComm = c_Ok_Onli
                  or l_UComm = c_Ok_Prin
                     or l_UComm = c_Ok_Subm
                        or l_UComm = c_Ok_SVar.
        End-Of-Definition.

        And then

        At Selection-Screen On p_Matnr.
        *
           Data: l_Count Type i.
        *
           If_Check_Required.
              If p_Matnr Is Initial.
                 g_Ucomm = syUComm.
                 Message E018.
              Else.
                 Select Count(*)
                   Into l_Count
                   From Mara
                  Where Matnr = p_Matnr And
                        LvOrm = Space.
                 If sySubrc <> 0.
                    g_Ucomm = syUComm.
                    Message E007 With p_Matnr.
                 EndIf.
              EndIf.
           EndIf.

        Thanks for your comments

        (0) 
        1. Juwin Pallipat Thomas

          Somehow, whenever my selection screen is so complexly interactive, I prefer to put my validations in Start-of-selection, rather than playing around with the OK codes in At Selection-screen event. Of course, the major functionality that would be lacking with this method will be, positioning cursor on the erred field. Plus point here is, it works with all the variations that are being discussed here – Enter key pressed, Background job, Save as variant etc.

          Comments?

          Example:

              1  report z1.

              2 

              3  tables:marc.

              4  select-options:so_matnr for marc-matnr,

              5                 so_werks for marc-werks.

              6 

              7  start-of-selection.

              8    select count(*)

              9           from mara

             10           where matnr in so_matnr.

             11    if sy-dbcnt is initial.

             12      message ‘Invalid material’ type ‘S’.

             13      stop.

             14    endif.

             15 

             16    select count(*)

             17           from t001w

             18           where werks in so_werks.

             19    if sy-dbcnt is initial.

             20      message ‘Invalid plant’ type ‘S’.

             21      stop.

             22    endif.

          Thanks, Juwin

          (0) 
      2. Raymond Giuseppi

        Usually I don’t either execute the expensive checks for SJOB ok_code, so they will only be executed in the background job. I often also “suggest” users to either input some list of values or execute in background.

        Regards,

        Raymond

        (0) 
  2. Shai Sinai

    Few more tips for better UIX:

    1. Set “mandatory” parameters as recommended:

    AT SELECTION-SCREEN OUTPUT.

      LOOP AT SCREEN.
        IF screenname = ‘P_MATNR’.
          screenrequired = ‘2’.
          MODIFY SCREEN.
        ENDIF.
      ENDLOOP.

    2. Use standard error message:

          MESSAGE e055(00).
          ” Fill in all required entry fields

    3. In case of block (multiple fields), set focus on errornous parameter:

          SET CURSOR FIELD ‘P_MATNR’.

    (0) 

Leave a Reply