DBASE IV v1.1->1.5->2.0 differences

 

Site d'origine : www.reocities.com/geoff_wass/dBASE/GaryWhite/dBASE/FAQ/qdiff.htm

 

dBASE IV v1.1->1.5->2.0 differences

 

Recompile any object files under the version of dBASE you will be using. While not always necessary for proper operation, it is always recommended. This will optimize the code under the dBASE version running and help avoid potential problems.

When going from v1.1 to v1.5 ( or anytime you move programs from one version to another ) make backups and then delete all object files,

DELETE *.??O

If there is no object file and the source files still exists, dBASE will automatically do a recompile the next time you run your program. Or you can recompile the code manually:

source object
.FMT -> .FMO SET FORMAT TO <filename>
.FRG -> .FRO REPORT FORM <filename> WHILE .F.
      * WHILE .F. suppress report output to screen
.LBG -> .LBO LABEL FORM <filename> WHILE .F.
.QBE -> .QBO SET VIEW TO <filename>
.PRG -> .DBO COMPILE <filename> [RUNTIME]
      * RUNTIME switch checks
      * RUNTIME/EXE compatibility

* dBIV 1.1-1.5 Differences * This also includes v1.1 -> v2.0 *

The SELECT() functions has been changed in 1.5. In 1.1 it returned the HIGHEST available work area, in 1.5 it returns the LOWEST.(see pg 4-127 of LR and page 17-4 of 'Getting Started'). The reason it has change is due to more work areas and more efficient use of memory. In v1.1 you had ten work areas and each was allocated a section of memory. In v1.5 with 40 work areas dBASE now allocates the work area as you use them, hence SELECT() pulls the next Available work area.

Assume you're in work area 1, the default, with no DBFs open:

USE table3 IN SELECT()
USE table2 IN SELECT()
USE table1

Table3 is opened IN 1, table2 IN 2, and then the USE table1 command closes table3 and opens table1 IN 1. In pre v1.5 versions, table3 and table2 would have been opened IN 10 and 9 respectively.

-----------------------------------

Because not all workareas are opened at startup in v1.5, CATALOG is no longer strictly in area 10. In v1.5 you can use the CATALOG() function for accessing the catalog directly.

Duplicate checking via .NOT. SEEK(FieldName) under Accept Value When in a screen form; this worked in 1.0 and 1.1 but not under 1.5. It should never have worked or been suggested as a means of achieving the goal of prevention of duplicate entries, but unfortunately many people have it in their screen forms. It should not be used because you don't want to move the record pointer in the current database while APPENDing/EDITing.

Version 1.5 handles the phantom record a little differently than 1.1 did. Essentially, if you move the record pointer ( as will occur with a validation seek UDF ), it 'forgets' the values of the GET's prior to and including the GET to which the seek is attached.

The following is an excerpt from the READ.ME from dBASE IV ver 1.5.

" If you write code or use an application that moves the record pointer during an interruption, (see the item above), you must take special care when you're executing the interrupt during the full-screen APPEND command. Whenever you interrupt APPEND, you should restore the record pointer as mentioned in the previous item. In addition, your interrupting code must save (on entry) any values entered onto the APPEND screen prior to the interruption. You must then restore these saved values after the record pointer is repositioned (just before the interrupt routine exits). These steps are required because dBASE IV keeps all values entered during the APPEND command in a temporary buffer. During APPEND, the buffer record values are handled as follows: - If you press Esc and abandon the new record, the values are discarded. - If you accept the new record during a normal APPEND, the values are added to the database file as a permanent record. However, when the record pointer is moved during an APPEND interrupt, the values in the temporary record are not retained (they become blank). Although the APPEND screen may show the values as they were originally entered, those values are no longer in the temporary buffer. A common occurrence of this is during an interrupt call to a validation UDF which uses a SEEK to check for duplicate keys. SEEK will reposition the database, changing the current record pointer and blanking the temporary buffer. "

To check for duplicates you can use one of the following methods:

@ 5,5 GET fld_name ;
   VALID REQUIRED nodup()
READ

FUNCTION Nodup
  mselect = SELECT()
  USE employee order lastname in (mselect) AGAIN
  mreturn = .NOT. SEEK(lastname,mselect)
  USE IN (mselect)
RETURN mreturn

If you have v2.0 or dB5D you can use KEYMATCH() to check for duplicates. It will not move the record pointer and will use any existing index for very fast searches!

@ 5,5 GET fld_name ;
VALID REQUIRED ;
(.not. KEYMATCH(fld_name,TAGNO("tagname")))
* you can use the index number as an argument
* within KEYMATCH() so you don't have to
* SET ORDER TO <tagname> prior to using
* TAGNO("tagname") returns the index
* number.
READ

For more on using KEYMATCH() see 
Lib 10: TI1641 Preventing Duplicates in a Data Entry Screen.

Files that use aggregate operators in the source file work in 1.1 and fail in 1.5.

USE x-y && a filename with a dash
? ALIAS() Version 1.1 returns: A
                  1.5 returns: _1

If you try to use this filename in an expression, ( or dBASE makes a temporary file during a query for example ) Version 1.5 generates the error ALIAS NOT FOUND. If you follow proper naming conventions, you will avoid these types of errors.

Naming conventions for field, file and memory variable names:

BEGINS with a letter, and contains nothing but letters, numbers and the underscore "_" character ( Don't use characters such as #,&,-,etc. ). Do not use dBASE reserve words. These are dBASE command words or the first 4 letters of a dBASE command as a name. Example: TOTAL, TOTA; SELECT, SELEC, SELE. Don't use the letters A-J, these are reserved for ALIAS names.

*** dBIV 1.1/1.5 - 2.0 Differences ***

PAD() RETURNS INCORRECT VALUE FROM A SUBMENU. DIFFERENT FROM V1.1/V1.5 Problem with PAD() in v2.0

PAD() does not return the correct value when returning from a submenu.
Steps to reproduce:Run the code listed below.
Choose b1 on the main menu
Enter again to go back to main menu
Hit enter on b1
This will take you to the submenu for a1, "a2" not "b1"

DEFINE MENU TOPLEVEL
DEFINE pad PAD_1 OF TOPLEVEL PROMPT "a1" AT 0,2
ON SELECTION pad PAD_1 OF TOPLEVEL DO PROC_1
DEFINE pad PAD_2 OF TOPLEVEL PROMPT "b1" AT 0,18
ON SELECTION pad PAD_2 OF TOPLEVEL DO PROC_1

DEFINE MENU amenu
DEFINE pad PAD_1 OF amenu PROMPT "a2" AT 0,2
ON SELECTION pad PAD_1 OF amenu DEACTIVATE MENU

DEFINE MENU bmenu
DEFINE pad PAD_1 OF bmenu PROMPT "b2" AT 0,2
ON SELECTION pad PAD_1 OF bmenu DEACTIVATE MENU

ACTIVATE MENU TOPLEVEL

RETURN

PROCEDURE PROC_1
DO CASE
   CASE PAD() = "PAD_1"
      ACTIVATE MENU amenu
   CASE PAD() = "PAD_2"
      ACTIVATE MENU bmenu
ENDCASE
RETURN

WORKAROUND: Moving the menu prompt will correct this problem, so use KEYBOARD right, left arrow.

PROCEDURE PROC_1
DO CASE
   CASE PAD() = "PAD_1"
      ACTIVATE MENU amenu
   CASE PAD() = "PAD_2"
      ACTIVATE MENU bmenu
ENDCASE
KEYBOARD CHR(4) + CHR(19)
RETURN

For additional changes between versions see the 'What's New' section in Getting Started manual and the README file.

There are also the following related files in library 1:

V15NEW.ZIP 
Title : New features in dBASE IV v1.5 DBASE IV V1.5 New features, compatibility, questions & answers

V20NEW.ZIP 
Title : Changes in dBASE IV v2.0 This file lists the changes in the newest version of dBASE, dBASE IV v2.0

Retour

 

Retour à l'accueil