Skip to Content
Technical Articles
Author's profile photo Bharat Bajaj

How to run Z program in foreground for long hours without time-out dump

Hello Guys,

Hope you are doing well.

Recently I came across a requirement, when I had to execute a Z program in foreground, which is supposed to run for 3-4 Hours.

Now, you might wonder why would the user run a program for so long in foreground and gaze his eyes on the screen, and not schedule a batch job instead.

Well, this was one of such case, where I had to upload an huge MS access file (which contains multiple tables) using the OLE function in SAP, and apparently the OLE functions works only in the foreground.

Although, as and alternative, I could have uploaded the data files in app server and read the data from there in background, but then I felt the urge to find something for the forground as well.

After some research, I came across this very common yet a Magical FM : SAPGUI_PROGRESS_INDICATOR, which did the whole trick.

Yes, we all frequently use this FM to show the progress bar during a program execution, but probably didn’t know that this FM resets the runtime value to Zero.

Below is the piece of code that I had implemented in my program, which you can utilize as well.

**This is just a sample code for illustration purpose.

REPORT ZTEST_NO_TIMEOUT.

START-OF-SELECTION.
PERFORM process_main.

FORM process_main.

  DATA : l_tab_data  TYPE STANDARD TABLE OF g_typ_data,
		 l_wa_data   LIKE LINE OF 		    l_tab_data,
         l_var_total TYPE i,
         l_var_count TYPE i,
		 l_var_limit TYPE i VALUE '500'.	" Interval for timer reset
  
**Get the Total number of records  
  DESCRIBE TABLE l_tab_data LINES l_var_total.
  
  LOOP AT l_tab_data into l_wa_data.
**Increment the counter  
	l_var_count = l_var_count + 1.	
*{
*Do somthing
*}

**Reset the timer at the inerval
	PERFORM check_and_reset_timer USING l_var_total
										l_var_count							
										l_var_limit.
  ENDLOOP.

ENDFORM.

FORM check_and_reset_timer  USING  i_var_total TYPE i
                                   i_var_count TYPE i
                                   i_var_limit TYPE i.
  DATA : l_var_mod 	TYPE i,
         l_var_perc TYPE i,
         l_var_msg 	TYPE bapi_msg.

  l_var_mod = i_var_count MOD i_var_limit.

  IF l_var_mod = 0.
    l_var_perc = ( i_var_count * 100 ) / i_var_total.

** &1 of &2 Records Processed....
    MESSAGE i002 WITH i_var_count i_var_total INTO l_var_msg.
    CONDENSE l_var_msg.

    PERFORM progress_indicator USING l_var_perc l_var_msg.
  ENDIF.

ENDFORM. 


FORM progress_indicator  USING  i_var_percent
                                i_var_text.

  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
    EXPORTING
      percentage = i_var_percent
      text       = i_var_text
    EXCEPTIONS
      OTHERS     = 1.

ENDFORM.

Hope this code will help you in simiar development for your project.

 

PS :  If you already knew about this, that’s wonderful. But If you didn’t, you can thank me 😉

 

Regards,

Bharat Bajaj

Assigned Tags

      11 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michelle Crapo
      Michelle Crapo

      Guess what?  I knew about the progress indicator.  I've used it to keep people from click over and over on a slower report.

      I did not know it reset the time.  Very cool.  Personally I've never had someone who wants to wait very long.  See the indicator above, usually the click on something too many times.

      And yes, I would have probably uploaded to the server - only because I'm a just in case person.  Just in case a connection breaks.   Of course uploading to the server takes time too.

      Nice - and interesting way of meeting your requirements,

      Michelle

      Author's profile photo Bharat Bajaj
      Bharat Bajaj
      Blog Post Author

      Hi Michelle,

      Yes. Even I have used this only for the progress bar in multiple reports.

      But with the timer reset thing, now my user can run the upload directly with the orignial file right from his desktop. No manual data extraction, manipulation, transformation or application server is involved.

      Ofcourse, the user need to run in foreground, but it saved lot of manual work for him. Just need to press F8 and forget about it. 🙂

      SAP has many hidden gems in it, we just need to explore.

      --

      Bharat

       

      Author's profile photo Michelle Crapo
      Michelle Crapo

      So very true.  Save a lot of work - your user must love you.  Hidden Gems.  Oh boy, are there a lot of those.  I'm just glad that you took the time to blog on one of them!

      Author's profile photo Matthew Billingham
      Matthew Billingham

      I did know about this trick. Even before 2013 https://blogs.sap.com/2013/12/03/progress-bar-avoid-timeout-dump/

      However, to me it is a "code smell"; that there's something wrong with the design, or the program is written so badly it just won't perform* well.

      The alarm bell that rings in my head for this use case is "Why does a huge MSAccess file need to be loaded by a user into a productive system on a regular basis?" (If the answer is "a one of dataload" - then I'd concede, that's fine).

      * Talking of perform, the PERFORM statement is obsolete. Try this:

      REPORT ztest_no_timeout.
      
      CLASS lcl_main DEFINITION.
        PUBLIC SECTION.
          METHODS:
            go.
      
        PRIVATE SECTION.
          types: ty_data type t100.
          CONSTANTS c_var_limit TYPE i VALUE '500'.	" Interval for timer reset
          DATA:
            var_total TYPE i,
            var_count TYPE i.
          METHODS check_and_reset_timer.
          METHODS indicate_progess
            IMPORTING
              i_var_perc TYPE i
              i_var_msg  TYPE csequence.
      
      ENDCLASS.
      
      CLASS lcl_main IMPLEMENTATION.
      
        METHOD go.
          DATA : tab_data TYPE STANDARD TABLE OF ty_data.
      
      **Get the Total number of records
           var_total = lines( tab_data ).
      
          LOOP AT tab_data REFERENCE INTO DATA(data).
      **Increment the counter
            var_count = var_count + 1.
      *{
      *Do somthing
      *}
      
      **Reset the timer at the interval
            check_and_reset_timer( ).
          ENDLOOP.
        ENDMETHOD.
      
        METHOD check_and_reset_timer.
          IF var_count MOD c_var_limit = 0.
            DATA(var_perc) = ( var_count * 100 ) / var_total.
      
      ** &1 of &2 Records Processed....
            MESSAGE i002(s1) WITH var_count var_total INTO DATA(var_msg).
            CONDENSE var_msg.
      
            indicate_progess( i_var_perc = var_perc i_var_msg = var_msg ).
          ENDIF.
        ENDMETHOD.
      
        METHOD indicate_progess.
          CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
            EXPORTING
              percentage = i_var_perc
              text       = i_var_msg
            EXCEPTIONS
              OTHERS     = 1.
      
        ENDMETHOD.
      
      ENDCLASS.
      
      START-OF-SELECTION.
        NEW lcl_main( )->go( ).
      Author's profile photo Michelle Crapo
      Michelle Crapo

      Nice.  Thank you for adding the OOP nice way of doing things.  I try to rarely use performs in my own code.   But they sneak in there sometimes.  Usually when I’m writing a “quick and dirty” program.

      I really like comments when they add to the blog.

      Mmmmm…  A blog from 2013.  I really have to start searching myself prior to putting a blog out there.

      Author's profile photo Matthew Billingham
      Matthew Billingham

      Well, it's not really OOP. Too small for that. Back when blogs were moderated, I used to encourage authors to use modern code in their examples, to get readers used to seeing it.

      I always write my quick and dirty code using classes. Too often it ends up being productive! I encourage others to do likewise - it really doesn't take any time. Especially with Eclipse autocomplete and ctrl-F1.

      Author's profile photo Michelle Crapo
      Michelle Crapo

      I guess I incorrectly call anything with a class OOP.  😉  🙂

      Too true "quick and dirty" - sometimes it ends up being something used more than once.   If I change form into method, it should be easy enough to do.

       

      Author's profile photo Bharat Bajaj
      Bharat Bajaj
      Blog Post Author

      Hi Matthew,

      Thanks for sharing the link to the old post. Didn't really know about it 🙂

      About the *Perform well, completely agree with you.

      The class based coding is always better and more efficient.

      I just wanted to elaborate the logic in a "quick and dirty" way 😉

      Thanks for taking time to replicate my logic in the class-method approach.

      Appreciate it 🙂

       

      Regards,

      Bharat

       

      Author's profile photo Shai Sinai
      Shai Sinai

      P.S.

      There is also a standard (static) class method: CL_PROGRESS_INDICATOR=>PROGRESS_INDICATE which can be used instead of FM.

      Not relevant to this use case, but it supports also background processing.

      Author's profile photo Lars Hvam
      Lars Hvam

      Also note that this will trigger an implicit commit

      Author's profile photo Chris Cameron
      Chris Cameron

      I've used a simple Commit Work to accomplish this in the past, though sparingly.  I look at the Time Out as a good thing that helps protect the system from one or two users consuming too many resources.