Archive for Tutorials
Using the Windows Clipboard in FoxPro
Posted by: | CommentsThe Windows Clipboard in easily accessed in FoxPro and Visual FoxPro (VFP). There are currently two commands that directly relate to it. These are _CLIPTEXT to copy and paste text and DataToClip() to copy values from a table. These are not highly sophisticated commands, but they are quick and straightforward and are often the simplest way to transfer data between applications.
Let us explore these two VFP commands further and provide some examples:
_CLIPTEXT System Variable
The _CLIPTEXT System Variable contains the content of the Windows Clipboard and can be engaged to write text to and read text from the Clipboard. This feature has been available since the earliest versions of FoxPro for Windows. The syntax is very simple:
_CLIPTEXT = cExpression && writes cExpression to the Clipboard cExpression = _CLIPTEXT && stores the Clipboard content to cExpression
One of the most common uses of _CLIPTEXT is during program development. Long SQL statements, commands and other strings generated by programs at runtime are often difficult to debug using VFP’s standard tools. In the following code sample an SQL statement is copied to the Windows Clipboard so the developer can paste it into a wordprocessor or other application for additional analysis:
cSQL = cFields + cSource +cFilter + cOrder + cOutput _CLIPTEXT = cSQL SET STEP ON && opens the Trace window and suspends the program
DataToClip Method
DataToClip() copies a set of records to the Windows Clipboard. It is a method of the Application Object or the _VFP System Variable. The field names appear as the first line of the text copied to the Clipboard followed by a separate line for each record. This method has been available since VFP 5 and is only slightly more complicated:
Syntax
ApplicationObject.DataToClip([nWorkArea | cTableAlias] [, nRecords] [, nClipFormat])
Arguments
- nWorkArea
- Specifies the work area number of the table for which records are copied to the Clipboard. If you omit cTableAlias and nWorkArea, records are copied to the Clipboard for the table open in the current work area.
- cTableAlias
- Specifies the alias of the table for which the records are copied to the Clipboard.
- nRecords
- Specifies the number of records copied to the Clipboard. If nRecords is greater than the number of remaining records in the table, all the remaining records are copied to the Clipboard. If nRecords and nClipFormat are omitted, the current record and all remaining records are copied to the Clipboard.
- nClipFormat
- Specifies how fields are delimited. The settings for nClipFormat are:
-
nClipFormat Description 1 (Default) Fields delimited with spaces 3 Fields delimited with tabs - If nClipFormat is omitted, fields are delimited with spaces.
This following copies the current work area from the current record to the end in tab-delimited format:
_VFP.DataToClip(,,3)
This following copies the current work area from the current record to the end in space-delimited format:
_VFP.DataToClip()
There are some important limitations with the DataToClip Method. Memo field content and General fields are not copied, there is no way to apply a filter or select which fields will be copied, and bugs have been found in the method’s implementation in VFP 5 and VFP 6. Also note executing DataToClip() does not move the record pointer.
How to Zip & Unzip Files
Posted by: | CommentsWe receive and send a lot of files as part of our data processing services, and some of our clients are unfamiliar with how to zip and extract files. The following instructions show how to compress and uncompress a file under the Windows, Mac and Linux operating environments. Note than under most systems you can select multiple files as well as folders/directories to zip into the same archive.
Zipping a file creates a compressed version of the file that is usually considerably smaller than the original file. The zipped version of the file has a .zip file extension.
Unzipping a file reverses the zip process and extracts the file from the compressed archive.
IMPORTANT: Please be cautious about opening .zip files from unknown e-mail senders because they can contain viruses. Confirm with known senders before opening a .zip file.
WINDOWS ME, XP, SERVER 2003, VISTA, SERVER 2008 and 7
Compress files (zip files)
- Locate the file you want to compress.
- Right-click the file; then point to Send to and click Compressed (zipped) folder.
A new compressed zip file is created in the same location.
Uncompress files (unzip files)
- Locate the compressed zip file you want to extract.
- Do one of the following:
- To extract a single file or folder, double-click the zip file to open it; then drag the file or folder from the archive to a new location.
- To extract the entire contents of the zip file, right-click the zip file; then click Extract All; then follow the instructions on the screen.
Windows 95, 98, 98SE and 2000 do not have built in zip file support, and it is necessary to utilize third-party software to create and extract zip files.
MAC OS X (10–10.4)
Compress files (zip files)
- Use Finder to locate the file you want to compress.
- Control-click or right-click the file icon; then click Compress [. . .]
A new compressed zip file is created in the same location.
Uncompress files (unzip files)
- Use Finder to locate the compressed zip file you want to extract.
- Double-click the file icon.
The files contained in the archive will be extracted to the same location.
MAC OS X (10.5–SNOW LEOPARD)
Compress files (zip files)
- Use Finder to locate the file you want to compress.
- Control-click or right-click the file icon; then click Create Archive of [. . .]
A new compressed zip file is created in the same location.
Uncompress files (unzip files)
- Use Finder to locate the compressed zip file you want to extract.
- Double-click the file icon.
The files contained in the archive will be extracted to the same location.
LINUX
Compress files (zip files)
- Open a shell prompt.
- Enter the following:
zip -r filename.zip filedirA new compressed zip file is created in the selected location.
Uncompress files (unzip files)
- Open a shell prompt.
- Enter the following:
unzip filename.zipThe files contained in the archive will be extracted to the same location as the zip file.
Making a Data Dictionary
Posted by: | CommentsA data dictionary is a document that catalogs the organization, contents and conventions of a database or collection of databases. It lists in written form all the databases, tables, views, fields and data definitions and often information about the table layouts, the relationships between tables and other details about the database schema.
It does not contain the actual data from the database system, only information necessary to manage and utilize it. It is also not an instruction manual, though a data dictionary is often included as part of an instruction manual.
There is no universal standard as to the level of detail in a data dictionary. What is included is dependent on the audience and the complexity of the database infrastructure. System administrators and programmers will usually have a highly detailed document, sometimes complete with visual depictions, while end users may only have the basics.
Below is an example of a data dictionary for a bookkeeping database with three tables. It shows the kinds of information typically included in a data dictionary, however, it is not meant to be all-inclusive. Other columns that might be provided could show if a field takes null values and the precise points where each field begins and ends. If scientific or technical information is involved, a column indicating normative ranges may be useful. The possibilities are myriad.
A data dictionary is an important part of database system documentation. Devoting the resources needed for a quality document will help insure fewer problems and significantly aid in productivity.
EXAMPLE DATA DICTIONARY FOR A BOOKKEEPING DATABASE
Number of Tables: 3
Table: name of the table. Field: name of the field. Rel: Table relationship key (if any); PK = primary key, FK = foreign key; see Foreign Key Relationships. Type: field data type. Width: field width. Dec: number of decimal points (if any). Description: data definition of the field contents.
Foreign Key Relationships: (1) points to Customers table Id field. (2) points to Sales table Invoice field.
| Table | Field | Rel | Type | Width | Dec | Description |
|---|---|---|---|---|---|---|
| CUSTOMERS | ID | PK | Character | 10 | Customer ID number | |
| NAME | Character | 25 | Customer name | |||
| CUST_TYPE | Character | 1 |
Customer type (key):
A = Active
I = Inactive P = Prospect |
|||
| TERMS | Character | 1 |
Payment terms (key):
N = Net Due
P = Prepaid |
|||
| SALES | INVOICE | PK | Character | 4 | Invoice number | |
| CUST_ID | FK (1) | Character | 10 | Customer ID number | ||
| SAL_DATE | Date | 8 | Date of sale | |||
| SAL_AMOUNT | Numeric | 10 | 2 | Amount of sale | ||
| RECEIPTS | ID | PK | Character | 10 | Unique ID number | |
| INV_NUM | FK (2) | Character | 4 | Invoice number | ||
| REC_DATE | Date | 8 | Date of receipt | |||
| REC_AMOUNT | Numeric | 10 | 2 | Amount of receipt |
Restructuring the pdNickname Database
Posted by: | CommentsAn alternative structure for pdNickname is to have one record per name with the variations in fields next to it. This tutorial explains how to do it.
Matching and merging names can be tricky. How do you relate William Smith with Bill Smith? The pdNickname database can be utilized to match names that are dissimilar because one has a given first name while another has a nickname or other variation, or vice versa.
Out of the box pdNickname is structured to allow immediate compatibility with the greatest number of database systems as well as to make it easy to become familiar with.
The nickname database is setup with two names per record. The first name field contains the names you are looking up, and in the second is a variation for each name—nickname, diminutive, given name, variant, etc. The same name can be listed several times in the first field, each time with a different variation. (See Figure 1.)
FIGURE 1: PDNICKNAME OUT OF THE BOX

If the names compared are Alexander Jones and Alex Jones, all names matching Alexander (NAME-A) are scanned until a variation is found that matches Alex (NAME-B). This works well, but there are other ways of organizing pdNickname that could work even better for you. In fact, we have restructured the table for utilization in our own services.
An alternative structure is to have one record per name and the variations in fields next to it. It is not practical to have separate fields for each variation, which can range from one to over two hundred. So what we do is have two Memo fields (also known as Long Text), one for close variations (relflag = "1") and the other for more distant variations (relflag = "2"), with the string of variations separated by delimiters for easier matching. (See Figure 2.)
FIGURE 2: PDNICKNAME RESTRUCTURED

Note: when browsing a table, normally you cannot see the content of a Memo or Long Text field because the database keeps it in a separate file. For this screenshot we have made the content visible.
Structured this way, when your program finds a match for NAME-A, it then determines if NAME-B can be found in variation field one or variation field two. This can be faster because you only access one record in each search request. The code sample below is an example in Visual FoxPro that illustrates this. Of course other programs use different commands and syntax to achieve the same outcome.
* CODE SAMPLE *- this Visual FoxPro function receives as parameters *- the two first names being compared - it returns a *- variable indicating what matches are found - this *- function is based on the restructuring of the *- pdNickname database described in this tutorial FUNCTION pdNickname LPARAMETERS cNameA, cNameB LOCAL nMatch IF NOT USED("nicknames") USE nicknames ALIAS nicknames IN 0 ENDIF cNameA = PADR(UPPER(ALLTRIM(cNameA)),25," ") cNameB = "/"+UPPER(ALLTRIM(cNameB))+"/" nMatch = 0 IF SEEK (cNameA, "nicknames", "name") DO CASE CASE OCCURS(cNameB, nicknames.variations) > 0 nMatch = 1 CASE OCCURS(cNameB, nicknames.var2) > 0 nMatch = 2 ENDCASE ENDIF RETURN nMatch
pdNickname, like all our Database Products, are structured to satisfy most users from the start. But there are many ways to integrate the databases into your system. It is up to you to determine what works best for you. Do not be afraid to experiment.