Contributed works of Danny A. del Pilar
How to build menu like old ACHOICE function?
KPI (Key Performance Indicator) Dashboard
How to build menu like old ACHOICE function?
KPI (Key Performance Indicator) Dashboard
PROGINDEX()
Short:
------
PROGINDEX() Perform an index with a progress box
Returns:
--------
Nil
Syntax:
-------
PROGINDEX(cName,cKey,[lUnique],[lShowCount],[lPause])
Description:
------------
Pops up a progress bar box with PROGON().
Performs an index using <cName> as the index name,
and <cKey> as the index key.
[lUnique] for index UNIQUE (default False)
[lShowCount] to show an index count as well as the
progress bar - default False
[lPause] if True will pause before removing the box
with PROGOFF()- default is False.
Examples:
---------
use customer
ProgIndex("Eraseme","LNAME",.f.,.t.,.t.)
Source:
-------
S_PROG.PRG
See also : PROGCOUNT(), PROGDISP(), PROGEVAL(), PROGOFF(), PROGON()
NKEY()
Short:
------
NKEY() Gets key of an index file
Returns:
--------
<cKey> => index key expression
Syntax:
-------
NKEY(cIndex)
Description:
------------
Gets key expression of index <cIndex>. <cIndex> is
the name of the index including extension. The function operates
differently from .ntx to .ndx.
Examples:
---------
for i = 1 to nIndexes
?"Key for index: "+aInd[i]+" is "+NKEY(aInd[i])
next
Warnings:
----------
Uses up a file handle temporarily. Opens up the index
with low level file functions.
Notes:
-------
NKEY() expects the full path of the index file and if
no path is passed, will use SET DEFAULT setting
Source:
-------
S_NKEY.PRG
| Ext. | File Type | Introduced or used by |
| .$$$ | temporary file | dBASE III |
| .$db | temporary file | dBASE IV |
| .act | FoxDoc Action Diagrams | FoxPro |
| .app | application object file | dBASE Appl. Generator |
| .app | generated application | FoxPro |
| .bak | Backup file | dBASE |
| .bar | horizontal bar menu object file | dBASE Appl. Generator |
| .bin | Binary files | dBASE |
| .bch | batch process object file | dBASE Appl. Generator |
| .cac | executable when caching on/off | dBASE IV |
| .cat | catalog | dBASE III, IV |
| .cdx | compound index | FoxPro |
| .ch | header file | Clipper |
| .cht | interface file for ChartMaster | dBASE |
| .clp | compiler script file (clip list) | Clipper |
| .cmd | command | dBASE – Waffle |
| .cod | template source file | dBASE Appl. Generator |
| .cpt | encrypted memo file | dBASE |
| .crp | encrypted database | dBASE IV |
| .ctl | control file | dBASE IV – Aldus Setup |
| .cvt | backup file for CONVERTed database file | dBASE IV |
| .db | configuration | dBASE |
| .db$ | temporary file | dBASE |
| .db2 | database | dBASE II |
| .db3 | database | dBASE III |
| .dbf | database file | dBASE – FoxPro |
| .dbk | database backup | dBASE IV |
| .dbo | compiled program | dBASE IV |
| .dbt | FoxBASE+ style memo | FoxPro |
| .dbt | memo file for database w/same name | dBASE – Clipper |
| .def | Definitions list | dBASE |
| .dif | Data Interchange Format. For APPEND FROM, COPY | dBASE – VisiCal |
| .doc | Documentation text file | dBASE Appl. Generator |
| .fil | files list object file | dBASE Appl. Generator |
| .fky | macro file | FoxPro |
| .fmo | compiled format file | dBASE IV |
| .fmt | format file | dBASE – FoxPro – Clipper |
| .fp | configuration file | FoxPro |
| .fpc | catalog | FoxPro |
| .fpt | memo | FoxPro |
| .fr3 | renamed dBASE III+ form file | dBASE IV |
| .frg | uncompiled report file, code fragment file | dBASE IV |
| .frm | report file | dBASE – Clipper |
| .fro | compiled report file | dBASE IV |
| .frt | report memo | FoxPro |
| .frx | report | FoxPro |
| .fw2 | Framework spreadsheet or database file | Framework – dBASE |
| .fxp | compiled format | FoxPro |
| .gen | compiled template | dBASE Appl. Generator |
| .idx | index (many) | FoxPro |
| .ind | include index | dBASE IV |
| .inx | index | FoxBase |
| .key | Key macro library | dBASE |
| .lbg | label generator data | dBASE IV |
| .lbl | label | dBASE – Clipper |
| .lbo | compiled label | dBASE IV |
| .lbt | label memo | FoxPro |
| .lbx | label | FoxPro |
| .ld1 | overlay file | dBASE |
| .log | Transaction log file | dBASE |
| .mbk | multiple index file backup | dBASE IV |
| .mdx | multiple index file | dBASE IV |
| .mem | memory variable save file | dBASE – FoxPro |
| .mnt | menu memo | FoxPro |
| .mnx | menu | FoxPro |
| .mpr | generated program | FoxPro |
| .mpx | compiled menu program | FoxPro |
| .ndx | index file | dBASE |
| .npi | source for DGEN.EXE interpreter | dBASE Appl. Generator |
| .ntx | index file | Clipper |
| .pjt | project memo | FoxPro |
| .pjx | project | FoxPro |
| .plb | library | FoxPro |
| .pll | pre-linked library | Clipper |
| .plt | pre-linked transfer file | Clipper |
| .pop | pop-up menu object | dBASE Appl. Generator |
| .ppo | pre-processor output | Clipper |
| .pr2 | printer driver | dBASE IV |
| .pr3 | PostScript printer driver | dBASE IV |
| .prf | printer driver | dBASE IV |
| .prg | program source file | dBASE – FoxPro – Clipper |
| .prs | procedure | dBASE IV |
| .prt | Print dump | dBASE |
| .prx | compiled program | FoxPro |
| .qbe | saved query (Query By Example) | dBASE IV – Quattro Pro |
| .qbo | compiled query | dBASE IV |
| .qpr | generated query program | FoxPro |
| .qpx | compiled query program | FoxPro |
| .qry | query | dBASE IV |
| .res | dBASE resources | dBASE IV |
| .rpd | Rapid file. For IMPORT/EXPORT,APPEND FROM, COPY | dBASE |
| .sc3 | renamed dBASE III screen mask file | dBASE IV |
| .scr | screen – screen snapshot | dBASE IV |
| .sct | screen memo | FoxPro |
| .scx | screen | FoxPro |
| .spr | generated screen program | FoxPro |
| .spx | compiled screen program | FoxPro |
| .str | structure list object file | dBASE Appl. Generator |
| .t44 | Temporary file for Sort or Index | dBASE IV |
| .tbk | memo backup | dBASE IV – FoxPro |
| .tvf | table view settings | dBASE |
| .upd | update data | dBASE |
| .upo | compiled update data | dBASE |
| .val | values list object file | dBASE Appl. Generator |
| .vew | view file | Clipper, Lotus Approach |
| .vue | view | dBASE IV – FoxPro |
| .w44 | temporary file for Sort or Index | dBASE |
| .wfm | form object | dBASE Form Designer |
| .win | window file | FoxPro – dBASE |
Source : http://www.clicketyclick.dk/databases/xbase/format/index.html
Notes:
– Such a list can’t be perfect. Some item may be obsolete / forgotten and something may not exist when this list compiled.
– “Clipper” may not include all versions of Clipper.
– Most of Clipper files are supported by Harbour.
Consider a table for customers records with two character fields : Customer ID and customer name:
| Cust_ID | Cust_Name |
| CC001 | Pierce Firth |
| CC002 | Stellan Taylor |
| CC003 | Chris Cherry |
| CC004 | Amanda Baranski |
It’s known all possible and necessary operations on a table: APPEND, DELETE, SEEK and so on; by the way, for SEEK we need an index file also.
Listing this table is quite simple:
USE CUSTOMER
WHILE .NOT. EOF()
? CUST_ID, CUST_NAME
DBSKIP()
ENDDO
If our table is sufficiently small, we can find a customer record without index and SEEK :
LOCATE FOR CUST_ID = “CC003”
? CUST_ID, CUST_NAME
If we want all our data will stand in memory and we could manage it more simple and quick way, we would use an array ( with some considerations about size of table; if it is too big, this method will be problematic ) :
aCustomer := {} // Declare / define an empty array
USE CUSTOMER
WHILE .NOT. EOF()
AADD(aCustomer, { CUST_ID, CUST_NAME } )
DBSKIP()
ENDDO
Traversing this array is quite simple :
FOR nRecord := 1 TO LEN( aCustomer )
? aCustomer[ nRecord, 1 ], aCustomer[ nRecord, 2 ]
NEXT
or :
a1Record := {}
FOR EACH a1Record IN aCustomer
? a1Record[ 1 ], a1Record[ 2 ]
NEXT
And locating a specific record too:
nRecord := ASCAN( aCustomer, { | a1Record | a1Record[ 1 ] == “CC003” } )
? aCustomer[ nRecord, 1 ], aCustomer[ nRecord, 2 ]
A lot of array functions are ready to use for maintain this array : ADEL(), AADD(), AINS() etc …
Now, let’s see how we could use a hash for achieve this job :
hCustomer := { => } // Declare / define an empty hash
USE CUSTOMER
WHILE .NOT. EOF()
hCustomer[ CUST_ID ] := CUST_NAME
DBSKIP()
ENDDO
Let’s traversing :
h1Record := NIL
FOR EACH h1Record IN hCustomer
? h1Record: __ENUMKEY(),h1Record:__ENUMVALUE()
NEXT
Now, we have a bit complicate our job; a few field addition to the table :
| No: | Field Name | Type | Width | Dec | Decription |
|
1 |
CUST_ID |
C |
5 |
0 |
Id ( Code ) |
|
2 |
CUST_NAME |
C |
10 |
0 |
Name |
|
3 |
CUST_SNAM |
C |
10 |
0 |
Surname |
|
4 |
CUST_FDAT |
D |
8 |
0 |
First date |
|
5 |
CUST_ACTV |
L |
1 |
0 |
Is active ? |
|
6 |
CUST_BLNCE |
N |
11 |
2 |
Balance |
While <key> part of an element of a hash may be C / D / N / L type; <xValue> part of hash too may be ANY type of data, exactly same as arrays.
So, we can make fields values other than first ( ID) elements of an array:
hCustomer := { => } // Declare / define an empty hash
USE CUSTOMER
WHILE .NOT. EOF()
a1Data:= { CUST_NAME, CUST_SNAM, CUST_FDAT, CUST_ACTV, CUST_BLNCE }
hCustomer[ CUST_ID ] := a1Data
DBSKIP()
ENDDO
Let’s traversing :
h1Record := NIL
FOR EACH h1Record IN hCustomer
a1Key := h1Record:__ENUMKEY()
a1Data := h1Record:__ENUMVALUE()
? a1Key
AEVAL( a1Data, { | x1 | QQOUT( x1 ) } )
NEXT
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._
/*
Hash vs Tables
*/
#define NTrim( n ) LTRIM( STR( n ) )
#define cLMarj SPACE( 3 )
PROCEDURE Main()
SET DATE GERM
SET CENT ON
SET COLO TO "W/B"
SetMode( 40, 120 )
CLS
hCustomers := { => } // Declare / define an empty PRIVATE hash
IF MakUseTable()
Table2Hash()
* Here the hash hCustomers may be altered in any way
ZAP
Hash2Table()
ELSE
? "Couldn't make / USE table"
ENDIF
?
@ MAXROW(), 0
WAIT "EOF HashVsTable.prg"
RETURN // HashVsTable.Main()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.
PROCEDURE Table2Hash()
hCustomers := { => }
WHILE .NOT. EOF()
hCustomers[ CUST_ID ] := CUST_SNAM
DBSKIP()
ENDDO
ListHash( hCustomers, "A hash transferred from a table (single value)" )
hCustomers := { => } // Declare / define an empty hash
DBGOTOP()
WHILE .NOT. EOF()
hCustomers[ CUST_ID ] := { CUST_NAME, CUST_SNAM, CUST_FDAT, CUST_ACTV, CUST_BLNCE }
DBSKIP()
ENDDO
ListHash( hCustomers, "A hash transferred from a table (multiple values)" )
RETURN // Table2Hash()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.
PROCEDURE Hash2Table()
LOCAL h1Record,;
c1Key,;
a1Record,;
n1Field
FOR EACH h1Record IN hCustomers
c1Key := h1Record:__ENUMKEY()
a1Record := h1Record:__ENUMVALUE()
DBAPPEND()
FIELDPUT( 1, c1Key )
AEVAL( a1Record, { | x1, n1 | FIELDPUT( n1 + 1 , x1 ) } )
NEXT h1Record
DBGOTOP()
?
? "Data trasferred from hash to table :"
?
WHILE ! EOF()
? STR( RECN(), 5), ''
FOR n1Field := 1 TO FCOUNT()
?? FIELDGET( n1Field ), ''
NEXT n1Field
DBSKIP()
ENDDO
RETURN // Hash2Table()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.
PROCEDURE ListHash( hHash, cComment )
LOCAL x1Pair
cComment := IF( HB_ISNIL( cComment ), '', cComment )
?
? cComment // , "-- Type :", VALTYPE( hHash ), "size:", LEN( hHash )
?
IF HB_ISHASH( hHash )
FOR EACH x1Pair IN hHash
nIndex := x1Pair:__ENUMINDEX()
x1Key := x1Pair:__ENUMKEY()
x1Value := x1Pair:__ENUMVALUE()
? cLMarj, NTrim( nIndex )
* ?? '', VALTYPE( x1Pair )
?? '', x1Key, "=>"
* ?? '', VALTYPE( x1Key )
* ?? VALTYPE( x1Value )
IF HB_ISARRAY( x1Value )
AEVAL( x1Value, { | x1 | QQOUT( '', x1 ) } )
ELSE
?? '', x1Value
ENDIF
NEXT
ELSE
? "Data type error; Expected hash, came", VALTYPE( hHash )
ENDIF HB_ISHASH( hHash )
RETURN // ListHash()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.
FUNCTION MakUseTable() // Make / USE table
LOCAL cTablName := "CUSTOMER.DBF"
LOCAL lRetval, aStru, aData, a1Record
IF FILE( cTablName )
USE (cTablName)
ELSE
aStru := { { "CUST_ID", "C", 5, 0 },;
{ "CUST_NAME", "C", 10, 0 },;
{ "CUST_SNAM", "C", 10, 0 },;
{ "CUST_FDAT", "D", 8, 0 },;
{ "CUST_ACTV", "L", 1, 0 },;
{ "CUST_BLNCE", "N", 11, 2 } }
*
* 5-th parameter of DBCREATE() is alias -
* if not given then WA is open without alias
* ^^^^^^^^^^^^^
DBCREATE( cTablName, aStru, , .F., "CUSTOMER" )
aData := { { "CC001", "Pierce", "Firth", 0d20120131, .T., 150.00 },;
{ "CC002", "Stellan", "Taylor", 0d20050505, .T., 0.15 },;
{ "CC003", "Chris", "Cherry", 0d19950302, .F., 0 },;
{ "CC004", "Amanda", "Baranski", 0d20011112, .T., 12345.00 } }
FOR EACH a1Record IN aData
CUSTOMER->(DBAPPEND())
AEVAL( a1Record, { | x1, nI1 | FIELDPUT( nI1, X1 ) } )
NEXT a1Record
DBGOTOP()
ENDIF
lRetval := ( ALIAS() == "CUSTOMER" )
RETURN lRetval // MakUseTable()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._
