""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
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