home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
dbase
/
_base16.zip
/
CLIPPER.DOC
< prev
next >
Wrap
Text File
|
1994-02-13
|
6KB
|
183 lines
Enhancing your Clipper programs using !STRUCT
================================================================
!STRUCT allows to export information from you dbf files, and put
it directly into your source code files. This will save you much
typing, and a lot of debugging headaches.
This file provides information on how to enhance your code by:
Using dbcreate()
Using field declarations
Accessing database fields by field number
Using dbcreate()
================================================================
Clipper 5.0 has a new function called dbcreate(), that allows the
creation of a database file from a structure array. By using a
structure array:
Your application generate its own dbf files
File structure updates are easier
Fields lengths up to 64,000 characters may be used
To see what a structure array looks like type:
!STRUCT . -A | MORE
To create a program that creates all of your databases, type:
!STRUCT . -A > CREATE.PRG
│ │ │ └───────── output file name
│ │ └─────────── redirect output symbol
│ └───────────── specify array style output
└──────────────── file specification
Then edit CREATE.PRG. You will a static array created for each
dbf file in you application.
static DBF_TEST := { ;
{"TEXT" , 'C', 80, 0 };
}
static DBF_SAMPLE := { ;
{"ID_NUM" , 'C', 6, 0 },;
{"ID_DATE" , 'D', 8, 0 },;
{"ID_AMT" , 'N', 8, 2 },;
{"ITEM" , 'C', 30, 0 };
}
Now add the necessary code to create the databases:
function Initialize()
if !file("sample.dbf")
dbcreate("sample", DBF_SAMPLE)
endif
if !file("test.dbf")
dbcreate("TEST", DBF_TEST)
endif
When you need to modify a database in an existing application,
simply edit this file again and change the array information. In
this example I decided to add the new field "extra". This code
will detect the fact that the actual database file structure
doesn't match the expected database structure, and it updates the
actual file structure.
static DBF_SAMPLE := { ;
{"ID_NUM" , 'C', 6, 0 },;
{"ID_DATE" , 'D', 8, 0 },;
{"ID_AMT" , 'N', 8, 2 },;
{"ITEM" , 'C', 30, 0 },;
{'EXTRA' , 'C', 8, 0 };
}
function open_sample()
use sample new
if len(DBF_SAMPLE) > fcount()
? "Updating file structure - Please wait"
close sample
erase sample.old
rename sample.dbf to sample.old
dbcreate("sample", DBF_SAMPLE)
use sample new
append from sample.old
erase sample.old
endif
Using field declarations
================================================================
To avoid complier warning, field declarations should be used.
The best way of doing this is to create a header file with all
the field names declared in it.
You can generate this header file very easily by typing:
!STRUCT . -F > FIELDS.CH
│ │ │ └───────── output file name
│ │ └─────────── redirect output symbol
│ └───────────── specify field declaration output
└──────────────── file specification (same as *.*)
To use the header file, put the include declaration at the top of
the file:
#include "fields.ch"
function main()
...
Any time a database or field is added, simply generate a new
FIELDS.CH header file.
Accessing database fields by field number
================================================================
Clipper 5.0 introduced the fieldget() and fieldput() functions.
Fieldget() and fieldput() allow you to reference database fields
by number, instead of by the name string. This is useful, if you
wish to pull your field information into an array.
The problem with using hard coding numbers to reference fields,
is that it is hard to keep track of which number corresponds to
which field.
To generate a header file that redefines each field with a
readable name type:
!STRUCT SAMPLE.DBF -N > DEFINES.CH
The utility will create the file DEFINES.CH that will look like
this:
*** SAMPLE ***
#define SAMPLE_ID_NUMBERS 1 // C, 6, 0
#define SAMPLE_ID_DATE 2 // D, 8, 0
#define SAMPLE_ID_AMT 3 // N, 8, 2
#define SAMPLE_ITEM 4 // C, 30, 0
#define MAX_SAMPLE 4
To get the value of the field ID_NUMBERS type:
#include "defines.ch"
? fieldget(SAMPLE_ID_NUMBERS)
A more useful example that sucks up the contents of a record into
an array, allows the user to edit the array, and then puts the
contents back into the original record:
#include "defines.ch"
func main()
local getlist:={}
local a:={}
use sample
a:=getrec(MAX_SAMPLE)
@ 10, 10 get a[SAMPLE_ID_NUMBERS]
@ 11, 10 get a[SAMPLE_ID_DATE ]
@ 12, 10 get a[SAMPLE_ID_AMT ]
@ 13, 10 get a[SAMPLE_ITEM ]
read
if lastkey()!=27
putrec(a, MAX_SAMPLE)
endif
func getrec(nLast)
local a[nLast]
local cnt
for cnt:=1 to nLast
a[cnt]:=fieldget(cnt)
next
return(a)
func putrec(a, nLast)
local cnt
for cnt:=1 to nLast
fieldput(cnt, a[cnt])
next
return nil