![]() |
|
Published 1999-03-08 Printer-friendly version
Various kinds of files, such as calendars, schedules, ASCII files, accounts, or files on other drives or other machines share the characteristic that multiple physical disk files can have the same structure. It is often desirable to have a single dictionary specification to declare that structure so that a single procedure set (application) can operate on them.
Clarion builds in this capability with the Name
attribute but provides no management capabilities. It is up to the
developer to manage which file is in process at any given time.
In Clarion, there are two keywords you must not confuse,
Label and Name.
Variables and data structures (which include windows, queues,
views and files) are referred to by their Label.
Clarion code always uses the Label.
Name is an attribute. Variables and structures may
or may not have a Name; in fact, they usually do not.
The contents of the Name attribute, if any, are
for use of an external object. This could be another program, like
a database engine or the operating system, or a Clarion DLL, like a
file driver.
In the case of data files, the Name attribute
contains the fully qualified directory entry for the file. For
example, a file declared as:
Customer File,Driver('Topspeed'),Name('foobar')
will look for or create a disk file called
foobar.tps in the current directory. Your code will
never contain this, only "Customer."
To handle multiple physical files from a single logical
declaration use a variable in the Name attribute:
Customer File,Driver('Topspeed'),Name(GLO:FileName)
You create this in the Dictionary Editor by completing the
Full Pathname field on the File Properties worksheet
(Figure 1) and pre-pending an exclamation point.

This is where the fun starts.
If you declare a file like that in Figure 1, your app will not compile. The compiler error makes the reason clear: the variable was not declared. Not only must you declare the variable, you must do so before the file declaration. That means that you have to use the Before File Declarations source embed because the Global Data button places variable declarations after the file declarations.
Thus, global files (files in the dictionary) require a global variable. Files declared at the module or procedure level, in hand code, require only that the variable have the STATIC attribute (though it can be at a higher scoping level).
Next, having added the STATIC attribute, if you try to run the app, it will crash and burn. The variable is empty and the app does not know the DOS name of the file it is supposed to open
File() could not be opened. Error: Invalid Filename(45). You may initialize the variable any time you wish but obviously not later than the first attempt to open the file.
The ABC FileManager class also provides the SetName method to
set the value of the Name attribute. This method
allows you to set the variable directly, without an assignment.
Moreover, you can call this method in a procedure which does not
actually use the file(s) in question (it's a property of the
FileManager, hence available any time after the FileManager has
been instantiated). The app frame comes to mind, as does the global
Procedure Setup embed.
Citing advantages of SetName, Pierre Tremblay observes (in the OOP newsgoup):
The variable in the name attribute for the file structure doesn't need to be exported [from the data app]. The FileManager class is holding a reference for that var.
So, to "initilialise" this variable without having it exported from the DLL, the SetName method is the only way to go.
Note what Pierre says: the variable "doesn't need to be exported." Yes, this means that you do not need to declare the variable in the non-data app(s).
Label as declared on the File
Properties worksheet in Clarion language statements;Name attribute,
initialize it before any attempt to open the file;Name may contain any
O/S-valid string;Full Pathname
entry on the File Properties worksheet with an exclamation
point;Topspeed files support a special syntax to allow multiple tables to be stored in a single file.
By using the special escape sequence '\!' in the NAME() attribute of a TopSpeed file declaration, you can specify that a single .TPS file will store more than one table. (C4 LRM)
When using the TopSpeed driver, if you wish to store multiple tables in a single physical file, separate the file and table names with "\!," as in TUTORIAL\!ORDERS. This refers to the ORDERS table in the TUTORIAL.TPS file. (C5 On-line Help)
The format of the Name entry is
file_name\!table_name which appears to
preclude using a variable in the Name attribute of a
TopSpeed file.
Appearances can be deceiving, for this is not the case.
Designate your variable on the File Properties worksheet and
initialize it in exactly the same way as any other
Name, but use the special syntax:
Authors_ = 'cwjfil\!Authors'
to initialize the variable. In this case, Authors_
refers to the Authors table in
CWJFIL.TPS.
The executable resides in one place but you need the ability to address files anywhere. The file might be in the current directory or in another directory. The files might be on a network drive. You can even map an IP address to a drive letter and use the Internet.

Here, there is one file (set) but multiple possible paths. In these cases, the path tends to be variable while the actual name of the file tends to be a constant. If so, it makes sense to give the Name variable an initial value when it is declared (Figure 2). If you can get the path information separately, from an INI or configuration file or from FileDialog, just concatenate the two.
FilePath = GetIni('JtMatch','FilePath',,'.\JOBTRAK.INI')
Contacts_ = Clip(FilePath) & Clip(Contacts_)
You want to work on one company's accounts then another's. Or you need to update Alice's calendar then Bill's.
You do not have to leave the browse, if you do not wish to (though, obviously, you can and this would be easier to program). All you need to remember is that you must close the current file before selecting the new file. Select the new file, prime the Name variable and refresh the browse.
If you have multiple Tabs and it is your intention that each Tab show a different file in the same browse, you must close, prime and reopen in ThisWindow.TakeNewSelection (ABC) or the ?CurrentTab .. New Selection (Clarion) embed.
Now multiple DLLs are really fun if you use variables.
Each variable must be declared in each of the project's apps.
If you're new to multiple DLLs, you should check the documentation. The important thing is that each app in the project needs to reference the files. But only one should allocate memory for them. This means that in all apps but one the files are declared and the EXTERNAL attribute added. The one app without the EXTERNAL attribute is usually referred to as the "global data DLL" and usually contains only the file declarations.
In the global data DLL, you simply declare the variable and, if desired, give it an initial value.
In every other app, you must also declare each of the variables. Each variable must also have the External and DLL attributes, similar to:
Contacts_ String(64),External,DLL(dll_mode)
to avoid compiler warnings (lots). (You do not need to do this if you use SetName).
Until C5, the method of choice was to create a text file with the necessary declarations and Include it in each application. The required file is usually created by requisitioning and modifying the data declarations from the main source file of the data DLL.
A major enhancement in the C5 Dictionary Editor makes this a thing of the past, totally automating the process.

Using the new Global option in the Dictionary Editor (see Figure 3) creates a file-like structure accessible in your applications as Global Data. That is, after you declare, say, GlobalData, you insert each variable in the same way you would add file fields. So, from the point of view of the Dictionary Editor this is a file but when accessed within an application, it is handled like global data, as intended.
The only restriction is that if you add several variables to this "file," grouping your Name variables, they will share a common prefix.
However, all of your declarations will be included and included correctly in each and every application. That is, your global application settings for dictionary handling (viz., the external flag) will be picked up and applied correctly without further intervention. (You still have to initialize variables, so you still have to do something.)
Note: as of C5EE SR1, Arnor Baldvinsson has discovered, this works correctly only with the ABC templates. The requisite template code was not retro-fit in the Clarion template chain. These lines are found in ABProgram.tpw, 218-37 and should be compared to Program.tpw, 90-99. He states that the new lines can be successfully substituted for the old. A copy of the modified template is available at http://www.cwicweb.com/apps/cwlaunch.dll/download.exe.0
The Clarion language has supported variable file names since its very beginning. In CDD, support was added to the Dictionary Editor and, partially, to the AppGen. But, until Clarion5, we had to hand code many, if not most, of the required declarations.
"When it rains, it pours." Now you have two methods that are about as automated as you can get. How do you choose?-This is the most difficult possible choice: two solid, reliable and easy to use techniques.
Download the demo application.
Steve
Parker started his professional life as a Philosopher but now tries to imitate
a Clarion developer. He has been attempting to subdue Clarion since version 2007 (DOS,
that is). He reports that, so far, Clarion is winning. Steve has been writing
about Clarion since 1993.
Copyright © 1999-2008 by CoveComm Inc. All Rights Reserved. Reproduction in any form without the express written consent of CoveComm Inc., except as described in the subscription agreement, is prohibited.
Clarion Magazine ISSN 1718-9942
One year: $189
(includes all back issues since '99)
Renewals from $139
Two years: $289
Renewals from $239