"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" REPORT PERCENT COMPLETE WITH THERMOMETER-LIKE MOVING BAR """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" PRODUCT : R:BASE VERSION : 3.1 CATEGORY : PROGRAMMING SUBCATEGORY : TOOLS """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" From Joe Howard & Bill Driskell When those using your application have to wait, it's a good idea to let them know the computer is working while they wait. This article shows you how to make the wait easier by displaying a moving bar - a bar that lies lengthwise on the screen and fills up as a process moves to completion. It looks like mercury filling up a thermometer tube, only this thermometer is lying on its side and the temperature is the percentage of completion. The bar moves from 0% complete to 100% complete. The visual appeal of the moving bar makes it easier to wait because you know much distance has been covered and how much farther you have to go. You'll find two programs listed below. Use DELAYBAR.CMD to show the expiration of a waiting period and DONE%BAR.CMD to show the percentage of completion in a row-by-row process that uses a DECLARE CURSOR structure. The longer the wait, the slower the bar will fill. Both programs (DELAYBAR.CMD and DONE%BAR.CMD) are included in the .ZIP file (MRIM1091.ZIP) that included this October 1991 issue of Microrim ONLINE. Using & Running DELAYBAR.CMD """""""""""""""""""""""""""" Use DELAYBAR.CMD to show the person using your application the duration of a programmed pause. For example, in a multi-user application, you might need to wait for a resource that's currently locked up by some other workstation. Display a message saying you'll try again in a few moments, and then run DELAYBAR.CMD to show that waiting period being used up. Before running DELAYBAR.CMD, set the INTEGER variable VMAXKNT to a number representing the length of the wait you want. The number is not the number of seconds. It's just a number, so theoretically a 50 on a 386 computer will be faster than a 50 on a 286 computer - given everything else, such as memory and RTVMCONV setting, is the same. Test it to see how long it takes at various VMAXKNT settings on your computer. For example, you might use these commands to run DELAYBAR.CMD: SET ERROR VAR verr LABEL lblname *( ...Code attempts to edit table...) IF verr <> 0 THEN WRITE 'Someone else is using + that table. We'll try again in + a few moments.' PAUSE FOR 1 SET VAR vmaxknt INTEGER = 60 RUN delaybar.cmd GOTO lblname ENDIF DELAYBAR.CMD Listing """""""""""""""""""" *( DELAYBAR.CMD--Moving bar shows) *( percent complete. Before running it) *( Set VMAXKNT to a number.) SET MESSAGES OFF SET ERROR MESSAGES OFF SET BELL OFF DEBUG SET MESSAGES ON DEBUG SET ERROR MESSAGES ON CLS SET VAR vbarknt INTEGER = 0, + vpcent INTEGER, + vline TEXT = (CHAR(205)), + vbarpos INTEGER, + vtop TEXT = (CHAR(201) + + SFIL(.vline,69) + CHAR(187)), + vmaxknt INTEGER + vbottom TEXT = (CHAR(200) + + SFIL(.vline,69) + CHAR(188)), + vside TEXT = (CHAR(186) + + SFIL(' ',69) + CHAR(186)) WRITE .vtop AT 18, 5 black ON cyan WRITE .vside AT 19, 5 black ON cyan WRITE .vside AT 20, 5 black ON cyan WRITE .vside AT 21, 5 black ON cyan WRITE .vbottom AT 22, 5 black ON cyan WRITE '0% done' AT 20, 62 black ON cyan *( Add a shadow.) CLS FROM 19, 76 TO 22, 77 black CLS FROM 23, 7 TO 23, 77 black SET VAR vback TEXT = (CHAR(219)), + vback = (SFIL(.vback,50)) WRITE .vback AT 20, 10 black ON cyan *( Check for too small VMAXKNT.) IF vmaxknt IS NULL OR vmaxknt < 10 THEN SET VAR vmaxknt INTEGER = 10 ENDIF WHILE vbarknt < .vmaxknt THEN SET VAR vbarknt = (.vbarknt + 1), + vpcent = (ANINT(.vbarknt + / .vmaxknt * 100)), vtext TEXT = + (CTXT(.vpcent) + '%' & 'done') WRITE .vtext AT 20, 62 black on cyan SET VAR vbarpos = + (ANINT(.vbarknt / .vmaxknt * 50) + 9), + vbar = (CHAR(176)) IF vmaxknt < 25 THEN SET VAR vbar = (SFIL(.vbar,5)) IF vbarknt <> 1 THEN SET VAR vbarpos = (.vbarpos - 4) ELSE SET VAR vbarpos = 10 ENDIF ELSE IF vmaxknt < 50 THEN SET VAR vbar = (SFIL(.vbar,4)) IF vbarknt <> 1 THEN SET VAR vbarpos = (.vbarpos - 3) ELSE SET VAR vbarpos = 10 ENDIF ENDIF ENDIF IF vbarpos < 10 THEN SET VAR vbarpos = 10 ENDIF WRITE .vbar AT 20, .vbarpos white ON red ENDWHILE CLEAR VAR vbarknt, vpcent, vline, vtop, + vbottom, vside, vback, vtext, vbar, vbarpos RETURN How to Use & Run DONE%BAR """"""""""""""""""""""""" The solution is a little more complex if you want to show a moving bar with a DECLARE CURSOR routine. You need to modify DONE%BAR.CMD (listed below) to fit with each particular DECLARE CURSOR structure, and you need to ensure that you don't attempt to use DONE%BAR.CMD with a routine that writes anything to the screen. You don't want two processes interfering with each other by both writing to the screen. DONE%BAR.CMD can be handy when a DECLARE CURSOR structure doesn't print anything at all or only prints to the printer or a file. For example, you can use DONE%BAR.CMD with a DECLARE CURSOR structure to go row by row through the table to validate data, print form-like reports on the printer, or print invoices. To use DONE%BAR.CMD, modify the starred lines in the code to use your DECLARE CURSOR structure. Then give the new version a unique name like INVOICE.CMD. This code works well in a single-table environment. The moving bar removes the boredom and frustration of waiting. But if you use more than one table, it may not be a good idea. It could take too long to find out what the maximum number of rows is. DONE%BAR.CMD Listing """""""""""""""""""" *( DONE%BAR.CMD--Moving bar shows percent completed.) *( This example code displays a moving bar while printing invoices for) *( each customer in CUSTOMER table in CONCOMP. You will need to) *( change lines marked with asterisks to meet your application,) *( database, table, view, column, and report names.) SET MESSAGES OFF; SET ERROR MESSAGES OFF SET BELL OFF; CLS DEBUG SET MESSAGES ON DEBUG SET ERROR MESSAGES ON CONNECT concomp *(***) DEL invoices.txt *(***) SET VAR vbarknt INTEGER = 0, + vpcent INTEGER, vline TEXT = (CHAR(205)), vbarpos INTEGER, + vtop TEXT = (CHAR(201) + SFIL(.vline,69) + CHAR(187)), + vmaxknt INTEGER, + vbottom TEXT = (CHAR(200) + SFIL(.vline,69) + CHAR(188)), + vside TEXT = (CHAR(186) + SFIL(' ',69) + CHAR(186)) WRITE .vtop AT 18, 5 black ON cyan WRITE .vside AT 19, 5 black ON cyan WRITE .vside AT 20, 5 black ON cyan WRITE .vside AT 21, 5 black ON cyan WRITE .vbottom AT 22, 5 black ON cyan WRITE '0% done' AT 20, 62 black ON cyan *( Add a shadow to the timer box.) CLS FROM 19, 76 TO 22, 77 black CLS FROM 23, 7 TO 23, 77 black SET VAR vback TEXT = (CHAR(219)), vback = (SFIL(.vback,50)) WRITE .vback AT 20, 10 black ON cyan *( Get maximum number of rows. Change following line to meet your) *( application requirements. In this example, an invoice is printed for) *( each customer in the CUSTOMER table, so this command is used:) COMPUTE vmaxknt AS ROWS FROM customer *(***) IF vmaxknt IS NULL OR vmaxknt < 10 THEN SET VAR vmaxknt INTEGER = 10 ENDIF *( Insert code that goes row by row, as does the following:) DECLARE c1 CURSOR FOR SELECT custid FROM customer *(***) OPEN c1 *(***) FETCH c1 INTO vcustid *(***) *( Use the following WHILE instead of WHILE SQLCODE <> 100.) *( Then you don't have to position FETCH right above ENDWHILE.) WHILE vbarknt < .vmaxknt THEN *( Insert commands that will use the FETCH variable values.) *( In this case only CUSTID is fetched. Send to a file or to) *( the printer when using the screen to display a moving bar.) OUTPUT invoices.txt APPEND *(***) PRINT invoice WHERE custid = .vcustid *(***) OUTPUT SCREEN *(***) FETCH c1 INTO vcustid *(***) SET VAR vbarknt = (.vbarknt + 1), + vpcent = (ANINT(.vbarknt / .vmaxknt * 100)), + vtext TEXT = (CTXT(.vpcent) + '%' & 'done') WRITE .vtext AT 20, 62 black on cyan SET VAR vbarpos = (ANINT(.vbarknt / .vmaxknt * 50) + 9), + vbar = (CHAR(176)) IF vmaxknt < 25 THEN SET VAR vbar = (SFIL(.vbar,5)) IF vbarknt <> 1 THEN ; SET VAR vbarpos = (.vbarpos - 4) ELSE ; SET VAR vbarpos = 10 ENDIF ELSE IF vmaxknt < 50 THEN ; SET VAR vbar = (SFIL(.vbar,4)) IF vbarknt <> 1 THEN ; SET VAR vbarpos = (.vbarpos - 3) ELSE SET VAR vbarpos = 10 ENDIF ENDIF ENDIF IF vbarpos < 10 THEN ; SET VAR vbarpos = 10 ; ENDIF WRITE .vbar AT 20, .vbarpos white ON red ENDWHILE CLEAR VAR vbarknt, vpcent, vline, vtop, vbottom, vside, vback, + vtext, vbar, vbarpos RETURN