How To use a progressbar in Dynamics NAV?

Administrator
Member, Moderator, Administrator Posts: 2,506
How To use a progressbar in Dynamics NAV?
http://www.mibuso.com/howtoinfo.asp?FileID=17
Discuss this How To here.
http://www.mibuso.com/howtoinfo.asp?FileID=17
Discuss this How To here.
0
Comments
-
I have a proposal for an advancement:
Instead of actual the progress bar every second it would be better to actual it about 100 times regardless of how long the process durates, because with a fixed intervall of 1 sec, you have the effect for a process that lasts 3 sec that only 33, 67 an 100 % ist displayed as progress. In my opinion the progress bar should work for all processes identically. To accomplish this, one has to calculate just the 100th part of the number of iterations and every time this value is passed, actual the progress bar and set the counter back to zero. Of course you would need two counters, one for the whole progress and the one which is reset to zero whenever actualisation is necessary. In this way the TIME function together with the - 1sec - calculation is avoided which may be more time consuming than just incrementing another int variable...New kits on the blog: https://massivedynamicsblog.wordpress.com0 -
Hi Gerd,
your idea is the way, I do it a long time.
Here is an example:Window.OPEN('Processing data... @1@@@@@@@@@@'); NoOfRecs := MyRecord.COUNT; REPEAT CurrRec += 1; IF NoOfRecs <= 100 THEN Window.UPDATE(1,(CurrRec / NoOfRecs * 10000) DIV 1) ELSE IF CurrRec MOD (NoOfRecs DIV 100) = 0 THEN Window.UPDATE(1,(CurrRec / NoOfRecs * 10000) DIV 1); // Your processing here... UNTIL MyRecord.NEXT = 0; Window.CLOSE;
This way doen't need another variable but an IF-Statement for the case that less than 100 records exists.Timo Lässer
Microsoft Dynamics NAV Developer since 1997
MSDynamics.de - German Microsoft Dynamics Community - member of [clip]0 -
In the beginning, I used that system, but it has some drawbacks:
E.g. you are processing 1.000.000 records and each records takes some amount of time to process, it means that you wont update your dialogbox for a lot of seconds (or minutes) giving the impression that Navision does not react and giving the user the bad idea of killing the Navision session.
With the 1 second rule, even when the progressbar is not moving, the user will see that the session responds to his mouseclicks and will know the session is still working.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
kriki wrote:... it means that you wont update your dialogbox for a lot of seconds (or minutes) giving the impression that Navision does not react...
This is a really good argument for the 1s method.
So in the long run, I think the 1s method is the safest one (though not the fastest one) and should be used throughout, because in the case of a fast process the lack of too few actualisations of the bar is negligible (perhaps the 1s could be changed to 500ms) - in the case of a long lasting process, however, the possibility to cancel at any time (or any second) is by far more import.
Nevertheless I will present here the ultimate progress bar, as far and safe as possible----------------------------- OnPreDataItem --- DiagProgress.OPEN('@1@@@@@@@@@@@@@@@@@@'); // --- evtl. put your code here NoOfRecs := COUNT; NoOfRecsProgress := NoOfRecs DIV 100; Counter := 0; NoOfProgressed := 0; TimeProgress := TIME; ----------------------------- OnAfterGetRecord --- Counter := Counter + 1; IF (Counter >= NoOfRecsProgress) OR (TIME - TimeProgress > 1000) THEN BEGIN NoOfProgressed := NoOfProgressed + Counter; DiagProgress.UPDATE(1,ROUND(NoOfProgressed / NoOfRecs * 10000,1)); Counter := 0; TimeProgress := TIME; END; // --- evtl. put your code here ----------------------------- OnPostDataItem --- // --- evtl. put your code here DiagProgress.CLOSE;
Some Remarks:
The TIME function is called twice, if the progress bar is to be updated - this could be avoided by a further time variable.
In the IF statement always both conditions of the OR expression are evaluated (even if the first one already gives TRUE)...New kits on the blog: https://massivedynamicsblog.wordpress.com0 -
This type of discussion is awesome, I love it when people contribute their ideas, and show how you can do things in more than one way.0
-
I think your ultimate progressbar is a little overkill.
To be honest, when I defined my progressbar a few years ago, I also thought about that system, but like you said, Navision ALWAYS tests both expressions and I wanted a dialogbox that is always useful and not too complex to use. Also when I am looping an internal variable with some calculations on it without any I/O operations. In this case it gets important that the processor can work as fast as possible. Meaning give it as little as possible overhead.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
In some developments I've seen a runtime DivByZero error using the progressbar, due to the lack of control on intProgressTotal variable: I prefer to set it to Count+1 in my code.
...but I'm quite sure that in standard code this situation is always checked! O:)Marco Silvestri0 -
Tohil wrote:In some developments I've seen a runtime DivByZero error using the progressbar, due to the lack of control on intProgressTotal variable: I prefer to set it to Count+1 in my code.
...but I'm quite sure that in standard code this situation is always checked! O:)Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
Then you catch the total number of records and you exit before even starting the loop. Logically, that wouldn't even make sense... if there are no records to process, then you sholdn't even go IN the loop, so you SHOULD never have that error.
In code it would be something like:MyRec.SETFILTER(whatever fields, whatever values IF MyRec.FINDSET THEN BEGIN // prepare the dialog box with the progress bar // initialize variables, one of them would be NoOfProgressed := 0; NoOfRecords := COUNTAPPROX; REPEAT NoOfProgressed += 1; // update progress bar UNTIL NEXT = 0; END;);
So if there are no records in the record var, it simply never executes the progress bar, and you never get divide by 0 errors.0 -
DenSter wrote:Then you catch the total number of records and you exit before even starting the loop. Logically, that wouldn't even make sense... if there are no records to process, then you sholdn't even go IN the loop, so you SHOULD never have that error.
In code it would be something like:MyRec.SETFILTER(whatever fields, whatever values IF MyRec.FINDSET THEN BEGIN // prepare the dialog box with the progress bar // initialize variables, one of them would be NoOfProgressed := 0; NoOfRecords := COUNTAPPROX; REPEAT NoOfProgressed += 1; // update progress bar UNTIL NEXT = 0; END;);
So if there are no records in the record var, it simply never executes the progress bar, and you never get divide by 0 errors.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
My humble suggestion is this (simpler than using the timer):
dWindow.OPEN('Campaigns processed: @1@@@@@@@@@\' +'Pending orders: @2@@@@@@@@@\' +'Posted orders: @3@@@@@@@@@\' +'Credit Memos: @4@@@@@@@@@\' +'Press Esc to abort'); CurrentRecordNo += 1; IF (CurrentRecordNo MOD 500) = 0 THEN dWindow.UPDATE(1,ROUND(CurrentRecordNo / NoOfRecords * 10000,1));
The important part is MOD 500. Set another number if the expected number of records in the table justifies it.
I normally use COUNTAPPROX even though the number can be out of sync. I find that it's not that important in reports.0 -
SEBruhn wrote:My humble suggestion is this (simpler than using the timer):
[code]
dWindow.OPEN('Campaigns processed: @\'
+'Pending orders: @\'
+'Posted orders: @\'
+'Credit Memos: @\'
+'Press Esc to abort');
CurrentRecordNo += 1;
IF (CurrentRecordNo MOD 500) = 0 THEN
dWindow.UPDATE(1,ROUND(CurrentRecordNo / NoOfRecords * 10000,1));
The important part is MOD 500. Set another number if the expected number of records in the table justifies it.
I normally use COUNTAPPROX even though the number can be out of sync. I find that it's not that important in reports.
And you can have 1.000.000 loops going at 1.000 per second and if you have a to low "MOD n", it slows down a lot. You can check it with this:
[code]FOR int := 1 to 1000000000 DO BEGIN
IF (int MOD 500) = 0 THEN
dWindow.UPDATE(1,ROUND(int / 1000000000 * 10000,1));
END;[/code]Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
I love this solution kriki, but i noticed one thing while developing a process for nav 2009 3tiers client.
the opening of the progress bar (obviously, not only with your solution) takes some time, and it is useless when the process takes less than 2 seconds for example...based on the design of the process, and based on how much time does a single loop takes (mine is to read some lines in a table and process them, one line takes about 0.1 secs) we can deny the opening of the dialog box at all.
repeat IF INTProgressCounter = 5 THEN BEGIN DLGProgressDialog.OPEN('#1##############\@2@@@@@@@@@@@@@@@@@@@@@@@@@\',TXTDialogText,INTProgress); END; IF INTProgressCounter > 5 THEN BEGIN IF TMTimeProgress < TIME - 1000 THEN BEGIN //update the dialog box every second TMTimeProgress := TIME; INTProgress := ROUND(INTProgressCounter/INTProgressTotal * 10000,1); DLGProgressDialog.UPDATE; END; END; INTProgressCounter += 1; until condition = true; IF INTProgressCounter > 6 THEN //6 because the counter is increased after the process...viceversa, it would be 5 DLGProgressDialog.CLOSE;
No further variables to add to the original solution0 -
If you know it is fast (less then a few seconds), you can avoid using a progressbar. After all: a progressbar serves only to show the user something is happening.
But if you don't know how much time each loop takes, you can't use your code. If each loop takes 20 seconds and you have only 3 loops to do, the total is 60 seconds, but in your case nothing will be shown.....Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
sure, that's why i specified that the developer must know how much a single loop takes...
in my process, the user selects "n" lines from a list and then process these lines: he can choose 3 or 100 lines...0 -
Just one tip: Instead TIME datatype use the DATATIME, else it will freeze when running over midnight... :-) it is known problem in standard Cost Adjustment batch...0
-
kine wrote:Just one tip: Instead TIME datatype use the DATATIME, else it will freeze when running over midnight... :-) it is known problem in standard Cost Adjustment batch...New kits on the blog: https://massivedynamicsblog.wordpress.com0
-
But only for on hour... :-) and it is more acceptable than each midnight... 8)0
-
I newer was satisfied with standard progress bar behaviour, nor "time" solution so, what about:
IF ((RecNo MOD (TotalRecNo DIV 100)) = 0) THEN Window.UPDATE(1,ROUND(RecNo / TotalRecNo * 10000,1));
no new variables, DIV and MOD are fast enough.0 -
-
As usual, my code fails
If TotalRecNo < 100 this cause division by 0 error
so,IF (TotalRecNo > 100) THEN IF ((RecNo MOD (TotalRecNo DIV 100)) = 0) THEN Window.UPDATE(1,ROUND(RecNo / TotalRecNo * 10000,1));
0 -
Ah, of course, with small number it isn't work very accurate. :-k
If you have a total of 199, the progress bar will go to 50%.
This one is better:IF (RecNo DIV (TotalRecNo / 100)) <> ((RecNo - 1) DIV (TotalRecNo / 100)) THEN Window.UPDATE(1, ROUND(RecNo / TotalRecNo * 10000, 1));
Reijer Molenaar
Object Manager0 -
the progress bar will go to 50%.
It will update the bar 200 times.Reijer Molenaar
Object Manager0 -
Actually, when you got 200 records you do not need to deal with window at all
can't imagine a process which will process 200 records in some time, which can be spotted on UI
Or, if you need to update window - just update unconditionally. All this code make sense if you got big enough number of records.
And you are right, if recordcount is less than 100 my code will not update progressbar at all, if it is between 100 and 199 we will got update for each record, but in all other cases this will be updated only when whole next percent is reached. no, only if record count is more than 999 the progress bar will be updated each percent. Everything below 1000 will be wrong
Apparently, there is no way to make progressbar accurate :) Look your code is accurate enough. Thanks!0 -
How to increase the size of the window dialog box.
Text001 = Generating data for the month of April-2013
When I run the report the dialog box show only Generating data for the.Regards,
Manish0 -
I am using ## for showing in what is going.
But adding more # does not works.Regards,
Manish0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions