>>> "File is in use by another" The message "File is in use by another" results from an attempt to USE a read-only database file with single-user dBASE Administrator. To avoid this situation, use PROTECT to prevent editing of database files rather than making the files read-only. >>> 43-Line Mode Using the Enhanced Graphics Adapter Users of dBASE III PLUS who have the IBM Enhanced Graphics Adapter and Display will notice that this hardware is supported but not documented. If you enter the full-screen configuration SET at the dot prompt and select the Color menu, you will notice that instead of "Color" or "Monochrome," "EColor25" and "EColor43" will be shown. You can toggle between the regular 25-line mode and the IBM Enhanced Graphic Adapter's special 43-line mode by pressing the Return key. Once in the 43-line mode, dBASE III uses all 43 lines of the screen in all display modes. This includes regular display commands such as LIST or DISPLAY, as well as full-screen commands such as APPEND, EDIT, BROWSE, @..SAY, @..GET. Unfortunately, no command in dBASE III PLUS can toggle modes, other than the full-screen SET command. In order to take advantage of this undocumented feature, set the switch settings on the IBM Enhanced Graphic Adapter should be as follows: SWITCHES 1 2 3 4 Off On On Off For more information on using of the IBM Enhanced Graphic Adapter, consult the manual provided with the card. >>> @...GET...PICTURE BY J. MIKE HEDBLOM Issuing @...GET on logical fields produces different displays when READ is executed, depending on the presence of "@L" PICTURE function and the version of dBASE III PLUS. If a logical field has an assigned value, @...GET displays that value. However, if the field has not been assigned a value, in version 1.0, @...GET displays a "?" and @...GET...PICTURE "@L" displays "T." Version 1.1 displays a "?" when the PICTURE function is present, but shows a blank if the PICTURE function is not used. >>> @...SAY & Overstriking It is possible to produce overstriking on a printer with the @...SAY command in dBASE III PLUS. The documentation warns that, after executing SET DEVICE TO PRINT, an @...SAY command with row or column coordinates less than the coordinates of the previous @...SAY will cause a page eject. This is true of row coordinates. However, it is possible to @...SAY at a lesser column coordinate in the same row or even at the same coordinate. For example, the following commands produce underlined output. SET DEVICE TO PRINT @ 10,20 SAY "UNDERLINE" @ 10,20 SAY "_________" SET DEVICE TO SCREEN >>> @...SAY When sending control codes to the printer with @...SAY, control codes are counted as characters by dBASE III PLUS although these characters are not printed by the printer. This causes the print position coordinates for following @...SAY commands to the same line to be offset left by the number of control code characters sent to the printer. For instance, if one control character is sent to row 5, the column coordinate on row 5 will be less by one. @ 5,0 SAY CHR(15) @ 5,12 SAY "Test" will print "Test" starting at column 11. The control codes for the following example are for the C-Itoh 8510A printer. SET DEVICE TO PRINT @ 5,5 SAY CHR(27) + '!' + 'Test' + CHR(27) + '"' ^------^-----------------^------^ |--- Each character takes one space. This prints the word "Test" in boldface and sets the type back to normal. @ 5,50 SAY "Test" <------- Prints at column 46. @ 6,50 SAY "Test" <------- Prints at column 50. >>> @..SAY/GET With SET SCOREBOARD ON, an @...SAY to line 0 in a format file will not write in the scoreboard area, but an @...GET will read from this area. This is consistent with previous versions of dBASE III. However, the larger size of the SCOREBOARD area in dBASE III PLUS increases the likelihood of conflict between SET SCOREBOARD ON and @...SAY...GET. >>> @...PICTURE When you use @...PICTURE with negative numbers, you need a template position for the minus sign. If you don't have one and the number fills the number of template digits you define an overflow will display. Including the "@(" PICTURE function to surround negative values with parentheses also requires a position for the minus sign, although the symbol is not used. The length of the template must be at least the length of the number plus one for the sign. For example, mvar = -100 @ 5,20 SAY mvar PICTURE "999" @ 6,20 SAY mvar PICTURE "@( 999" each display an overflow. However, @ 5,20 SAY mvar PICTURE "9999" @ 6,20 SAY mvar PICTURE "@( 9999" correctly display, "-100" and "(100)," respectively. >>> ACCEPT/WAIT When a function key is SET to a literal character string, the ACCEPT TO command accepts the assigned string, while WAIT TO does not. Instead, the WAIT command takes the decimal ASCII representation of the function key itself. For example, SET FUNCTION 10 TO 'A' WAIT TO mem ACCEPT TO mem1 If F10 is pressed in response to the WAIT and ACCEPT commands, DISPLAY MEMORY shows a graphic character representing the ASCII code of the F10 key in mem and an "A" in mem1. For reference, here are the values stored when these keys are pressed in response to the WAIT command. Key Pressed Value Function =========== ===== ======== F1 0 HELP F2 255 ASSIST F3 254 LIST F4 253 DIR F5 252 DISPLAY STRUCTURE F6 251 DISPLAY STATUS F7 250 DISPLAY MEMORY F8 249 DISPLAY F9 248 APPEND F10 247 EDIT SPACE 32 SPACE BACKSPACE 127 BACKSPACE All other keys that send nondisplay characters (including Alt, control keys, and shifted keypad characters) send an ASCII 0. >>> ACCESS DISK [dBASE III PLUS - Multi-User] Because of a disk manufacturing error in which a unique access code was not recorded on System Disk #1 and System Disk #1 Back-up of dBASE III PLUS, Ashton-Tate implemented an exchange policy for the affected products. The serial numbers of the affected products are 2500001 through 2533960. Copies of dBASE III PLUS with other serial numbers are fully functional and are not affected. The defect involves only local area network use. It does not affect functionality or data integrity of dBASE III PLUS when used in its stand-alone, single-user mode. The problem was created when a special access code that permits dBASE III PLUS to be networked with other copies of dBASE III PLUS was not placed on System Disk #1 and System Disk #1 Back-up. All other disks packaged with the product are not affected. >>> Accessing Filenames with No Extensions In dBASE III PLUS, you can now access and create files with no extensions. To access or create such a file, use the double period (..) in place of the extension. For example, you can access an external file with no extension in the APPEND FROM command. Virtually all dBASE III PLUS commands that operate on files support this capability. The following list of command lines show a number of ways to work with these files. * ---Import a file with no extension. APPEND FROM Yourfile.. SDF * ---Export a file with no extension. COPY TO Yourfile.. SDF * ---Open a database file with no extension. USE Yourfile.. * ---Rename a file with no extension. RENAME Yourfile.. TO Yourfile.TXT Note that DIR does not respect the (..) notation. You must instead use the standard wildcard notation. >>> APPEND FROM Beginning with the Developer's Release of dBASE III, APPEND FROM [DELIMITED] will import delimited files without delimiters. Formerly, delimited files without delimiters would be erroneously APPENDed into the current database file. >>> APPEND FROM DELIMITED APPEND FROM DELIMITED WITH BLANK does not recognize blank fields and left-justifies the APPENDed data. When a blank field is APPENDed, the field is filled with data from the next field in the record. The data in the fields following the blank field are shifted into preceding fields. Leading blanks are removed from all APPENDed data. To illustrate, .LIST Record# Field1 Field2 Field3 1 March March March 2 April April 3 May May May 4 June June June . COPY TO Test TYPE DELIMITED WITH BLANK . ZAP . APPEND FROM Test TYPE DELIMITED WITH BLANK . LIST Record# Field1 Field2 Field3 1 March March March 2 April April 3 May May May 4 June June June In record 2, the data from Field3 shifted to Field2. This occurs in both versions 1.0 and 1.1 of dBASE III PLUS. >>> Applications Generator The Applications Generator does not reset the SET commands it changes to their original values when terminating. This means that subsequent operations affected by the status of any SET commmand could be compromised unless you reset it. Most noticeably, SET SAFETY is changed to OFF. The following is a list of the SET commands the Applications Generator changes and the status when you leave the Applications Generator: Command Setting ------------------- BELL ON CONFIRM ON ESCAPE OFF FIELDS OFF HEADINGS OFF SAFETY OFF STATUS ON TALK ON To workaround this, create a command file that calls the Applications Generator and then resets the current status of all critical SET commands. When you need to run the Applications Generator, DO this command file instead. This occurs in both versions of dBASE III PLUS. >>> ASSIST/RETRIEVE On page L1-24 of the original dBASE III PLUS documentation, ASSIST Retrieve:List:Construct a field list is incorrectly documented as displaying an arrow next to selected fields. An arrow does briefly flash next to the selected fields but does not remain on screen. The documentation also states that fields can be deselected by pressing Return on the previously selected field. Selected fields are dimmed, indicating that they cannot be deselected. >>> ASSIST There is no way to close files from ASSIST. To close files opened in ASSIST, select ASSIST Set Up:Quit dBASE III, or execute a CLEAR ALL or appropriate CLOSE command from the dot prompt after leaving ASSIST. >>> ASSIST and Subdirectories If you are an ASSIST user, you may have found that you cannot change directories in ASSIST. The following program, Subdir.PRG, allows you to provide support for subdirectories by running ASSIST from a menu that includes choices for changing directories. Whenever you want to enter ASSIST, type DO Subdir and choose the directory where you want to work. When you are situated, choose the option for ASSIST and away you go. After you leave ASSIST, you must also quit Subdir by pressing Esc. Subdir then CLOSEs all the DATABASES you may have opened. If you want Subdir to come up automatically whenever you bring up dBASE III PLUS, add the command line COMMAND=DO Subdir; to your Config.DB file. The program operates by selecting subdirectories from the current default directory you boot dBASE III PLUS from. After it loads (this can take some time), you can move forward to all of the subdirectories under the current one and back. You can run ASSIST from any selected subdirectory. Subdir has, in addition, a number of small but significant features. For example, it displays the volume label for the current drive. It has row and column coordinates that may be modified to change the display location of the menu window. It also displays the default directory name, so you always know where you started. There are some limitations to be aware of: 1. Subdir only displays the first 9 subdirectories it encounters, no matter how many there are in the default directory. 2. It does not allow the user to navigate anywhere on the disk. 3. It does not display sub-subdirectories. Program Code * Program ...: Subdir.PRG * Author ....: Stephen Goodman and Olivier Biggerstaff * Date ......: April 1, 1987 * Note(s) ...: Executes a menu that allows you to change your DOS * directories in association with ASSIST. * SET TALK OFF SET BELL OFF SET SAFETY OFF SET TITLE OFF CLEAR * * ---This portion creates a database file to hold the * ---names of the subdirectories in the current directory. @ 12,2 SAY "Reading directory - Please wait" RUN DIR > Sysdir.TXT SET CATALOG TO Sysdir SELECT 10 COPY STRUCTURE EXTENDED TO Tempfile SET CATALOG TO SELECT 1 USE Tempfile ZAP APPEND BLANK REPLACE field_name WITH "Textdata",; field_type WITH "C",; field_len WITH 80 USE CREATE SYSDIR FROM Tempfile APPEND FROM Sysdir.TXT SDF DELETE FILE Tempfile.DBF DELETE FILE Sysdir.TXT DELETE FILE Sysdir.CAT * * ---The drive and volume label are saved to variables. GOTO 2 drive = SUBSTR(Textdata, 18, 1) + ":" title = TRIM("Available Directories" + ; IIF(SUBSTR(Textdata, 23, 1) = " ", "", " for " + ; SUBSTR(Textdata, 23))) * * ---The current directory is the default. GOTO 3 d_default = drive + TRIM(SUBSTR(Textdata, 18)) * * ---Delete all non-subdirectory entries. DELETE FOR SUBSTR(Textdata, 1, 1) = "."; .OR. SUBSTR(Textdata, 14, 5) <> "" PACK * * ---Read the database file into memory variables. dot = .F. GOTO TOP DO WHILE .NOT. EOF() datanum = LTRIM(STR(RECNO())) data&datanum = SUBSTR(Textdata, 1, 8) IF SUBSTR(Textdata, 10, 1) <> " " data&datanum = data&datanum + "." + SUBSTR(Textdata, 10, 3) dot = .T. ENDIF SKIP ENDDO * * ---The maximum number of subdirectories is 9. maximum = LTRIM(STR(MIN(9, RECCOUNT()))) USE DELETE FILE Sysdir.DBF maxlength = LEN(d_default) + 11 + IIF(dot, 0, 4) maxlength = MAX(LEN(title), maxlength) + 6 line = CHR(199) + REPLICATE(CHR(196), maxlength - 2) + CHR(182) default = .T. choice = " " mchoice = " " DO WHILE .T. choice = " " CLEAR row = 6 col = 4 * * ---Draw a double lined box with 2 lines in it. @ row - 2, col - 3 TO VAL(maximum) + 12, maxlength DOUBLE @ row + 1, col - 3 SAY line @ row - 1, col SAY title * * ---If there are no subdirectories, say so. IF maximum = "0" @ row, col SAY "None in "+d_default ELSE @ row + 5, col - 3 SAY line @ row, col - 1 SAY IIF(default, CHR(175), " ") + "Default is " + d_default ENDIF @ row + 2, col SAY "A. Run ASSIST" @ row + 3, col SAY "B. Go to Default" @ row + 4, col SAY "E. Exit" * * ---Display the subdirectory names in the box. datanum = "1" DO WHILE datanum <= maximum @ row + VAL(datanum) + 5, col SAY datanum + ". Directory " + data&datanum datanum = LTRIM(STR(VAL(datanum) + 1)) ENDDO IF .NOT. default .AND. mchoice $ "123456789" @ row + VAL(mchoice) + 5, col - 1 SAY CHR(175) ENDIF @ row + VAL(datanum) + 7, col SAY "Enter selection: " choice = " " mcol = COL() DO WHILE .NOT. (choice $ "ABE" .OR. (choice >= "1" .AND. choice <= maximum)) choice = " " @ row + VAL(datanum) + 7,mcol + 1 GET choice; PICTURE "!" READ ENDDO * * ---Change directory, run ASSIST, or exit to dBASE III PLUS. DO CASE CASE choice = "A" ASSIST CASE choice = "B" CLEAR RUN CD &d_default default = .T. CASE choice = "E" EXIT CASE choice >= "1" .AND. choice <= maximum mchoice = choice CLEAR d_choice = data&choice IF LEN(d_default) = 3 RUN CD \&d_choice ELSE RUN CD &d_default\&d_choice ENDIF default = .F. ENDCASE ENDDO * * ---Close up and return to the default directory. CLEAR CLOSE DATABASES RUN CD &d_default SET TALK ON SET SAFETY ON SET TITLE ON RETURN * EOP Subdir.PRG >>> ASSIST In ASSIST, it is not possible to specify the .NOT. (or FALSE) of a logical field in a search condition. When a logical field is specified as the search condition, ASSIST uses .T. as the search condition. This is true of versions 1.0 and 1.1 of dBASE III PLUS. >>> ASSIST 1. In any of the submenus of the Update, Position, Retrieve, or Organize menus that support the building of search conditions, when building a condition for a date type field, non-date entries are accepted as an argument for the CTOD() function without an error message. In the Developer"s Release and earlier versions this would fail to locate any date field. But since the CTOD() function in dBASE III PLUS converts non-date entries to blank dates, searching for non-date entries on date fields with dBASE III PLUS will position the record pointer at the first blank date encountered. If there are no blank dates in the database file, dBASE III PLUS will not locate any records. 2. With versions of dBASE III greater than 1.1, it is not possible to build a search condition for blank spaces from ASSIST. The Developer"s Release would return the user to ASSIST without comment when this was attempted. dBASE III PLUS will attempt to execute the command. However, when it constructs the command line, blank spaces are excluded. For example, requesting ASSIST to LIST FOR = " " actually executes: LIST FOR = "" Since all conditions are true when compared to a null string, this is identical to: LIST ALL >>> BROWSE The Ctrl-Home and F10 keys behave slightly differently in BROWSE. Both keys call the menu bar to the screen, but only Ctrl-Home removes it. This is true of both versions of dBASE III PLUS. >>> BROWSE BROWSE is extremely slow paging through a database file if the file is indexed and the index contains many identical entries. The wait to move from one page to the next is better measured in minutes than seconds and may appear to have locked the machine. The amount of time necessary is proportional to the amount of records with identical keys in the index file. This occurs in both versions of dBASE III PLUS. >>> BROWSE The status bar is a part of BROWSE and cannot be removed with SET STATUS OFF. The state of the status bar prior to BROWSE is restored when BROWSE is exited. >>> CALL Including the memory variable alias (M->) in the WITH clause of the CALL command returns the error message "Not a character expression." if the data type of the memory variable you pass is numeric. The variable is passed correctly if the M-> alias is not included. Since, however, CALL...WITH assumes a character expression or a memory variable of any type, when you pass a memory variable and a field with the same name exists, dBASE III PLUS always passes the memory variable reference to the WITH clause. This occurs in both versions of dBASE III PLUS. >>> CASE When using the CASE structure to branch control within your command files, there are two distinct behaviors if the either the DO CASE or ENDCASE statements are missing from the construct. 1. If a CASE statement is not preceded by a DO CASE statement, commands following the CASE statement and preceding the ENDCASE statement will not execute. In the following example, the LIST and WAIT commands do not execute but the DISPLAY MEMORY statement does. DO WHILE .T. USE Test CASE LIST <--------| WAIT <--------| Commands do not execute. ENDCASE DISPLAY MEMORY <---------- Command executes. ENDDO 2. A CASE structure without a terminating ENDCASE will terminate execution of a command file and return control to the dot prompt without an error message when the first true CASE statement executes. >>> CHR(0) to Printer BY CHUCK LITZELL dBASE III PLUS is unable to send CHR(0) to the printer. Since dBASE uses CHR(0) internally to mark the end of strings, it processes right up to, but does not include, the CHR(0). This is a problem only if you need to send control codes that include CHR(0) to the printer. Many printers ignore the high bit when processing escape codes. Therefore, sending CHR(128) in place of CHR(0) might work because CHR(128) is the equivalent of CHR(0) with bit seven turned on. If CHR(128) does not produce the desired results with your printer, however, you can use the following DEBUG script to create a .BIN file that will send CHR(0) to your printer. Using a text editor or the dBASE MODIFY FILE command, create a text file, named Prnull.DBG, with the lines that follow. Note the empty line five lines from the bottom; it's important! N PRNULL.BIN A 100 PUSH AX PUSH DX XOR DX, DX MOV AX, 0500 INT 21 POP DX POP AX RETF RCX C W Q To create Prnull.BIN, you must have access to DEBUG.COM, which you will find on your DOS Supplemental Program diskette. Change to the drive and directory in which you want to create Prnull.BIN and enter DEBUG < Prnull.DBG This command will create Prnull.BIN. If you don't get the DOS prompt rather quickly, there is an error in your DEBUG script. Press Return until you see a dash (DEBUG's prompt), and type Q and then press Return to quit DEBUG. When Prnull.BIN has been successfully created you can erase Prnull.DBG. Using Prnull.BIN from within dBASE III PLUS is simple. First LOAD Prnull. Any time you need to print a CHR(0), just CALL Prnull. The following example sets the form length to seven inches on an Epson FX-80 printer. * Set Form Length to 7 inches * on Epson FX-80 printer * (ESC C NUL 7) LOAD Prnull SET PRINT ON SET CONSOLE OFF ?? CHR(27) + "C" CALL Prnull ?? CHR(7) SET PRINT OFF SET CONSOLE ON RELEASE MODULE Prnull >>> CHR() CHR(138) and CHR(141), "" and "" respectively, produce unexpected results when displayed on the screen and cause .PRG files containing these characters to appear corrupted when edited with MODIFY COMMAND. Displaying CHR(138) causes the rest of the characters on that line to be suppressed. CHR(141) displays following characters on the next line. This occurs because dBASE III PLUS interprets CHR(138) and CHR(141) as a linefeed and a carriage return, respectively. The dBASE III PLUS MODIFY COMMAND editor strips off the eighth data bit of all characters except CHR(141) when files are loaded. When CHR(138) is loaded into MODIFY COMMAND, it is transformed into CHR(10). Because CHR(10) is the MODIFY COMMAND end-of-line marker, data after the CHR(138) is not displayed. Executing a program file that formerly contained CHR(138) produces various errors when executed, depending on the command affected. When CHR(141) is loaded into the editor, characters following are displayed on the next line and the line status, on the right side of the screen, reveals that the line is continued. The CHR(141) remains in the file unless it is deleted or overwritten. This occurs in both versions 1.0 and 1.1 of dBASE III PLUS. >>> CLEAR CLEAR is incorrectly documented on page U5-50 of the original documentation as positioning the cursor in the upper left-hand corner of the screen at coordinates 0,0. CLEAR positions the cursor to the lower left-hand corner of the screen at coordinates 24,0 if SET STATUS is OFF, or coordinates 21,0 if SET STATUS is ON. >>> Compaq 386 DOS Running dBASE III PLUS on a Compaq 386 requires Compaq 386 DOS, not standard MS-DOS. To check whether a machine is running Compaq 386 DOS, enter the DOS MODE command at the operating system using the AUTO parameter (a valid parameter of Compaq 386 DOS only). For example, at the operating system, type C> MODE AUTO If the error message "Invalid parameter" is returned, the machine is running the wrong version of DOS. Running the wrong DOS may cause problems with system I/O. >>> CONFIG.DB The Command section of the original Using dBASE III PLUS manual says, "SET STATUS is normally ON." However, STATUS actually defaults to OFF unless STATUS=ON is included in the CONFIG.DB file. The CONFIG.DB file included with the original dBASE III PLUS disks contains the line STATUS=ON. >>> CONFIG.DB Using the keyword COMMAND in the CONFIG.DB or loading dBASE III PLUS with DBASE alters the initial sign on. If this keyword is not included in the CONFIG.DB file and the command DBASE is used to call the program up, dBASE III PLUS will display the license agreement on the screen and immediately present the dot prompt. However, if COMMAND = is included in CONFIG.DB or if dBASE III PLUS is invoked with a command filename on the DOS command line, the sign-on message will remain on the screen for approximately ten seconds or until Return is pressed before executing the command from CONFIG.DB or DOing the specified file. >>> COPY STRUCTURE EXTENDED Sometimes you may want to make a copy of a database file structure without making an exact duplicate as you would with the COPY STRUCTURE command. As a typical situation, you might have database file that is usable, but you think has a corrupted header. You would like to COPY the database file with a new header and not have to recreate the structure by hand. With COPY STRUCTURE EXTENDED, this task can be accomplished quite easily. The following block of code shows just exactly how. * ---Create new file. USE COPY STRUCTURE EXTENDED TO CLOSE DATABASE CREATE FROM * ---COPY old file data to new file. USE APPEND FROM CLOSE DATABASE 1. Description dBASE III PLUS and its predecessors, the Developer's Release, version 1.1, and version 1.0, do not allow you to COPY a DELIMITED file without delimiters and commas separating fields. Using the WITH BLANK option, you can get an text file without delimiters but you also get a text file without commas separating fields. A standard delimited file looks like this: "field1","field2",12,.T. ^ ^ ^ | | | | | ----------- Field separator. ---------------------------- Delimiter that bounds character fields. If the external processor that you are interfacing only supports comma separated text files without delimiters, you can use the following command file to create one. The resulting text file will be in the following form: field1,field2,12,.T. To run this program, type the following command line in a command file or at the dot prompt: DO Cpdelim WITH "","",; "","" The resulting file will have a (.TXT) extension. 2. Program Example * Program ...: Cpdelim.PRG * Author ....: Christopher White * Date ......: May 1, 1986 * Note(s) ...: Program to COPY to a DELIMITED file without delimiters. * PARAMETERS dbf, ndx, condition, txtfile * ---Set environment. SET TALK OFF SET SAFETY OFF * ---Open database file to copy and define the working set of * ---records. filexp = dbf + IIF("" <> TRIM(ndx)," INDEX " + ndx,"") USE &filexp SET FILTER TO &condition GO TOP * ---Create a structure extended file. COPY STRUCTURE EXTENDED TO Temp SELECT B USE Temp * ---Find the last field is that not a memo field. lastrec = RECCOUNT() GO BOTTOM DO WHILE Field_type = "M" .AND. (.NOT. BOF()) lastrec = lastrec - 1 SKIP -1 ENDDO * ---Open output text file. SET ALTERNATE TO &txtfile SET ALTERNATE ON * ---Output records. SELECT A DO WHILE .NOT. EOF() SELECT B GO TOP * ---Output fields. DO WHILE .NOT. EOF() fld_nme = TRIM("A->" + Field_name) DO CASE CASE field_type = "C" * ---Character field. ?? TRIM(&fld_nme) CASE field_type = "D" * ---Date field. ?? STR( YEAR(&fld_nme),4 ) +; RIGHT( STR(100 + MONTH(&fld_nme),3),2 ) +; RIGHT( STR(100 + DAY(&fld_nme),3),2 ) CASE field_type = "N" * ---Numeric field. ?? LTRIM(STR(&fld_nme,Field_len,Field_dec)) CASE field_type = "L" * ---Logical field. ?? &fld_nme ENDCASE * ---Insert field separator. ?? IIF(RECNO() = lastrec,"",",") SKIP ENDDO * ---Insert record separator. ? * ---Get next output record. SELECT A SKIP ENDDO * ---Clean up. CLOSE ALTERNATE CLOSE DATABASES ERASE Temp.DBF RETURN * EOP Cpdelim.PRG >>> CREATE LABEL The correct upper limit for Options:Labels across page is 5, not 15 as documented on pages L6-19 and U5-64 of the dBASE III PLUS documentation. This is corrected in the second edition. Elapsed. PRG * Program ....: Elapsed.PRG * Author .....: Chuck Litzell * Date .......: October 1, 1987 * Version ....: dBASE III Plus * Note(s) ....: Calculates elapsed time between a starting date and time * and an ending date and time. * Returns result in fifth parameter as a character string in * the format HH:MM:SS * * The program is called with the following syntax: * * DO Elapsed WITH sdate, stime, edate, etime, result * * sdate ::= starting date, date expression * stime ::= starting time as HH:MM:SS; * character expression * edate ::= ending date, date expression * etime ::= ending time as HH:MM:SS; * character expression * result ::= character memvar, difference is stored * in this variable as HH:MM:SS * PARAMETERS sdate, stime, edate, etime, result * ---Proportion of a day for an hour, minute and second. hour = 1 / 24 min = hour / 60 sec = min / 60 * ---Get starting date + time in dstart. dstart = sdate + VAL(stime) * hour +; VAL(SUBSTR(stime, AT(":", stime) + 1, 2)) * min +; VAL(RIGHT(stime, 2)) * sec * ---Get ending date + time in dend. dend = edate + VAL(etime) * hour +; VAL(SUBSTR(etime, AT(":", etime) + 1, 2)) * min +; VAL(RIGHT(etime, 2)) * sec timedif = ABS(dend - dstart) result = IIF(dend < dstart, "-", "") rhour = INT(timedif / hour) rmin = INT((timedif - rhour * hour) / min) rsec = ROUND((timedif - rhour * hour - rmin * min) / sec,0) result = result + LTRIM(STR(rhour)) + ":" +; RIGHT(STR(rmin + 100, 3), 2) + ":" +; RIGHT(STR(rsec + 100, 3), 2) RETURN * ---EOP: Elapsed.PRG. Projtime.PRG * Program ....: Projtime.PRG * Author .....: Chuck Litzell * Date .......: October 1, 1987 * Version ....: dBASE III Plus Versions, 1.0 and 1.1 * Note(s) ....: Calculates future date and time by adding a number of * days, hours, minutes and seconds to a given date and time. * * The program is called with the following syntax: * * DO Projtime WITH sdate, stime, days, timex, rdate, rtime * * sdate ::= starting date, date expression * stime ::= starting time as HH:MM:SS; * character expression * days ::= number of days to add * timex ::= time to add expressed as HH:MM:SS; * character expression * rdate ::= date memvar, receives calculated future date * rtime ::= character memvar, receives calculated * future time expressed as HH:MM:SS * * PARAMETERS sdate, stime, days, timex, rdate, rtime * ---Proportion of a day for an hour, minute and second. hour = 1 / 24 min = hour / 60 sec = min / 60 * ---Get starting date and time in dwork. dwork = sdate + VAL(stime) * hour +; VAL(SUBSTR(stime, AT(":", stime) + 1, 2)) * min +; VAL(RIGHT(stime, 2)) * sec * ---Add days and time offset. dwork = dwork + days + ; VAL(timex) * hour +; VAL(SUBSTR(timex, AT(":", timex) + 1, 2)) * min +; VAL(RIGHT(timex, 2)) * sec * ---Store integer portion of ending date in rdate. * ---This construct removes the decimals that have * ---been added to rdate. rdate = CTOD(DTOC(dwork)) * ---Get decimal portion of ending date in twork. twork = dwork - rdate * ---Convert twork to a character string. rhour = INT(twork / hour) rmin = INT((twork - rhour * hour) / min) rsec = ROUND((twork - rhour * hour - rmin * min) / sec, 0) rtime = LTRIM(STR(rhour)) + ":" +; RIGHT(STR(rmin + 100, 3), 2) + ":" +; RIGHT(STR(rsec + 100, 3), 2) RETURN * ---EOP: Projtime.PRG. >>> CREATE FROM The CREATE FROM command is used to create a database file from a database file that contains the target database file structure as records. This a very useful but not well understood aspect of dBASE III PLUS. It can be used as a vehicle for transferring file structures from other processors such as spreadsheets, word processors, and mainframes. As an example, your mainframe consultant could add the target dBASE III database file structure as a delimited file to the download package he sends you. It then would be an easy matter to CREATE the target database file structure FROM the extended structure definition, and then APPEND FROM the downloaded delimited data file. Quite nicely this would free you from knowing or having to CREATE the target database file structure yourself. If this prospect intrigues you, the structure of the delimited extended file must be as follows: Field Field Name Type Width Dec 1 Field_name Character 10 2 Field_type Character 1 3 Field_len Numeric 3 4 Field_dec Numeric 3 ** Total ** 28 Each record of the delimited extended file must have fields equivalent to the one listed above. The file should be a standard delimited file obeying all the rules of the delimited file structure. The following demonstrates what a typical delimited extended file looks like. ---------------- Field name | --------- Data type | | ----- Field length | | | v v v v -- Number of decimal places if numeric "Field_one","C",15 "Field_two","N",10,2 To import this structure into dBASE III PLUS and translate it into a database file structure, perform the following steps. * ---Create mechanism for structure translation. USE COPY STRUCTURE EXTENDED TO Temp USE Temp ZAP * ---Bring the structure to translate into the mechanism. APPEND FROM DELIMITED USE * ---Translate your structure into a database file. CREATE FROM Temp ERASE Temp.DBF >>> CREATE REPORT In CREATE REPORT, the Columns:Decimal places value defaults to the number of decimal places specified by SET DECIMALS TO when SET FIXED is ON; ignoring the number of decimal places specified in the file structure. The documentation for CREATE REPORT incorrectly states that the Columns:Decimal places value defaults to the number of decimal places specified in the file structure. This is true of both versions of dBASE III PLUS. ============================== CTOOLS SECTION >>> Array Save and Restore [cTools Programmers Library] The Graphics Library uses a binary save of an array, unlike The Programmer's Library, which uses a text save. The dBASE Tools for C Incentive Disk allows you to use a text save with The Graphics Library. >>> Linking the Graphics Library [cTools Programmers Library] There have been several requests either to include portions of the Graphics Library in the Programmer's Library at link time or exclude portions of the Graphics Library that require source code. Neither one is possible but you can load both libraries at once as long as you have 640K of memory. >>> Scaling [cTools Programmers Library] The Graphics Library does not currently include parameters to allow manual Y axis scaling (as in Framework II). You can, however, write a dBASE III PLUS using the low-level graphic functions to draw a graph. END CTOOLS SECTION ============================== >>> Date Fields The date data type uses the Gregorian system of timekeeping in that only those centesimal years divisible by 400 are leap years. See the table at right for examples. This is true for every version of dBASE III PLUS. Year Number of Days 2000 366 1900 365 1800 365 1700 365 1600 366 1500 365 >>> Date and Time Calculations BY CHUCK LITZELL dBASE III PLUS stores Date data types differently in memory variables than in database fields. In a database field, dates are stored as eight digits in the format YYYYMMDD. When a date is stored to a memory variable, however, it is stored as a floating point number. The actual value stored is an offset, in days, from a base date. This method of representing dates makes date math possible. Since a date memory variable is a floating point number, it should be possible to store decimals to the date as well as integers. Typing these lines at the dot prompt confirms this: . mdate = DATE() . ? mdate 10/01/87 . mdate = mdate + .5 . ? mdate 10/01/87 . mdate = mdate + .5 . ? mdate 10/02/87 Adding .5 to mdate increments the date by one-half day, or 12 hours. Adding it a second time advances the date to the next day. Applications that need to perform date and time calculations can take advantage of this additional capacity of date memory variables. The procedures, Elapsed.PRG (Figure 1) and Projtime.PRG (Figure 2), demonstrate how times, represented as a fraction of a day, can be combined with date memory variables in calculations. Elapsed calculates the elapsed time between two dates and times, and Projtime calculates the date and time after a given increment to a given date and time. Both procedures accept dates and times as input parameters. Times are represented as character strings in a format similar to the result of the TIME() function, except that the number of hours may be more than two digits. "12:30:15," "1:00:05," and "4521:18:37" are all handled correctly by these procedures. However, "12:5:5," "7:30," and "18:12:5," are not valid. The minutes and days must be two digits, and there must be two colons appropriately positioned within the string. Here's an example of how to use Elapsed: mtime = "" DO Elapsed WITH CTOD("10/01/87"), "12:15:45",; CTOD("12/13/87"), "17:00:00", mtime ? mtime 1756:44:15 and here's an example of how to use Projtime: mdate = CTOD(" / / ") mtime = "" DO Projtime WITH CTOD("12/31/87"), "23:59:59",; 0, "00:00:01", mdate, mtime ? mdate, mtime 01/01/88 0:00:00 >>> dBCODE dBCODE does not trap illegal characters in filenames when encoding command files. Executing a dBCODEd command file that references an illegal filename produces the error message "Unrecognized phrase/keyword in command." [36] or "File does not exist." [1]. >>> .DBF File Header The dBASE III PLUS database file header is one byte shorter than that created by all other versions of dBASE III. Earlier versions put an "extra" byte (00H) between the header and the beginning of the data. dBASE III PLUS no longer includes this byte and the data begins immediately following the last byte of the header (0DH). The number of bytes in the header (bytes 8 and 9) reflect the smaller header size. dBASE III PLUS has no problem reading files from earlier versions as long as bytes 8 and 9 correctly reflect the actual size of the header. This procedure will create a file one byte smaller than the original file: * ---This is a 1.1 created file. USE Test COPY TO Test1 DIR && Test1 is one byte smaller than Test. >>> Demonstration Disk (RunTime+) In the Developer's Release of dBASE III, the dBRUN programs from the Demonstration Disk are not compatible with the full system. Code crunched with DBC.COM from the Demonstration Disk can only be run with dBRUN from the Demonstration Disk. Code crunched with DBC.COM from the Developer's Disk can only be run with the full dBASE III system or the dBRUN disk, purchased separately. The error message: No database is in USE. Enter filename: is a common indicator that the incorrect dBRUN or dBC is being used. >>> DIRECTORY DIRECTORY is an undocumented dBASE III PLUS command that performs identically to the dBASE DIR command. >>> DO dBASE III PLUS allows recursive calls of program files. A program can call a subprogram and that subprogram can call the originating program until too many files are open. For example, * A_prog.PRG * B_prog.PRG DO B_prog DO A_prog A program may also call itself. The following program continues to open files until the "Too many files are open." [6] error message is returned. * Test.PRG DO Test It is possible to do this in all versions of dBASE III PLUS. >>> DO If you SET PROCEDURE TO a file on a drive other than the default, DO requires that the drive designator not be included in the command. The commands SET PROCEDURE TO A:Test DO A:Test1 will cause dBASE III to look for the command file Test1.PRG on drive A:. The proper syntax is SET PROCEDURE TO A:Test DO Test1 This is true for all versions of dBASE III PLUS. >>> DO WHILE In versions of dBASE III earlier than the Developer's Release, the DO WHILE command will stop evaluating it's condition as soon as the expression is complete, ignoring characters beyond that point. This makes it possible for conditions with a seemingly invalid expression to be executed. For example, DO WHILE EOF() = .T. DO WHILE EOF() = .F. both equal DO WHILE EOF() and, DO WHILE .T. = EOF() equals DO WHILE .T. DO WHILE .F. = EOF() equals DO WHILE .F. In the Developer's Release and dBASE III PLUS the above conditions will return the error message, "Invalid operator." >>> Documentation Error 1. Page 5-25 of the Networking section of the dBASE III PLUS Reference Manual shows the following command line. CASE ERROR() = 158 This command is supposed to trap the "File is in use by another" condition. The error number, however, is incorrect and the command line should read: CASE ERROR() = 108 2. There are coding errors on pages 4-18, 5-27, and 5-30 of the Networking section of the dBASE III PLUS Reference Manual. The command line, IF TIME = 250 purports to test if an attempt to lock a database file failed. It is not, however, a reliable coding method and should be changed to IF .NOT. FLOCK() 3. On page 4-18 of the Networking section of the dBASE III PLUS Reference Manual, the command times = 1 should be inserted immediately before the SKIP command. The routine on the following page is an error handling routine executed if SKIP encounters a locked record and expects the variable, times, to be reset each time it is called. 4. On page 5-30 of the Networking section of the dBASE III PLUS Reference Manual, the UNLOCK command should be placed after the READ command. >>> EDIT RECORD In dBASE III versions 1.0 and 1.1, EDIT RECORD and EDIT behave identically. They both enter the full-screen edit mode at the record indicated. PgUp and PgDn take the user to the previous and following records respectively. In the Developer's Release and dBASEIIIPLUS, EDIT acts the same as in version 1.0 and 1.1; however, EDIT RECORD allows editing of the specified record only. PgUp and PgDn return the user to the dot prompt. This is true of both versions of dBASE III PLUS. >>> EOF() When you execute REINDEX or PACK on an indexed database file the the record pointer is positioned to the end-of-file and EOF() returns a true (.T.). By contrast, INDEX ON and PACK position the record pointer to the first record when used on non-indexed database files. This occurs in both versions of dBASE III PLUS. >>> ERROR() The following error messages cannot be trapped by ON ERROR in any version of dBASE III PLUS, although they do return the error number specified. 14 No find. 25 Record not inserted. 39 Numeric overflow (data was lost). 49 File has been deleted. 52 No database in USE. 56 Disk full when writing file: 72 ALTERNATE could not be opened. 73 ^^ Expected ON or OFF. 74 ^--- Truncated. 81 Invalid date. 82 ** Not Found ** 86 ^-- Keyword not found. 89 Cannot erase a file which is open. 113 Index interrupted. Index will be damaged if not completed. 129 Unable to LOCK. 132 Unauthorized login. 144 Unauthorized duplicate. 145 Error in configuration value. 150 Help text not found. The following error message cannot be trapped by ON ERROR in version 1.0 of dBASE III PLUS, but can be trapped in version 1.1. 149 Master catalog is empty. >>> Error Messages The error message "Invalid DIF vector - DBF field mismatch [116]" is undocumented in the original dBASE III PLUS documentation. This error message occurs when APPENDing FROM a DIF file and data in that file conflicts with the DIF header. >>> Error Messages by Number The following is a list of dBASE III PLUS error messages in numeric order. 1 File does not exist. 2 Unassigned file no. 3 File is already open. 4 End-of-file encountered. 5 Record is out of range. 6 Too many files are open. 7 File already exists. 8 Unbalanced parenthesis. 9 Data type mismatch. 10 Syntax error. 11 Invalid function argument. 12 Variable not found. 13 ALIAS not found. 14 No find. 15 Not a dBASE database. 16 *** Unrecognized command verb. 17 Cannot select requested database. 18 Line exceeds maximum of 254 characters. 19 Index file does not match database. 20 Record is not in index. 21 Out of memory variable memory. 22 Out of memory variable slots. 23 Index is too big (100 char maximum). 24 ALIAS name already in use. 25 Record not inserted. 26 Database is not indexed. 27 Not a numeric expression. 28 Too many indices. 29 File is not accessible. 30 Position is off the screen. 31 Invalid function name. 33 Structure invalid. 34 Operation with Memo field invalid. 35 Unterminated string. 36 Unrecognized phrase/keyword in command. 37 Not a Logical expression. 38 Beginning of file encountered. 39 Numeric overflow (data was lost). 41 .DBT file cannot be opened. 42 CONTINUE without LOCATE. 43 Insufficient memory. 44 Cyclic relation. 45 Not a character expression. 46 Illegal value. 47 No fields to process. 48 Field not found. 50 Report file invalid. 51 End of file or error on keyboard input. 52 No database in USE. 53 There are no files of the type requested in this drive or catalog. 54 Label file invalid. 55 Memory Variable file is invalid. 56 Disk full when writing file: 57 ***Execution error on CHR() : Out of range. 58 ***Execution error on LOG() : Zero or negative. 59 ***Execution error on SPACE() : Too large. 60 ***Execution error on SPACE() : Negative. 61 ***Execution error on SQRT() : Negative. 62 ***Execution error on SUBSTR() : Start point out of range. 63 ***Execution error on STR() : Out of range. 65 Internal error : Unknown command code: 66 Internal error : CMDSET(): 67 Internal error : EVAL work area overflow 68 Internal error : Illegal opcode. 70 ** WARNING ** Data will probably be lost. Confirm (Y/N). 72 ALTERNATE could not be opened. 73 ^^ Expected ON or OFF. 74 ^--- Truncated. 75 ^--- Out of range. 76 ***Execution error on - : Concatenation string too large. 77 ***Execution error on + : Concatenation string too large. 78 ***Execution error on ^ or ** : Negative base, fractional exponent. 79 ***Execution error on STORE : String too large. 81 Invalid date. 82 ** Not Found ** 86 ^-- Keyword not found. 87 ***Execution error on NDX() : invalid index number. 88 ***Execution error on REPLICATE() : String too large. 89 Cannot erase a file which is open. 90 Operation with Logical field invalid. 91 File was not LOADed. 92 Unable to load COMMAND.COM. 93 No PARAMETER statement found. 94 Wrong number of parameters. 95 Valid only in programs. 96 Mismatched DO WHILE and ENDDO. 99 Invalid DOS SET option. 101 Not suspended. 102 ***Execution error on STUFF() : String too large 103 DOs nested too deep. 104 Unknown function key. 105 Table is full. 106 Invalid index number. 107 Invalid operator. 108 File is in use by another. 109 Record is in use by another. 110 Exclusive open of file is required. 111 Cannot write to a read-only file. 112 Index expression is too big (220 char maximum). 113 Index interrupted. Index will be deleted if not completed. 114 Index damaged. REINDEX should be done before using data. 115 Invalid DIF File Header. 116 Invalid DIF vector - DBF field mismatch. 117 Invalid DIF Type Indicator. 118 Invalid DIF character. 119 Invalid SYLK File Header. 120 Invalid SYLK Dimension Bounds 121 Invalid SYLK File Format. 122 Data Catalog has not been established. 123 Invalid printer port. 124 Invalid printer redirection. 125 Printer not ready. 126 Printer is either not connected or turned off. 127 Not a valid VIEW file. 128 Unable to SKIP. 129 Unable to LOCK. 130 Record is not locked. 131 Database is encrypted. 132 Unauthorized login. 133 Unauthorized access level. 134 Not a QUERY file. 136 Unsupported path given. 137 Maximum record length exceeded. 138 No fields were found to copy. 139 Cannot JOIN a file with itself. 140 Not a PFS file. 141 Fields list too complicated. 142 Relation record is in use by others. 143 Query not valid for this environment. 146 Maximum path length exceeded. 147 Cannot append in column order. 148 Network server busy. 149 Master catalog is empty. Note also that the following error is not documented. 146 Maximum path length exceeded. >>> "EVAL Work area" Messages The dBASE III PLUS "EVAL work area" is used by any expression in any command that allows any type of expression or condition. Commands that contain a condition or expression invoke the expression evaluator and use the evaluation workarea. The error message "Internal error: EVAL work area overflow" occurs when a command is too complex to be evaluated within the workarea's allocated space. This is true of all versions of dBASE III PLUS. >>> Exclusive .OR. dBASE's .OR. is nonexclusive. In other words, it returns true (.T.) in any case except when both conditions you are comparing are false (.F.). Exclusive .OR. (normally called XOR) returns true (.T.) only if the two conditions you are comparing are different. To XOR two conditions, you can use the following formula (where term_a and term_b represent two logical values): ? (term_a .AND. .NOT. term_b) .OR. (.NOT. term_a .AND. term_b) The following code fragment prints out all the possible values for XOR: x = "(term_a .AND. .NOT. term_b) .OR. (.NOT. term_a .AND. term_b)" term_a = .T. term_b = .T. ? ".T. XOR .T. = " + IIF(&x,".T.",".F.") term_a = .T. term_b = .F. ? ".T. XOR .F. = " + IIF(&x,".T.",".F.") term_a = .F. term_b = .T. ? ".F. XOR .T. = " + IIF(&x,".T.",".F.") term_a = .F. term_b = .F. ? ".F. XOR .F. = " + IIF(&x,".T.",".F.") The printout shows: .T. XOR .T. = .F. .T. XOR .F. = .T. .F. XOR .T. = .T. .F. XOR .F. = .F. >>> "***Execution error on SUBSTR(): Start point out of range." If you are using the SUBSTR() function with memory variables or with an expression whose value might be null or shorter in length than the starting position argument of the SUBSTR() function, you will get the error message "***Execution error on SUBSTR(): Start point out of range." This is not a terminal error condition as is the case with a syntax error. The SUBSTR() function terminates gracefully, returning a null as the result. The execution error, however, does present a problem. If SET CONSOLE is ON and the execution error occurs, the error message will echo to the screen, disturbing your display. If SET PRINT is ON or the substring expression is part of any command that is sending output with the TO PRINT clause, the error message will echo to the printer. This is particularly a problem with REPORT and LABEL FORMs. There are three strategies you can use to suppress the display of the error message. The use of each depends on what commands are being used with the substring expression. 1. If you are assigning memory variables or using @...SAY to send the result of the substring expression to the screen or printer, you can SET CONSOLE OFF to suppress the error message. 2. If you are using a TO PRINT command such as LABEL FORM TO PRINT, use the IIF() function as the starting position expression to return a zero if the length of the character string is less than the start position you really want. SUBSTR() always returns a null string if the starting position is zero. For example, the following expression returns a null string if the length of the memory variable "x" is less than three. SUBSTR(x, IIF(LEN(x) < 3, 0, 3), 6) Use a SUBSTR() with this form to suppress the execution error message. 3. Lastly, you can use ON ERROR to trap execution errors. Define the argument of the ON ERROR condition as a dummy expression such as, ON ERROR dummy = 0 before you execute a command that causes the execution error. Be aware that this approach is limited since you may need the ON ERROR condition for other purposes. In addition, branching to a command file in order to trap a range of error conditions terminates REPORT or LABEL FORMs. >>> EXPORT The error messages produced by EXPORT and their causes are not documented. They are not trapped by ON ERROR. The messages are 1. "Too many @ commands on one page of format file." This error occurs when there are more than 200 @ commands in the format file used for EXPORT. 2. "Format files must be in row major order to be exported." This error occurs if the and/or coordinates have values that are less than previously given coordinates. For example, @ 10,1 SAY 'A' @ 5,1 SAY 'B' 3. "PFS does not allow row numbers higher than 20." Any value higher than 20 produces this error. This is corrected in the second edition of the documentation. >>> EXP() The range of the numeric expression of the EXP() function is between -708.3964185322642 and 709.7827128933841 Values outside this range exceed the numeric accuracy of dBASE III PLUS and produce an internal numeric overflow. For example, using EXP() to evaluate the exponent of the LOG() of a number should return the original value. In the following exmaple, a value outside of the range does return itself. * ---Correct result. ? LOG(EXP(709)) 709.00 * ---Incorrect result. ? LOG(EXP(710)) 11356.52 Evaluating the LOG() of the EXP() of a number below -708.3964185322641 produces the error message "Execution error on LOG() : Zero or negative" [58]. This occurs in both versions of dBASE III PLUS. >>> F1 Key The F1 function key can be used to exit an active @...GET if the @...GET is not within a format file opened with SET FORMAT TO. Changes made prior to pressing F1 are saved as if Ctrl-W were pressed. However, even though F1 exits and saves the data, it does not produce exit-key values that are consistent with other dBASE III PLUS write operations. Write operations always save the data and produce an exit-key value that READKEY() interprets as data changed, regardless of whether data have been altered. When F1 is used to exit a full-screen operation, READKEY() returns either 36 for no change in data or 292 when data have changed. To be consistent, F1 should not produce 36 since it means non-updated data. Pressing F1 in an active screen format moves the cursor to the beginning of the current field without exiting the screen. This occurs in all versions of dBASE III PLUS. >>> File Extensions In Table 1 is a list of default filename extensions created by dBASE III PLUS along with their descriptions and the commands which may be used to create them. Only extensions that remain on disk once dBASE III PLUS has terminated normally are included. Temporary files created, then erased, by dBASE III PLUS are not included. Note that DBC.COM and DBL.COM also create files with .PRG extensions. See the Runtime section of the manual for more information on DBC and DBL. When dCONVERT is used to convert dBASE II files, the old file is renamed with a "B" for the last letter of the extension (.??B.) Following is a list of commands with their descriptions that create a file with no default extension. Command Description EXPORT TO... Creates a PFS TYPE PFS file. MODIFY/CREATE Creates a text FILE file. COPY TO... Creates a TYPE SYLK Multiplan spreadsheet. >>> Floating Dollar Signs dBASE III PLUS does not directly support the display of numbers right-justified with a floating dollar sign. To achieve a floating dollar sign to either print or display numeric data, you can use the following expression. RIGHT(SPACE() + "$" + ; LTRIM(TRANSFORM(, "999,999,999,999.99"), ) This expression can be used wherever dBASE III PLUS accepts the result of a character expression. This includes @...SAY, ??, LABEL and REPORT FORMS. >>> For 256K Machines dBASE III PLUS runs with PC-DOS version 2.xx if you have 256K installed memory in your computer. If you have a minimum of 384K of installed memory, dBASE III PLUS runs with PC-DOS version 3.xx as well as version 2.xx. For 256K operation, two files are provided, CONFI256.SYS and CONFI256.DB, on System Disk #1. These two files set system parameters for maximum overall performance of dBASE III PLUS in a 256K environment. The CONFI256.SYS file contains: FILES = 20 BUFFERS = 4 Copy the CONFI256.SYS file to the root directory of the disk you boot DOS from or the directory set by the DOS COMSPEC command and rename it to CONFIG.SYS. If CONFIG.SYS already exists, modify the file to include FILES = 20 and BUFFERS = 4. The CONFI256.DB file contains: COMMAND = ASSIST STATUS = ON BUCKET = 1 GETS = 35 MVARSIZ = 3 HISTORY = 10 TYPEAHEAD = 10 Copy CONFI256.DB into be placed in the same directory as DBASE.COM and rename it to CONFIG.DB. The CONFI256.DB settings reduce the memory-intensive parameters allowing dBASE III PLUS to work in a 256K environment. The smaller settings place the following limitations on dBASE III PLUS. MVARSIZ is reduced to 3,000 bytes which is half the normal default size of 6,000 bytes. This reduces the amount of space available for memory variables and may cause incompatibilities with programs written with earlier versions of dBASE III. Refer to the SAVE and RESTORE commands for ways to optimize use of memory variable space. BUCKET size is reduced to 1,024 bytes, half the normal default size. This reduces the amount of memory available for the PICTURE and RANGE options of the @...GET command, and may cause incompatibilities with programs written with earlier versions of dBASE III. CREATE SCREEN is limited to one screen, with a maximum of 35 pending GETs. Format files created on machines with more memory may not work when moved to a 256K machine. The limitation of 35 pending GETs may also cause incompatibilities with programs written with earlier versions of dBASE III. The RUN command is not supported on computers with 256K of memory. dBASE III PLUS requires 256K, the RUN command requires additional memory for COMMAND.COM plus the memory required by the external program. This is consistent with earlier versions of dBASE III. The "Insufficient memory" message is an indication that some memory must be released to allow dBASE III PLUS to continue with the operation. When using dBASE III PLUS with 256K RAM this message may result from a combination of factors and varies with the size and number of database files, index files, format files, and the HISTORY and TYPEAHEAD buffer sizes. If the "Insufficient memory" message is received: 1. Ensure that you are using the correct CONFIG.SYS and CONFIG.DB files, as listed above for 256K operation. 2. Close one or more open files and then proceed. Increasing the amount of RAM in your computer will significantly enhance the performance of dBASE III PLUS. >>> GETENV() You can use DOS environmental variables to set and hold locational pointers to various directories for the purpose of installing application systems. Many modern programs are now so large they require the use of subdirectories to control the location of information. In view of this, many use the DOS environmental variable technique to accomplish the needed control. In order to gain the same power with dBASE III PLUS and your programs, use GETENV() to return the contents of environmental variables that each hold a directory pointer for a specific set of files. Remember that GETENV() can return not only system variables that DOS uses, such as PATH or COMSPEC, but also environmental variables that you assign in DOS. You can assign these variables from anywhere in DOS, but many programs that use this directory pointer system initialize the environmental variables in the AUTOEXEC.BAT. This type of a system in dBASE III PLUS would consist of creating three basic classes of files (.PRG, .DBF, and .NDX) with three potential locations. You could, of course, have many more, but these serve the purposes of example. To set this up, you need first to create the environmental variables in DOS with a series SET command lines as follows: SET DB_DIR= SET PRG_DIR= SET NDX_DIR= In the initialization area of your main application program you need to define a series of memory variables using GETENV() that correspond to the DOS environmental variables you have set up. For example, db_dir = GETENV("DB_DIR") prg_dir = GETENV("PRG_DIR") ndx_dir = GETENV("NDX_DIR") Now that you have the directory pointers variables for each class of file, you can use them to either SET the dBASE III PLUS PATH to the list of valid directories or you can them explicitly in file access commands. For example, SET PATH TO &db_dir., &ndx_dir., &prg_dir. or USE &db_dir.\ INDEX &ndx_dir.\ and DO &prg_dir.\ One of the problems you may encounter using this technique is not having enough environment space for your variable definitions. This can happen if, for example, you have a long PATH statement. You can, however, change the size of the DOS environment if you are running under PC/MS-DOS 3.1 and above with the undocumented CONFIG.SYS command SHELL. The general syntax of the SHELL command is as follows: SHELL=C:\ C:\ /P/E: When you wish to use SHELL, place it in your CONFIG.SYS file along with the traditional FILES and BUFFERS settings. To set up the SHELL command line, specify the path to your command processor, the name of your command processor (usually COMMAND.COM), the path again, a space, the /P and /E: switches (no spaces between them) and the number of 16-byte paragraphs to allocate to the environment space. If you do not specify the number of paragraphs, the default is 8 or a total of 128 bytes. If you do specify a /E: setting, the acceptable range is 11 to 63. Be aware that the order and spacing of the SHELL command arguments are vital. Reference: DeVoney, Chris. Using PC DOS. Indianapolis, Indiana: Que Corporation, 1986. pps. 487-488. >>> HELP It is not documented that the HELP command requires a file handle. When HELP is executed, dBASE III PLUS opens the file HELP.DBS. If the maximum number of files (15) are already open, the error message "Too many files are open." [6] is produced when HELP is executed. >>> HELP.DBS There are two HELP.DBS files shipped with dBASE III PLUS version 1.1; one each on System disk #1 and System disk #2. The file on System disk #2 is for dBASE III PLUS single-user systems. The file on System disk #1 is for dBASE III PLUS Administrator. >>> ID.EXE When terminate-and-stay-resident (TSR) programs are loaded and ID.EXE is run, a Ctrl-C may be required at the "Check over your responses. Would you like to re-edit them? (Y/N)." prompt. In one instance, the order in which the TSR programs were loaded affected the outcome of ID.EXE TSR programs should be removed from memory before running ID.EXE >>> IIF() dBASE III PLUS parses the entire IIF() statement before executing the function. If either parameter of the IIF() function is erroneous, then the entire function returns an error. For example, mem = "dBASE" ? IIF(.T., mem, SUBSTR(mem, 10, 3)) returns the error message "***Execution error on SUBSTR() : Start point out of range" even though the false condition is never executed. The IIF() function requires that each argument be a valid expression. This is true for versions 1.0 and 1.1 of dBASE III PLUS. >>> IMPORT IMPORTing a PFS file from a drive other than the default creates the new .DBF, .FMT, and .VUE files on the drive containing the PFS file, not the default drive. This occurs in versions 1.0 and 1.1 of dBASE III PLUS. >>> INDEXing Street Addresses If you have a name and address database file, you might need to INDEX your database file in street order. The basic requirement is to create an index file that keeps all like streets together, and orders the addresses by numeric value within each street. The reason for this is that INDEXing ON the street alone will not give you a very meaningful order. An additional requirement is to assign all blank and "P.O. Box" addresses a value that groups them at the top or bottom of the index so that you can easily skip over them. The following commands use IIF() in combination with other string functions to create an index key that will produce an index file in street order. When you use these commands, enter the assignments to the memory variables "ae" and "af" first, and then enter the INDEX command on one continuous command line. As you type the INDEX command line, be sure to ignore embedded blanks and semicolons within the INDEX expression to keep the expression length less than the 220-character limit that dBASE III PLUS imposes. * ---INDEXing street names. ae = [SUBSTR(Street, 1, AT(" ",Street) - 1)] af = [SUBSTR(Street, AT(" ",Street) + 1, 5)] INDEX ON IIF( "BOX" $ &ae.; .OR. "P.O." $ &ae.; .OR. LEN(TRIM(Street)) = 0,; " ",; &af. + RIGHT(STR(100000 + VAL(&ae),6),5); ); TO Address >>> INDEX File Size To calculate the size of a dBASE III PLUS index file created with INDEX or REINDEX, use the following program, Ndxsize.PRG. The variable, keyexplen, refers to the length of the index file's key expression and must be provided. Keyexplen is 8 when using numeric or date type keys and is rounded up to the nearest multiple of four on character type keys. To execute Ndxsize, use the following general syntax: USE klen = ret_val = 0 DO Ndxsize WITH klen, ret_val * Program ...: Ndxsize.PRG * Author ....: Paul Redmond * Date ......: January 1, 1987 * Note(s) ...: Calculates the optimal size of an index file after * an INDEX or REINDEX. * PARAMETERS keyexplen, answer PRIVATE ALL blkkeycnt = INT(504 / (keyexplen + 8)) blkleft = RECCOUNT() / blkkeycnt blkcnt = blkleft + 2 blkkeycnt = blkkeycnt + 1 DO WHILE blkleft > blkkeycnt blkleft = INT((blkleft - 1) / blkkeycnt) + 1 blkcnt = blkcnt + blkleft ENDDO answer = blkcnt * 512 * EOP Ndxsize.PRG Note that the size of the index file changes if an APPEND is used with an indexed database file. INDEX and REINDEX optimize the index file; this formula approximates the optimum index file size. This algorithm is relevant to both versions 1.0 and 1.1 of dBASE III PLUS. >>> INKEY() The list of alternate keys on pages U6-29 [Original] and U6-41 [Revised 6/86] is incomplete. Alternate keys not documented are: Special Key Alternate Key ------------------------------- Rightarrow | Alt-<4> Leftarrow | Alt-R Uparrow | Alt-<5> Dnarrow | Alt-O Ctrl-Rightarrow | Alt-<2> Ins | Alt-U Del | Alt-<7> Home | Alt-<1> End | Alt-<6> PgDn | Ctrl-@, Alt-<3> Ctrl-End | Alt-I Esc | Ctrl-[ Ctrl-PgUp | Alt-S Ctrl-PgDn | Alt-A F1 | Ctrl-\ Numbers enclosed in <> denote keys on the numeric keypad only. All keys can be duplicated by entering their ASCII key codes on the numeric keypad while holding down the Alt key. Though this list is included in the documentation under INKEY(), the alternate keys are applicable throughout dBASE III PLUS. For example, in BROWSE Ctrl-\ toggles the cursor control keys menu instead of invoking HELP, as F1 does. Ctrl-Q is incorrectly documented as the alternate key for Esc; Ctrl-[ is the alternate key for Esc. In data-entry screens Ctrl-Q and Esc act the same in that they both abort the entry screen without writing the changes. However, during LIST or DISPLAY Ctrl-Q resumes scrolling after Ctrl-S has paused the output. Esc aborts the operation entirely. INKEY() returns 27 for Esc and Ctrl-[, while Ctrl-Q returns 17. >>> INKEY() 1. The INKEY() function in the Developer's Release and dBASE III PLUS seems to return the wrong answer after a WAIT command has been executed. For example, WAIT i = INKEY() ? i The memory variable "i" will always contain the value zero no matter what key was last pressed. The reason for this is that WAIT pauses and waits for a key value from the keyboard or type-ahead buffer. Once the key is sensed, it is taken from the buffer. The INKEY() function also looks at this buffer for a key, but finds that the last key has been taken by the WAIT command and so returns a zero value. The correct method to poll the keyboard for a key press is to use either the WAIT command or the INKEY() function but not both in combination. For example, * ---Use the WAIT command. WAIT TO choice DO CASE CASE choice = 19 ... CASE choice = 27 ... ENDCASE ---Use the INKEY() function. key = INKEY() DO WHILE key = 0 key = INKEY() ENDDO DO CASE CASE key = 19 ... CASE key = 27 ... ENDCASE 2. The following program can be used to help you determine the key code for each key pressed. SET ESCAPE OFF SET TALK OFF esc = 27 DO WHILE .T. key = INKEY() DO WHILE key = 0 key = INKEY() ENDDO ? key IF key = esc EXIT ENDIF ENDDO SET TALK ON SET ESCAPE ON RETURN >>> INKEY() INKEY() returns the following codes for function keys: Key Normal Ctrl Alt =============================== F1 28 94 104 F2 -1 95 105 F3 -2 96 106 F4 -3 97 107 F5 -4 98 108 F6 -5 99 109 F7 -6 100 110 F8 -7 101 111 F9 -8 102 112 F10 -9 103 113 >>> INPUT The INPUT command behaves differently in different versions of dBASE III. In versions 1.0 and 1.1, it accepts a carriage return as a valid response and does not create a variable. If one exists, it is left intact. Control is then returned to the calling program or the dot prompt. In the Developer's Release and dBASE III PLUS, however, INPUT does not accept a carriage return as a valid response. It scrolls the screen up one line and awaits valid input each time a carriage return is entered and control is not returned to the calling program or dot prompt until a valid input is accepted. >>> INSTALL.BAT The files required to run dBASE III PLUS version 1.1 are not documented. They are: DBASE.EXE DBASE.OVL DBASEINL.OVL DBASE.MSG CONFIG.SYS (In the root directory of the boot disk.) Additional files needed by dBASE III PLUS (version 1.1) to function fully but not required to load are: HELP.DBS ASSIST.HLP CONFIG.DB >>> Interactive Mode In dBASE III PLUS, you cannot continue command lines issued at the dot prompt with a semicolon. Previous versions supported this feature. To continue a line beyond the width of the screen keep typing and the command will scroll left. In dBASE III PLUS, the command line is an editable 254 character, single line, horizontal scroll space. All keys that are valid in full-screen modes are valid at command line. >>> Justifying and Centering Strings BY CHUCK LITZELL Frequently, there is a need to center or right justify a message on the screen or in a report. The usual method is to add to the left of the string the number of spaces required to offset the message to the desired position. The dBASE III PLUS code to accomplish this is short, though somewhat complicated owing to the mathematics involved. Use this expression to center a string: string = IIF(width > LEN(string),; SPACE((width - LEN(string)) / 2),; "") + string To right justify a string, use string = IIF(width > LEN(string),; SPACE(width - LEN(string)),; "") + string` Often, reports and screen displays have headings that include a left-justified string, a centered string, and a right-justified string. Title.PRG (Figure 1) is a procedure that builds such a heading. The three strings are passed as parameters, along with the width of the desired heading. The resulting string is returned in the first parameter. * Program ...: Title.PRG * Versions ..: dBASE III PLUS v1.0, 1.1 * Note(s) ...: Generates a report or screen title line with text * left justified, centered and right justified. * The result is returned in the first parameter, ltext. * * The calling program must ensure that the width * specified is sufficient to contain the three * strings without overlap. No error will result * if there is overlap, but the result string will be * erroneous. * * Example: * pagen = 1 * header = DTOC(DATE()) * DO Title WITH header, "Employee Master Report",; * "Page " + LTRIM(STR(pagen)), 80 * @ 1, 0 SAY header * PARAMETERS ltext, ctext, rtext, width * * ltext ::= text to be left justified. * ctext ::= text to be centered. * rtext ::= text to be right justified. * width ::= width of output string. * tmpstr = RIGHT(SPACE(width) + TRIM(rtext), width) tmpstr = STUFF(tmpstr, (width - LEN(TRIM(RTRIM(ctext)))) / 2,; LEN(TRIM(RTRIM(ctext))), TRIM(RTRIM(ctext))) ltext = STUFF(tmpstr, 1, LEN(TRIM(RTRIM(ltext))), TRIM(RTRIM(ltext))) RETURN * EOP Title.PRG >>> LIST The LIST command is designed to display "Record in use by another" if a record is locked by a different workstation with RLOCK(). This performs according to expectation unless record number 1 is locked with RLOCK(), in which case blank data is displayed for the record. There is no work-around for this situation. >>> LIST PROCEDURE Often, when you are modifying an existing application where you have merged a number of command files into a procedure file, you may want to get a list of procedures. You can do this easily using the DOS utility, FIND.EXE. FIND is a very fast, free text-search program that searches for a specified string anywhere in a file, returning the lines where the search argument is found. Optionally, FIND will return line numbers as well. Unfortunately, searches are case-sensitive and case is not a configurable option. You can, however, use this to your advantage by making the use of the command verb PROCEDURE always uppercase and any other uses in comments and in the SET and CLOSE PROCEDURE commands some combination of case and word length to make the PROCEDURE declaration unique. To list procedures from the DOS prompt use the following command line, FIND "PROCEDURE" You can, off course, RUN this command line from within dBASE III PLUS or you can create a command file that calls FIND and constructs the FIND command like the following, PROCEDURE Proc_file RUN FIND "PROCEDURE" &Proc_file..PRG RETURN If you want to include line numbers in the listing add /N to the FIND command line. >>> LOAD The explanation of "Table is full" (Using, pages 5-121 and 8-15) states that you have attempted to LOAD more than five files. It actually occurs if you try to LOAD more than 16 files. Five files was the limitation of the Developer's Release. This is corrected in the second edition of the documentation. >>> LOCATE/CONTINUE To use CONTINUE, a search or scope condition must be specified in the preceding LOCATE command, although a LOCATE without a FOR or WHILE condition does not cause an error and positions the record pointer at the top of the file. However, following that LOCATE with CONTINUE returns the error message "CONTINUE without LOCATE". ASSIST does not prevent users from selecting Continue in this way. In ASSIST, executing Position:Locate with no condition positions the record pointer at the top of the file and activates Position:Continue. Choosing Position:Continue returns the error message "CONTINUE without LOCATE." This occurs in versions 1.0 and 1.1 of dBASE III PLUS. >>> LOOP The command verb LOOP does not appear in the second edition documentation index. An explanation of LOOP can be found on page U5-114 under the DO WHILE command. >>> MENUBAR.BIN The documentation for MENUBAR.BIN in the dBASE Programmer's Utilities states that the light bar can be moved within the menu with the eight cursor-movement keys and that Return and Esc are used to select items from the menu. However, it is not documented that the cursor-movement keys can be used to select items, as well as navigate through the menu. When Ctrl is used in conjunction with a cursor key, the item under the cursor is selected and the menu is exited without moving the cursor. These keys and their functions are shown in Table 2. The key code returned by MENUBAR corresponds to the INKEY() key codes. Extension Description Commands BAK Backup MODIFY COMMAND MODIFY STRUCTURE CAT Catalog CREATE CATALOG SET CATALOG TO DBF Database file COPY STRUCTURE TO COPY TO COPY...STRUCTURE EXTENDED CREATE CREATE FROM IMPORT JOIN TOTAL SORT DBT Memo field file CREATE MODIFY STRUCTURE COPY TO DIF VisiCalc file COPY TO...TYPE DIF FMT Format file CREATE SCREEN IMPORT FRM Report design file CREATE REPORT LBL Label design file CREATE LABEL MEM Memory variable file SAVE NDX Index file INDEX PRG Program, procedure MODIFY COMMAND QRY Query file CREATE QUERY SCR Screen design file CREATE SCREEN TBK Memo file backup MODIFY STRUCTURE TXT Text file COPY TO...TYPE DELIMITED COPY TO...TYPE SDF CREATE SCREEN (text image) SET ALTERNATE TO FILE WKS Lotus 1-2-3 file COPY TO...TYPE WKS VUE View file CREATE VIEW IMPORT >>> MODIFY STRUCTURE 1. MODIFY STRUCTURE generates the error "NET 803: Network path not found" if the database file is in the root directory of any physical drive or logical drive. Even if network drive F: is attached to the subdirectory \DBASE on the file server, it is still belongs to the logical root directory of drive F:. The work-around is to move the file to a subdirectory or COPY TO Temp MODIFY STRUCTURE After receiving the "NET 803" error message, the user must press A to abort. The database file structure will have been modified but zero records will remain in file, then APPEND FROM Temp 2. MODIFY STRUCTURE generates the error "File is already open" if the database structure contains a memo field and there are no records in the file. The work-around is to add one blank record to file. >>> Precedence of File Attributes Page 3-24 of the Networking section of the dBASE III PLUS Reference Manual states that "File and field privileges can be used to override the file access read/write attribute established at the operating system or network shell level." This is incorrect. Attributes of directories and files established at the network level always have precedence over the dBASE Administrator Protect mechanism. >>> Printing dBASE III PLUS handles printing differently from earlier versions of dBASE III. Earlier versions of dBASE III relied on DOS to handle printer status errors. All error messages were generated and handled by DOS. dBASE III PLUS uses a different DOS call to send characters to the printer port. This new routine is faster but also returns a printer port time-out error quicker. dBASE III PLUS checks the port status at initialization; errors occurring after initialization are handled by DOS. Because of these differences, it is possible to get error messages in dBASE III PLUS when none would not occur in dBASE III. The differences are: 1. When the print device is activated, dBASE III PLUS checks the printer port for two specific conditions: "Invalid printer port" and "Printer is either not connected or turned off." If neither condition is true but an error is still detected, dBASE III PLUS defaults to the "Printer not ready" error message. For example, on a parallel printer, pin 12 is used to signal a "paper out" condition. If pin 12 is missing or broken on a cable, dBASE III PLUS checks the status of the printer port, finds an error condition that does not meet one of the two specific conditions that are tested, and returns the default error message, "Printer not ready." "Invalid printer port" occurs when redirecting the printer to an invalid port, such as LPT4. "Printer is either not connected or turned off" may occur when redirecting the printer to a valid COM port and attempting to print when that port does not have a printer attached to it. 2. Because different DOS versions have different time-out intervals for the printer port, some DOS versions time out while waiting for the print buffer to empty. This will generate the DOS error message "Printer not ready. Retry? (Y/N)." This situation can be corrected by issuing the DOS command MODE LPT1:,,P The "P" parameter at the end of the command line above instructs DOS to infinitely retry the printer port. This prevents the port from timing out. Error conditions (such as paper out or printer not connected) may appear to hang the machine while DOS infinitely retries the port. Unless the error condition is resolved, a warm boot is required to terminate the process. >>> READKEY() If you terminate a full-screen operation in dBASE III PLUS with a Ctrl-W or Ctrl-End, READKEY() always returns 270, regardless of whether the contents were altered or not. In the Developer's Release, READKEY() returned a value of 14 if the field or variable was not changed. Additionally, READKEY() always returns a value of 12 when you terminate a full-screen operation with Esc or Ctrl-Q. >>> RENAME The RENAME command can move files between directories on the same disk drive. When the new filename includes a path different from the original filename, RENAME moves the file to the directory specified by the new path. For example, RENAME \DBASE\Test.TXT TO \DOS\Test.TXT Test.TXT is moved from \DBASE to \DOS, provided that the directory \DOS exists on the same disk drive. When renaming a file in a directory other than the default, the path of the destination filename is required. If the destination path is ignored, dBASE III PLUS moves the file to the default directory. When the destination drive is different from the source drive, dBASE III PLUS returns the error message "File already exists." [7]. This is inconsistent with DOS, which renames files without moving them. The error message "Invalid parameter" is produced when a destination path is included in the DOS RENAME command. >>> REPLACE REPLACEing a field of a database file from another work area when the record pointer is at EOF() increments the record counter and appends a record to the file when the record pointer is moved to the new record. For example, USE Test1 GO BOTTOM SKIP && Sets EOF() true. SELECT B USE Test2 REPLACE Test1->Name WITH "XXXX" SELECT A GO RECNO() adds a new record to Test1 and the contents of Name are "XXXX". Issuing multiple REPLACEs to a database file when EOF() is true increments the record counter for each REPLACE executed; however, data is added to the current record only. Do not trust this method for appending records. This process occurs because the record counter is increased; but, the original data on the disk is not erased in the fields REPLACEd. This means that the information on the disk in the region of the new record becomes part of that record. When the data on the disk is from a previously DELETEd and PACKed record, the new record is marked for deletion. Other characters such as nulls and end-of-file markers can become embedded in the record. This will corrupt the database file and cause unpredictable results. When the field REPLACEd is an index key field, the results are slightly different. Performing a SEEK or FIND on the new expression returns the error message "No find" until REINDEX is issued. Multiple REPLACEs to the EOF() add only the last expression REPLACEd after REINDEX is issued, all other data is lost. DISPLAY STRUCTURE, GO BOTTOM, and RECCOUNT() reveal a record count consistent with the number of REPLACEs executed. COUNT displays the number of records added previously to the REPLACE command until REINDEX is issued. Attempting to GO/GOTO the new records produces the error message "Record is out of range" [5]. SKIP moves the record pointer through these records as if they were available. To reset the database file record count after multiple REPLACEs, issue PACK. This occurs in both versions of dBASE III PLUS. Key Function Return Select the item under the light bar. Esc Select the item under the light bar. Home Move the light bar to the first column, first row. PgUp Move the light bar to the first column, last row. End Move the light bar to the last column, first row. PgDn Move the light bar to the last column, last row. Ctrl-Home Select the item under the light bar. Ctrl-PgUp Select the item under the light bar. Ctrl-End Select the item under the light bar. Ctrl-PgDn Select the item under the light bar. >>> REPLACE In addition to the ability to change the contents of fields in work areas other than the currently selected one by creating a global field pool with SET FIELDS TO and then REPLACEing into the remote area, you can also REPLACE into the remote area by specifying the alias before the target field name. For example, * ---REPLACE with SET FIELDS. SELECT 1 USE Fileone SELECT 2 USE Filetwo SET FIELDS TO Fileone->Fieldone, Fieldtwo REPLACE Fieldone WITH Fieldtwo * ---REPLACE without a fields list. SELECT 1 USE Fileone SELECT 2 USE Filetwo REPLACE Fileone->Fieldone WITH Fieldtwo >>> REPLICATE() Once the error message "Execution error on REPLICATE(): String too large." [88] is produced, it does not reoccur until a valid numeric expression is included in REPLICATE(). For example, * ---The next line produces the error. mvar = REPLICATE("A",32766) * ---In the next line no error is produced. mvar = REPLICATE("A",32767) mvar = REPLICATE("A",10) * ---The next line produces the error. mvar = REPLICATE("A",32767) The result of REPLICATE() is a null string whenever the second argument is too large, regardless of whether an error message is returned. This is true of versions 1.0 and 1.1 of dBASE III PLUS. >>> REPORT FORM CREATE REPORT Options:Double space report causes double spacing between records only. All other portions of the REPORT FORM, including wrapped fields, are single spaced. This is true of both versions of dBASE III PLUS. >>> REPORT FORM In both versions 1.0 and 1.1 of dBASE III PLUS, the width of a REPORT FORM total is determined by the value of Contents:Column width. There are several conditions to consider: 1. With a total width greater than the Contents:Column width, the decimal portion of the total is truncated to accommodate the integer portion. 2. When the integer portion of the total exceeds the Contents:Column width, the total displays in scientific notation. 3. If the value of the total is greater than 9E+98, an overflow displays. >>> REPORT FORM (Memo Fields) If you plan to print a memo field from another work area in a REPORT FORM, including the alias as a part of the memo field name will not display the memo field information when you execute the REPORT FORM. You must instead include a SET FIELDS TO command before you CREATE REPORT and not include the memo field alias name in Columns:Field contents. If you select the memo field from the field list displayed by F10, delete the automatically inserted alias before you exit the Column:Fields contents. When you are ready to run your report, be sure to SET FIELDS TO the list of fields you are using first or you will get the error message "Syntax error in field expression" when you execute the REPORT FORM. In the following exmaple, Test1.DBF contains the memo field Notes. * ---CREATE a REPORT to printing memo fields from a * ---nonactive work area. SELECT 2 USE Test1 INDEX Test1 SELECT 1 USE Test2 SET FIELDS TO Name, Address, Test1->Notes CREATE REPORT Test1 In Columns:Field contents enter Notes and do not include the alias name. This situation occurs in both versions of dBASE III PLUS. >>> REPORT FORM PLAIN The following are some undocumented notes on REPORT FORM PLAIN. These situations arise in both versions 1.0 and 1.1 of dBASE III PLUS. 1. Selecting PLAIN always reserves the first two lines of the first page of the report for a heading, even when the headings are blank. 2. Setting the Options:Lines per page equal to the printer form length causes alternate blank pages to be printed when the report is run. This happens because a form feed, CHR(12), is printed at the end of each page. When Options:Lines per page equals the form length, the CHR(12) is printed at the top of each new page causing a blank to be printed between printed pages. 3. Setting Options:Lines per page equal to one less than the form length prints a blank row between pages. This occurs because the CHR(12) is printed at the beginning of the last line on a page, skipping that line. >>> REPORT FORM TO PRINT To imbed printer control characters in Options:Page title, Group: headings, or Column:Heading, enter the control characters from the numeric keypad with an Alt- and add 128 to the ASCII value. The high order value is necessary as dBASE III PLUS filters low value ASCII characters as control keys. This procedure works only on printers that can strip off the eighth data bit with the printer set to strip off the eighth bit. Stripping off the eighth bit causes characters whose ASCII values are greater than 127 to be interpreted as 128 less than their actual value. To enter an Alt-, hold down Alt and enter the ASCII decimal value of the control code on the numeric keypad. For example, to enter CHR(15), enter Alt-143 (15 + 128 = 143). This works in both versions of dBASE III PLUS. >>> RETURN With the ON ESCAPE active, pressing Esc at a WAIT, INPUT, or ACCEPT command causes the program to resume at the line following the WAIT, INPUT, or ACCEPT command with no error messages. In version 1.0, pressing Esc in response to an INPUT statement with SET ESCAPE OFF hangs the system, while an Esc at a WAIT statement returns to the dot prompt. >>> RESTORE The dBASE III Reference Manual for all versions incorrectly states about the RESTORE command that any memory variables STOREd as PUBLIC remain PUBLIC if the ADDITIVE option is used. The ADDITIVE option to RESTORE will allow the user to RESTORE variables as PUBLIC only if they are declared PUBLIC before the RESTORE FROM ADDITIVE command is issued. If the variables are not explicitly declared PUBLIC, they will be RESTOREd as PRIVATE variables, regardless of their status when STOREd and SAVEd. For example, PUBLIC one, two STORE 1 TO one, two SAVE TO Mem CLEAR ALL RESTORE FROM Mem ADDITIVE <-- Variables are RESTOREd without being redeclared PUBLIC. will create PRIVATE variables "one" and "two," while, PUBLIC one, two STORE 1 TO one, two SAVE TO Mem CLEAR ALL PUBLIC one, two <-- Variable is redeclared PUBLIC. RESTORE FROM Mem ADDITIVE creates PUBLIC variables "one" and "two." >>> RUN / ! RUN / ! produces the error message "Insufficient memory" [43] if the maximum number of files (15) are open. To use RUN / !, a file handle must be available. However, when ADDFILES.BIN from the dBASE Programmers Utilities is loaded and used to open the maximum 20 files, RUN / ! executes without error. This is true for every version of dBASE III PLUS. >>> Scientific Notation dBASE III PLUS has a limited ability to handle scientific notation. Scientific notation is a number followed by the letter "e" followed by an integer, where the integer is a power of ten that is multiplied by the first number. For example, 1e4 = 1 * 10^4 = 10000 -1e4 = -1 * 10^4 = -10000 dBASE III PLUS can use this notation for variable initialization, field entry, APPENDing from text files, and in all numeric expressions. Variable initialization: The command mem = 1e4 or mem1 = "1e4" mem = VAL(mem1) stores 10000 to memory variable "mem." Field entry: The command REPLACE WITH 1e4 stores 10000 to . APPENDing FROM text files: If an SDF text file contains the number 1e4, APPENDing it into a database file puts 1e4 into a numeric field--not 10000 as might be expected. Numeric expressions involving this field generate valid answers. This method is the only one you can use because scientific notation cannot be entered during full-screen editing. To convert fields in scientific notation to decimal, use this command syntax: REPLACE ALL WITH dBASE III PLUS has a numeric accuracy of 15.9 digits, 13 digits when comparing non-zero numbers. Operations that exceed the accuracy may produce the error message "Numeric overflow (data was lost)." Numeric expressions: ? 1e4 * 3 displays 30000. >>> Converting Numbers to Scientific Notation Although dBASE III PLUS allows you to convert numbers from scientific notation to numbers in {decimal} notation (See...), it does not allow you convert decimal notation to scientific notation. The following programs, Sci.PRG, converts numbers in decimal format to scientific notation. To use Sci.PRG, call it with the following general syntax: ret_val = "" DO Sci WITH , , ret_val where the arguments are defined as follows: number ::= integer to be converted decimals ::= number of decimal places ret_val ::= character variable to accept return value Also included is a sample program, SciTest.PRG, that demonstrates how to use Sci.PRG to list a set of numbers from a database file in scientific notation. * Program ...: Sci.PRG * Author ....: Kenneth N. Getz * Date ......: March 1, 1987 * Version ...: dBASE III PLUS * Note(s) ...: Converts x to scientific notation correct to decimal number * of decimal places. Works for any positive number within * dBASE III PLUS limits. * PRIVATE ALL PARAMETERS x, dec, ret_val y = LOG(ABS(x)) / LOG(10) && Find order of magnitude. y = IIF(INT(y) = y, INT(y) + 1, INT(y)) y = IIF(ABS(x) < 1,y - 1,y) z = x / 10^y && Normalize the number (0 < z < 10). order = 10^dec && Find order of rounding accuracy. fudge = IIF(x < 0, -.5, .5) q = INT( z * order + fudge)/order ret_val = LTRIM(STR(q,15,dec)) + "E" + IIF(ABS(x) < 1,"-","+") + LTRIM(STR(ABS(y))) RETURN * EOP Sci.PRG * Program ...: SciTest.PRG * Author ....: Kenneth N. Getz * Date ......: March 1, 1987 * Version ...: dBASE III PLUS * Note(s) ...: A test program for Sci.PRG. Uses the database SciTest.DBF * PRIVATE ALL PARAMETERS decimals STORE SPACE(30) TO ret_val USE Scitest DO WHILE .NOT. EOF() ? num DO Sci WITH num, decimals, ret_val ?? IIF(num < 0, SPACE(10), SPACE(11)) + ret_val SKIP ENDDO RETURN * EOP SciTest.PRG >>> Semicolon In dBASE III PLUS, you cannot continue commands issued at the dot prompt with a semicolon. The dBASE III PLUS command line is a 254-character horizontal scroll space. Previous versions of dBASE III allowed you to continue a dot prompt command line with a semicolon. >>> SET ALTERNATE TO You can use the following program, Cpsep.PRG to COPY a database file to a flat ASCII file with no separators between either fields or records. Such a file differs from the SDF format in that each record is not separated with a carriage return/line feed pair. * Program ...: Cpsep.PRG * Author ....: Quinn Wildman * Date ......: January 1, 1987 * Note(s) ...: Creates a text file image of a database file with * no record separators. * SET TALK ON ACCEPT "Enter name of text file: " TO txtfile ACCEPT "Enter name of database file: " TO dbfile USE &dbfile SET ALTERNATE TO &txtfile SET ALTERNATE ON DO WHILE .NOT. EOF() cnt = 1 DO WHILE LEN( FIELD( cnt )) <> 0 macro = FIELD( cnt ) ?? ¯o cnt = cnt + 1 ENDDO SKIP ENDDO SET ALTERNATE OFF CLOSE ALTERNATE CLEAR ALL SET TALK ON * EOP Cpsep.PRG >>> SET CATALOG ON If you assign an ALIAS when you USE a database file, the catalog does not store the ALIAS but instead stores the filename as the ALIAS. For example, SET CATALOG TO USE Test1 ALIAS Testfile SELECT 10 LIST ^------ This show the ALIAS as "Test1," not "Testfile." >>> SET CATALOG ON With an active Catalog and SET CATALOG ON, creating a new index or issuing SET INDEX TO an existing index file does not prompt for a file title description as documented in the Using dBASE III PLUS manual. Instead, dBASE III PLUS places the index key expression in the Catalog field Title. >>> SET CATALOG TO ? Attempting to open a catalog file that has the same name as an open database file or assigned alias name produces the error message "ALIAS name already in use." [24]. To avoid the error message, assign a different alias to the database file or close the database file before executing SET CATALOG TO. For example, USE Test SET CATALOG TO Test produces the error message. This occurs in both versions 1.0 and 1.1 of dBASE III PLUS. >>> SET COLOR The SET COLOR TO command changed somewhat in the Developer's Release and dBASE III PLUS. Formerly, colors could be referenced by number or letter code. With the Developer's Release and dBASE III PLUS, only letter codes are accepted. Additionally, there are several new options. Black can now be referenced with the letter code N, inverse video with the letter code I, and the screen can be blanked with the code X. The following table shows all the default color attributes for dBASE III from version 1.0 through dBASE III PLUS. Color Attribute Table Developer's Release dBASE III dBASE III PLUS Color Letter Number Letter Only Black 0 | N or Blue B 1 | B Green G 2 | G Cyan BG 3 | BG Red R 4 | R Magenta BR 5 | BR Brown GR 6 | GR White W or RB 7 | W or RB Other Blank | X Blinking * | * High intensity + | + Inverse video | I Underline U | U Three other capabilities are added to color in dBASE III PLUS. First, there is a new function, ISCOLOR(), that returns a true value (.T.), if your monitor is in color mode. Second, SET COLOR supports a toggle syntax, ON/OFF, to toggle your monitor between color and monochrome modes, if your machine supports both. Lastly, a background option is added for machines that cannot set the background of individual characters with the standard and enhanced options. >>> SET COLOR TO It is not documented that the U and I arguments of SET COLOR TO, which are for monochrome monitors, set the color to black when used on a color monitor. For example, on a color monitor SET COLOR TO U/I is equivalent to SET COLOR TO N/N >>> SET COLOR TO Using an attribute (high intensity or blinking) of colors with SET COLOR TO applies to the foreground setting only and has no effect on background colors. In fact, if you assign an attribute to a background color, dBASE III PLUS passes the attribute to the foreground color instead. Because of this, the colors gray (N+) and yellow (GR+) appear as black and brown respectively when used for background settings. Keep in mind that for color settings there are three basic settings (display, enhanced, and border) and that within each one there are both foreground and background colors. SET COLOR TO [[][,][,]] where standard ::= [][/] enhanced ::= [][/] border ::= [][/] and foreground ::= [[{attribute}]] background ::= It appears that the attribute although it affects the color is a function of the setting. Each setting, therefore, can have only one attribute which is applied to the foreground color. This behavior is in contrast to dBASE III version 1.0 and 1.1, where attempting to assign an attribute to a background color did not pass the attribute to the foreground color. >>> SET DATE FRENCH The format of date variable display varies between versions 1.1 and the Developer's Release and dBASE III PLUS, when SET DATE is FRENCH. For example, dBASE III Developer's Release Version 1.1 dBASE III PLUS SET DATE FRENCH DD.MM.YY DD/MM/YY The Developer's Release and the dBASE III PLUS displays are identical to SET DATE BRITISH. >>> SET DELETED ON SET DELETED ON can affect the FIND command when there is more than one record in the database file with the same index key. For example, suppose there are two "Johnsons" in the database file. The first is marked for deletion and the second is locked with RLOCK() at a different workstation. If SET DELETED is ON, and you try to FIND "Johnson", you will get the message "No find" instead of the expected "Record is in use by another." Under any other circumstance, a FIND on a record locked with RLOCK() returns the message "Record is in use by another" and positions the record pointer to that record. There is no work-around at this time. >>> SET ESCAPE OFF Esc terminates an active READ regardless of the status of SET ESCAPE in both versions of dBASE III PLUS. Documentation Index The index for the second edition of the documentation contains incorrect page references. The specific references are shown in Figure 2. Item Incorrect Correct -------------------------------------------------------------- Function keys (Page X-17) U5-224 - U5-225 U5-234 Memo field (Page X-20) adjusting width for output U5-234 U5-243 editing in programs P5-16 P5-26 >>> SET FIELDS TO Issuing the SET FIELDS TO command automatically SETs FIELDS ON, regardless of the FIELDS status prior to issuing the SET FIELDS TO command. The dBASE III PLUS Reference Manual states on page 5-169 of the Using section, under the SET FIELDS TO command, "The list of fields is not active unless the SET FIELDS command is ON." This statement implies that the command SET FIELDS ON must be executed explicitly to activate the current field list after creating it. Anytime the command SET FIELDS is executed either to create a fields list or to add to one, FIELDS are SET ON. >>> SET FILTER TO It is not documented in any of the dBASE III PLUS reference manuals that certain commands ignore the SET FILTER TO condition. Specifically, the commands DISPLAY (current record), DISPLAY RECORD , GO/GOTO, or any command with the scope RECORD or NEXT . For example, if the SET FILTER TO condition excludes record five and GOTO 5 is executed, a subsequent DISPLAY reveals the contents of the record. >>> SET HISTORY OFF Page U5-180 of the original documentation incorrectly states, "The command SET HISTORY OFF disables the history feature so that prior commands can't be recalled." Page U5-237 of the revised documentation incorrectly states, "The command SET HISTORY OFF clears the history buffer." The command SET HISTORY OFF suppresses the storage of commands into the history buffer. Commands entered in HISTORY prior to SET HISTORY OFF may still be displayed, edited, and re-executed. To clear the history buffer of commands, SET HISTORY TO 0. >>> SET ORDER TO You must reposition the record pointer after executing SET ORDER TO in dBASE III PLUS. The easiest way to do this is to issue the command: GO RECNO() This will cause the record pointer to reposition itself to the current record position updating the internal record pointer. If, however, EOF() returns true (.T.), this won't work. In this case, use the following command: GO IIF(EOF(), RECCOUNT(), RECNO()) >>> SET PATH TO The original documentation does not include the path length limitations for the SET PATH TO command. The path is limited to 60 characters. Exceeding that limit will produce the error message "Maximum path length exceeded" [146]. >>> SET PROCEDURE TO Beginning in Developer's Release, you can have a command file that SETs PROCEDURE to itself, effectively allowing you to create single file applications such as those you could create with dBCODEing and dBLINKing. Additionally, you can CLOSE the PROCEDURE within the calling program. Be sure, however, you do not CLOSE PROCEDURE within any of the procedures or dBASE III PLUS will return the error message "File is already open." For example, * ---Sayhello.PRG SET PROCEDURE TO Sayhello && SETs PROCEDURE TO itself. DO Proc1 DO Proc2 CLOSE PROCEDURE RETURN PROCEDURE Proc1 ? "Hi there, I'm procedure number One and I love black beans." RETURN PROCEDURE Proc2 ? "Howdy, I'm procedure number Two and I'm a Taurus." RETURN * EOP Sayhello.PRG In dBASE III version 1.1, doing this returned the error message "File is already open." >>> SET RELATION TO The description of "Cyclic relation" under Error Messages contains the line "SET RELATION, without any parameters, disconnects all relations from the currently selected work area." But SET RELATION with no arguments produces a "Syntax error." The proper command is SET RELATION TO with no argument. This is corrected in the second edition of the documentation. >>> SET RELATION TO Throughout the documentation for dBASE III PLUS, there is some ambiguity about the various ways you can link database files with SET RELATION TO. SET RELATION TO relates two database files in three different ways. 1. You can relate two database files with a key expression allowing you to create connections between database files based on value. It is important to stress that you are not confined to a single common field. The linking expression can be any legitimate dBASE III PLUS expression. To work, the key expression must return a value from the source work area that matches a value in the master index file of the target work area. Because the relation is created by an expression, you can take two dissimilar database file structures that contain common values and create a relation between them. In exactly the same way, you can create a relation between database files that have common fields. In both cases, the mechanism is the same: the relation is created by an expression. 2. Another way to relate database files is by record number. This type of relation allows you to link two database files having no common field values but have a one-to-one relation based on physical position. Record one in the source corresponds to record one in the target file and so on. Generally, you will use this formulation to create a virtual database file where you need a number of fields greater than the dBASE III PLUS limit of 128 per database file. When the record pointer moves in the source database file, the record pointer in the target moves to the same record number as the source record. For example, * ---Setup and syntax with a physical relation. SELECT B USE File2 SELECT A USE File1 INDEX File1 SET RELATION TO RECNO() INTO File2 * ---List records from File1 and File2. DO WHILE .NOT. EOF() ? Field1, Field2, File2->Field1, File2->Field2 * ---Advance File1 and File2 pointer. SKIP ENDDO * ---Setup and syntax with no relation. SELECT B USE File2 SELECT A USE File1 INDEX File1 * ---List records from File1 and File2. DO WHILE .NOT. EOF() ? Field1, Field2, File2->Field1, File2->Field2 * ---Advance the File1 pointer. SKIP * ---Advance the File2 pointer. recpos = RECNO() SELECT B GO recpos SELECT A ENDDO In order to build various index sort orders, put all of your key fields in the master database file as the diagram below indicates. This is important since a relation based on RECNO() precludes the use of an index file in the target work area. Master -----> Sub1 ------> Sub2 (Keys) (Non-keys) (Non-keys) 3. The last type of relation is a physical link between database files based on a numeric expression. If the linking expression evaluates to numeric and the target database file is not INDEXed, then the target record pointer moves to the record number returned by the linking expression each time the source database file pointer moves. For example, the following linking expression relates two unINDEXed database files so each pair of adjacent records in the source database file points to a single record in the target file. IIF(MOD(RECNO(),2)=1,INT(RECNO()/2)+1,INT(RECNO()/2)) Record numbers one and two in the source point to record number one in the target, three and four in the source point to two in the target, and so on. This type of relation can be used to build virtual data structures based on a link that is a combination of value and physical location. In general, it is important to your mastery of dBASE to understand the truly dynamic nature of relating database files with SET RELATION TO. For more information on SET RELATION TO, refer to the page D3-11 of the April 1985 issue of TechNotes. >>> SET RELATION TO In versions 1.0 and 1.1 of dBASE III, a relation could be released with the command SET RELATION. In the Developer's Release and dBASE III PLUS, this command returns a syntax error although it releases the RELATION. The proper and supported command syntax to release a relation is SET RELATION TO. >>> SET SCOREBOARD/SET STATUS The SET SCOREBOARD ON/OFF and SET STATUS ON/OFF commands will clear the entire screen when issued in dBASE III PLUS. In previous versions, SET SCOREBOARD ON/OFF would affect only the SCOREBOARD area of the screen. >>> SET VIEW TO If any change has been made to any of the component parts of a view, invoking that view file with SET VIEW TO will return an error message. The specific message will depend on the error in the view file. For example, if the name of field in the fields of the view has been changed by MODIFYing the STRUCTURE of one of the constituent database files, issuing the SET VIEW TO command will return "Variable not found." Once this condition has occurred, there is no way to open the view file and modify it, as MODIFY VIEW will return the same error message. The file must be deleted and re-created, or the environment must be made consistent with the view file once more. >>> STORE Attempting to STORE a string containing "&&" to a memory variable produces the error message "Unterminated string" when executed. This is because the double ampersands are interpreted as an in-line comment, effectively removing the closing quotation mark from the command line. To work around this, split the character expression between the ampersands into two expressions and concatenate them when assigning them to the memory variable. For example, the following is a successful instance of embedding "&&" in a string. STORE "Before the &" + "& and after." TO mvar >>> Tandy printers Some older Tandy printers do not recognize CHR(12) as a form feed character. To correct this problem, install the device driver LPDRVR.SYS in CONFIG.SYS. LPDRVR.SYS is provided with Tandy DOS 3.x. LPDRVR.SYS keeps track of the number of carriage return/line feeds sent to the printer. When a form feed is transmitted, LPDRVR.SYS sends the remaining number of carriage return/line feeds necessary to reach the top of the next page. To install LPDRVR.SYS, add the following line to CONFIG.SYS: DEVICE = LPDRVR.SYS If LPDRVR.SYS is not available, it may be obtained from Tandy. The phone number for hardware support is (817)338-2394 and the phone number for software support: (817)338-2390 and (817)338-2392 or leave a message at their main switchboard, (817)390-3011. >>> TRANSFORM() In both versions 1.0 and 1.1 of dBASE III PLUS, including a TRANSFORM() expression with a PICTURE function in the CREATE REPORT Columns:Contents may require resetting Contents:Width to a value greater than the default. When the expression to be TRANSFORMed is numeric, using the default Contents:Width of 10 forces the displays to wrap to a second line. Increasing the Contents:Width corrects the problem. The following is a list of functions and the corresponding minimum values: Function Width ----------------------------------------------- TRANSFORM(, "@C") 16 TRANSFORM(, "@X") 16 TRANSFORM(, "@(") 15 TRANSFORM(, "@Z") 13 TRANSFORM(, "@B") LEN() >>> Trapping the Esc Key In dBASE III PLUS, version 1.1, SET ESCAPE OFF is ignored by the WAIT, INPUT, and ACCEPT commands. If the user presses Esc in response to any of these commands, dBASE III PLUS responds with the "Cancel, Ignore, or Suspend?" message, and the user can cancel the application program. The work-around is to add an ON ESCAPE command to the application: ON ESCAPE DO Esc_back Esc_back.PRG needs just one line: >>> UNINSTAL.BAT UNINSTAL.BAT deletes CONFIG.SYS, if it exists, in the target drive default directory. This is potentially dangerous if the default directory of the target disk is the root directory. Some systems, such as older Bernoulli drives, require CONFIG.SYS to boot. Use caution when uninstalling dBASE III PLUS from a root directory. >>> UPDATE If you are trying to UPDATE one database file from another and the relation between them is many-to-one, you may have found that the UPDATE command does not support this formulation. The UPDATE command only updates the first instance in the target database file. This means that the UPDATE command is useful only when the relation between the source and the target database files is one-to-one. To update your many-instance file from the single-instance file, use the REPLACE command in combination with SET RELATION. For example, SELECT 2 USE INDEX SELECT 1 USE INDEX SET RELATION TO INTO REPLACE ALL WITH ->,; WITH ->,; WITH -> >>> USE If byte 15 of a .DBF file header contains a value other than a null, USEing the file in dBASE III PLUS produces the error message "Database is encrypted." This byte is used by the dBASE Administrator to mark a file as encrypted. Earlier versions of dBASE III ignored this byte. If you encounter this error message when USEing a database file in single-user mode, run NEWHEAD.BAS or use DEBUG to change the byte back to a null. Note that in order to use DEBUG, your database file must be smaller in size than the amount of free memory available prior to running DEBUG.