Commands

This section describes each member of the Visual DataFlex command set. They are listed alphabetically. These commands make up the syntax of the Visual DataFlex programming language.

Refer to the Visual DataFlex Language Guide for information on the syntax and use of the Visual DataFlex programming language.

Command Categories

Execution Control Commands

File I/O Commands

Variable Declaration Commands


Execution Controls commands

Execution Control Commands

Command | Purpose
Break | Stops execution of a control block.
Case | Allows conditional execution of code based on one or more Boolean-expressions.
For | Executes a block of code in an iteration.
For_All | Implements a constraint oriented file-scanning and processing structure.
If | Conditionally controls the execution of one or more statements of code.
Loop | Terminates a repeating block of code initiated with For, Repeat, or While.
Repeat | Executes a repeating block of code.
Until | Establishes a conditional terminator for repeating blocks of code initiated with Repeat or While.
While | Marks a block of code to be executed repeatedly depending on a condition.


File I/O Commands

See Also: File I/O Functions, Appending Data to an Output File, Sequential File I/O

Command | Purpose
Append_Output | To add output to a sequential file.
Channel Command Component | To enable concurrent opening of more than one output destination or input source, and to enable switching from on channel to another as an application executes.
Close_Input | To close a sequential input file.
Close_Output | To close a sequential output file.
Direct_Input | To open a file or device for sequential input.
Direct_Output | To write output to a sequential file, a printer, or the Windows clipboard.
Get_Channel_Position | Gets the value of the file offset of a sequential file channel.
Get_Channel_Size | To determine the size (in bytes) of a sequential file opened with direct_input or direct_output.
Get_Current_Input_Channel | To return the full path of the user's current directory, including the drive letter.
Get_Current_Output_Channel | To retrieve the number of the sequential file channel currently being used for output.
Read | To read "words" of data from a sequential file, device, or text field and move them to one or more variables.
Read_Block | To read a block of data of a specified size from a sequential file, device, or text field and move it to a variable.
Read_Hex | To read binary data as two-byte hexadecimal numbers.
Readln | To read a line of data from a sequential file, device, text field, or image, and move its "words" to one or more variables.
Set_Channel_Position | To set the input/output channel position pointer to a position.
Write | To write the values of one or more variables to a sequential file, device or text field.
Write_Hex | To write binary data as two-byte hexadecimal numbers.
Writeln | To write the values of one or more variables to a sequential file, device, or text field as a line of data.


Variable Declaration Commands

See Also: Declaring Variables, Array Types, Struct, Framework Data Types

Command | Purpose
Address | Declares one or more Address variables.
BigInt | Declares one or more eight-byte Integer variables.
Boolean | Declares one or more Boolean variables.
Char | Declares one or more one byte signed Integer variables.
Currency | Declares one or more Currency variables.
Date | Declares one or more Date variables.
DateTime | Declares one or more DateTime variables.
Decimal | Declares one or more Decimal variables.
DWord | Declares one or more DWord variables.
Float | Declares one or more single precision 32 bit floating point variables.
Handle | Declares one or more Handle variables.
Integer | Declares one or more Integer variables.
Number | Declares one or more Number variables.
Pointer | Declares one or more Pointer variables.
Real | Declares one or more floating-point numeric variables.
RowId | Declares one or more RowId variables.
Short | Declares one or more two byte signed Integer variables.
String | Declares one or more String variables.
Time | Declares one or more Time variables.
TimeSpan | Declares one or more TimeSpan variables.
UBigInt | Declares one or more eight byte unsigned Integer variables.
UChar | Declares one or more one byte unsigned Integer variables.
UInteger | Declares one or more four byte unsigned Integer variables.
UShort | Declares one or more two byte unsigned Integer variables.
Variant | Declares one or more Variant Integer variables.


Abort

See Also: Runprogram, Exit_Application

Purpose

To end the execution of the current Visual DataFlex program. Control returns to the calling Visual DataFlex program (in the case of nested execution by Chain Wait or Runprogram Wait) or to the operating system.

Syntax

Abort

What It Does

Abort closes all files opened by the current Visual DataFlex program and returns execution to the operating system or to the program from which the Visual DataFlex program was called.

Notes

  • Although Abort may be placed in positions other than the end of the program, it is best not to use Abort too liberally in the source code or your program may become confusing.

  • Abort also closes the Showln console window.


Abort_transaction_Command

Abort_Transaction

See Also: Transactions and DDOs, Begin_Transaction, End_Transaction

Purpose

To cancel a transaction that is in progress.

Syntax

Abort_Transaction

What It Does

This command aborts the transaction and rolls back the transaction in progress to the original state. All locked records are released and the lock count is zeroed. There is no need to issue an Unlock command.

Example

Begin_Transaction

Reread

Move "Data Access Corporation" To Vendor.Name

Save Vendor

Save InvHdr

Move False To bTransOK

For i From 1 To 3

Move i To InvItems.LineNumber

Save InvItems

// if any item is Visual DataFlex, this is a good transaction

If (InvItems.Name Contains "Visual DataFlex");

Move True To bTransOK

Loop

If bTransOK;

Unlock

Else; // Only allow the transaction if VDF is purchased.

Abort_Transaction

// The next line has no effect if the transaction is aborted.

End_Transaction

Notes

  • This command has no effect if executed outside a Begin_Transaction... End_Transaction command block, because it only affects transactions in progress.

  • The abort transaction command will not jump to the End_Transaction command automatically. The flow of the program will continue on the next line.".


Add

See Also: Math Functions, Move, Subtract

Purpose

To perform addition.

Syntax

Add {value} to {variable}

Where {value} is a variable, a constant, or an expression; and {variable} is any variable.

What It Does

The Add command adds the value of {value} to the value of {variable}.

The following two lines of code do the same thing:

Move (invoice.amount + vendor.total_due) to vendor.total_due

Add invoice.amount to vendor.total_due

Using add and subtract commands (rather than expressions) can make your programs easier to understand. This is especially true when using the command with expressions.

Add (invoice.amount - invoice.discount) To vendor.total_due

instead of

Move (vendor.total_due + (invoice.amount – invoice.discount)) To vendor.total_due


Address

See Also: Declaring Variables, Variable Declaration Commands, Struct, Alloc, Realloc

Purpose

Declares one or more Address variables.

Syntax

To declare Address variables

Address {identifier} […{identifier}]

Where

  • {identifier} is a variable name for the new address variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Address

Address{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Address command declares a variable to hold a memory address.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Function AllocateBlock Returns Address

Address aMyVar

Move (alloc(1024)) To aMyVar // allocate a memory block

Function_Return aMyVar

End_Function

This example declares a variable named aMyVar of type address and initializes it.

Address[] aMemoryLocations

This example declares 1 dynamic array variable, named aMemoryLocations, containing an undefined number of elements of type Address.

Address[5] aMemoryLocations

This example declares 1 static array variable, named aMemoryLocations, containing 5 elements of type Address.

Address[][3] aMemoryLocations

This example creates a two-dimensional dynamic array variable named aMemoryLocations, containing an undefined number of elements of type Address. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Address variable, you should use the global_variable command to do so.


Append_Output

See Also: File I/O Commands, Close_Output, Direct_Input, Get_Channel_Position, Set_Channel_Position, Write, Writeln, Seqeof, Appending Data to an Output File, Channel command component

Purpose

To add output to a sequential file.

Syntax

Append_Output [Channel {channel-number}] {filename}

Where {channel-number} is a constant or variable between 0 and 9. Default value is 1. {filename} is the name of the file to append to. Filenames with embedded spaces must be quoted.

What It Does

Append_Output sets the destination for sequential output (output from the Write and Writeln commands) of the program. Append_Output differs from Direct_Output in that Append_Output adds output to an existing file whereas Direct_Output starts writing the sequential file at the beginning of the file.

The channel feature is used when you need more than one output destination or more than one input source at the same time in your program. If the channel is omitted, the default channel for sequential output (1) will be used.

The position at which data is written into the file can be changed with the Set_Channel_Position command, and queried with the Get_Channel_Position command. If Set_Channel_Position is used to append to some point within the file, the remaining contents are overwritten.

Example

Integer iCount

String sBuffer

// Create a text file

Direct_output "hello.txt"

For iCount From 1 To 10

Writeln "Line: " iCount " - Hello!"

Loop

Close_Output

// Open file for input.

Direct_Input "hello.txt"

Showln "Contents of Hello.Txt"

For iCount From 1 To 10

// Read from the text file.

Readln sBuffer

Showln sBuffer

Loop

Close_Input

// Write another 10 lines to the file.

// Append output to hello.txt

Append_Output "hello.txt"

For iCount From 11 To 20

Writeln "Line: " iCount " - Hello!"

Loop

Close_Output

Notes

  • If {filename} does not exist when an Append_Output is executed, a new file is created.

  • When Append_Output is issued for a channel where a sequential output file is already open, the open file is closed, and the new file is opened.

  • If a filename is given with no subdirectory path, Visual DataFlex will search the directories listed in the DFPATH of the program.


Attach

See Also: Relate, Save,

Purpose

To move the primary key from each parent table into the matching external keys of the named child database tables.

Syntax

Attach {child-table} [… {child-table}]

Where {child-table} is the name or filelist number of one or more child tables.

What It Does

Each relationship indicates a many-to-one connection between parent and child tables. Many-to-one relationships have the following properties:

  1. The parent table has a primary key, a key that uniquely identifies each record. It is composed of one or more fields.

  2. The primary key of the parent table is also stored in the child table. It is called an external key.

Attach moves the primary key from each parent table into the matching external keys of the named child tables.

Use Database Builder to set up relationships between parent and child tables.

Example

In the following example, a table of locations serviced is used to access a large vendor table. The location table is read and if there is a record, the external keys (city and state) are moved into a vendor table.

// Open tables.

Open vendor

Open location

Move "Fl" to location.state

Move "Miami" to location.city

// Assume an overlapped state-city field.

Find EQ location.state_city

// If there is a record in the location, find a vendor for this city.

If (Found) Begin

// Move related fields into parent table transaction buffer.

Attach vendor

// Now we can find by state_city in the child table vendor.

Find EQ vendor.state_city

End

If the command includes multiple parent tables, attaches are done to such tables in the order in which they are named.

Attaches will be done only to those child tables which are open, using whatever data is in the parent table at the time of attach. If a parent table is open, but no record is in its buffer, attach will be performed on the clear buffer of the parent table, thereby clearing the external keys of the child tables.

Notes

  • Attach moves data from parent tables to child tables. The relate command moves data from child tables to parent tables.

  • The save command automatically executes an attach, eliminating the requirement to use the attach command in most situations.

  • You can also pass table numbers to the attach command.


Begin

See Also: End, If

Purpose

To define the beginning and end of a block of commands whose execution is to be controlled by other commands.

Syntax

Begin

…

End

What It Does

Begin defines the start of a block of commands. End defines the end of the block. Execution of the commands in the block will only occur if the Begin command itself executes.

Example

Procedure OnClick

    Integer bReady      // A flag to see if we can continue...

    Integer iTimes

    Show "This is Hal. Earthling, you are truly prepared"

    Showln " to go forward today..."

    Move 0      To iTimes

    Move MBR_NO To bReady

    While (bReady = MBR_NO)

        Move (YesNo_Box("Haven't you forgotten something? ", ;

            "Important!",  MB_DEFBUTTON2) ) to bReady

        Increment iTimes

        If (bReady=MBR_NO) Begin

            // Begins can be nested

            If (iTimes eq 1) Begin

                 Showln

                 Show "I'm sure you have"

            End

            Else;

                 Show "I insist. You have"

            Show " forgotten something."

            If (iTimes > 10) Begin

                Showln "Please insert floppy diskette into a CD ROM drive."

                If (iTimes > 20) Begin

                    Showln "*** This does not compute..."

                    If (iTimes > 40) ;

                        Showln "This is not a drill..."

                End

            End

            Showln "You will be given another chance before we go on"

            Showln

        End

     Loop

End_Procedure

Notes

  • Begin ... End blocks may be nested up to 40 levels deep. You may freely use other block-control commands (loops) within begin … end blocks, but they may not overlap; i.e., you must terminate a block before an outer block can continue.


Begin_Transaction

See Also: Transactions and DDOs, Abort_Transaction, End_Transaction, Lock, Unlock

Purpose

To explicitly mark the beginning of a database transaction.

Syntax

Begin_Transaction

What It Does

This command is used to mark the beginning of a database transaction. In case of a rollback, the entire transaction is rolled back. A side effect of the Begin_Transaction command is to execute a Lock command.

Example

Begin_Transaction

Reread

Move "Data Access Corporation" To vendor.name

Save vendor

Save invheader

Move FALSE To bTransOK

For iCount From 1 To 3

Move iCount To invitems.linenumber

Save invitems

// if any item is DataFlex, this is a good transaction

If (invitems.name Contains "DataFlex");

Move TRUE To bTransOK

Loop

If bTransOK;

Unlock

Else; // Only allow the transaction if VDF is purchased.

Abort_Transaction

// The next line has no effect if the transaction is aborted.

End_Transaction

Notes

  • A database table may only be used in a transaction if transaction processing is enabled. You can set this in the parameter tab of Database Builder. If any table in a set of tables participating in a transaction is not properly set up for transaction processing, transaction control for the application as a whole will fail.

  • Sometimes the programmer does not explicitly set the beginning and end of a transaction. In this case Visual DataFlex will use the first lock command to mark the start of a transaction, and the last unlock to mark the end of a transaction.

  • You do not need to explicitly use Begin_Transaction… End_Transaction for database operations that are executed and controlled by DataDictionary objects.

  • Table-manipulation commands like Make_File and Zerofile may not be used within a transaction.

  • The Begin_Transaction and End_Transaction commands must be matched within the same scope. The following structure is not legal:

Begin_Transaction

…

If (bTest) Begin

…

End_Transaction

End


BigInt

See Also: Declaring Variables, Variable Declaration Commands, Struct, Integer, UBigInt

Purpose

Declares one or more eight-byte Integer variables.

Syntax

To declare BigInt variables

BigInt {identifier} [… {identifier}]

Where

  • {identifier} is the name of a new BigInt variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type BigInt

BigInt{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The BigInt command declares integer variables of eight bytes in the range whose range is approximately -8 * 10^18 to 8 * 10^18

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

BigInt biMyVar

Move 1000000000000000 To biMyVar

End_Procedure

This example declares a BigInt variable named biMyVar and initializes its value.

BigInt[] biDriveSizeInBytes

This example declares 1 dynamic array variable, named biDriveSizeInBytes, containing an undefined number of elements of type BigInt.

BigInt[5] biDriveSizeInBytes

This example declares 1 static array variable, named biDriveSizeInBytes, containing 5 of elements of type BigInt.

BigInt[][3] biDriveSizeInBytes

This example creates a two-dimensional dynamic array variable named biDriveSizeInBytes, containing an undefined number of elements of type BigInt. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • You may do calculations with BigInt variables, but any decimal values that results will be truncated without report of error.

  • If you need to define a global BigInt variable, you should use the global_variable command to do so.


Boolean

See Also: Declaring Variables, Variable Declaration Commands, Struct, Boolean Expressions

Purpose

Declares one or more Boolean variables..

Syntax

To declare Boolean variables

Boolean {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a Boolean type variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Boolean

Boolean{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Boolean command declares Boolean variables.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

Boolean bSmoker bMarried bEmployed

Move False To bSmoker

Move False To bMarried

Move True To bEmployed

End_Procedure // Test

This example declares 3 Boolean variables: bSmoker, bMarried and bEmployed and initializes their values.

Boolean[] bPassFail

This example declares 1 dynamic array variable, named bPassFail, containing an undefined number of elements of type Boolean.

Boolean[5] bPassFail

This example declares 1 static array variable, named bPassFail, containing 5 of elements of type Boolean.

Boolean[][3] bPassFail

This example creates a two-dimensional dynamic array variable named bPassFail, containing an undefined number of elements of type Boolean. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • The Boolean type is a simple type that is used for declaring variables for storing Boolean values. Boolean values are denoted by the predefined constants True and False.

  • The Integer value of False is 0 and the Integer value of True is 1.

  • If you need to define a global Boolean variable, you should use the global_variable command to do so.


Break

See Also: Boolean Expressions, Execution Control Commands, For, Loop, Repeat, Until, While, Boolean

Purpose

Stops execution of a control block.

Syntax

Break [Begin]

What It Does

Break stops execution of a control block. A block is a Begin ... End, Repeat ... Until, a For ... Loop, or a While ... Loop construction.

Break with no argument causes execution to jump to the first command after the end of the block. A Break Begin causes execution to go back to the start of a loop.

Example

Procedure OnClick

Integer iCount // a counter

String sValue // contents of a string

String sTest // test character

// loop through the characters of the string 'hello world'

Move "hello world" To sValue

For iCount From 1 To (length(sValue))

Move (Mid(sValue, 1, iCount)) To sTest

// if the character 'w' is found, quit the loop.

If (sTest = 'w');

Break

Else; // show progress

Showln "Character number " iCount " is a [" sTest "]"

Loop

End_Procedure

Notes

  • Note that break only exits the current block (the block executing when the break command is executed).

  • The following code block is a reworking of the For ... Loop from the previous example. Note that it contains an unintentional bug, because the break quits the Begin ... End block, but not the For ... Loop:

Move "hello world" To sValue

For iCount From 1 To (length(sValue))

Move (Mid(sValue, 1, iCount)) To sTest

// If the character 'w' is found, quit the loop.

If (sTest = 'w') Begin

Showln "found a 'w'"

Break // BUG! The break quits the begin…end, not the for…loop,

// so all the characters in the string will print.

End

Else; // show progress

Showln "Character number " iCount " is a [" sTest "]"

Loop


Broadcast

See Also: Broadcast_Focus, Delegate, Forward, Get, Send, Set

Purpose

To send a message to child objects of an object. It can also be used to send a message to all descendents of an object. When sent to the desktop, all objects in the program can receive the message.

Syntax

Broadcast [Recursive | Recursive_Up] [No_Stop] {Get | Set | Send} {message…}

Where {message..} is the name and syntax of the message to broadcast. Refer to the Get, Set or Send commands for more information on their respective syntax.

What It Does

The broadcast command sends a message to the children of an object. The child objects receive the message in the order in which the children were first created.

The recursive option allows a message to be sent to all generations descended from the object, instead of just its immediate children. The message will be sent to a child and then to all of that child's children, before proceeding to the next child This option allows the message to be sent to the parent before it is sent to its children. This is useful when the parent of an object must be notified of an event before its children are.

If the Recursive_Up option is used, the recursion will proceed from the lowest level of descendence up to the original recipient object. This method of recursion will allow the lower levels to process the message before their parent objects process the message. Broadcast in this mode can be used to deactivate child objects, destroy child objects, set values of properties, and so forth. This mode is well suited for left-right tree navigation, where every node on the tree is an object.

If a recipient object is not specified in the Get, Set, Send, all objects will receive the message.

When Broadcast is used with the Get command, the broadcasting will terminate when the first non-zero integer value is returned. This is one way to build a system where the first object that answers a broadcasted request will be used.

The broadcast command will stop when the broadcasted message returns a value not equal to zero. With the No_Stop option, a Broadcast Get|Set|Send instruction will continue broadcasting when the message returns a non-zero value. Since only functions should return values, this is primarily true for a Broadcast Get usage. However, there are procedures in Visual DataFlex (runtime and packages) that do return a value. So, the No_Stop option can be useful when calling functions and procedures. When the broadcast finishes, the return value will be that of the last object that processed the message.

Example

Use windows.pkg

Class cTreeNode Is An Array

Procedure Construct_Object

Property Integer piLevel

End_Procedure

Procedure CreateNode Integer iMaximumLevels Integer iNodesPerLevel

Integer i

For i From 1 To iNodesPerLevel

Object oNewNode Is A cTreeNode

Set piLevel To (piLevel(parent(Self))+1)

If (piLevel(Self) <= iMaximumLevels);

Send CreateNode iMaximumLevels iNodesPerLevel

End_Object

Loop

End_Procedure

Procedure VisitNode

Showln "Visiting Node: " (Object_Id(Self)) " Level: " (piLevel(Self))

End_Procedure

End_Class

Class cTree Is An Array

Procedure Construct_object

Property Integer piMaximumLevels

Property Integer piNodesPerLevel

Object oBaseNode Is A cTreeNode

Set level To 1

Showln "Creating Node: " (Object_Id(Self)) " Level: " ;

(piLevel(self))

End_Object

End_Procedure

Procedure Populate

Send CreateNode To (oBaseNode(Self));

(piMaximumLevels(Self)) (piNodesPerLevel(Self))

End_Procedure

Procedure Navigate

Showln "Recursive Up"

Broadcast Recursive_Up Send VisitNode To (oBaseNode(Self))

Showln "Recursive Down"

Broadcast Recursive Send VisitNode To (oBaseNode(Self))

End_Procedure

End_Class

Object oTest is A Button

Object oTree Is An cTree

Set piMaximumLevels To 3

Set piNodesPerLevel To 3

Send Populate

End_Object

Procedure OnClick

Send Navigate To oTree

End_Procedure

End_Object

Notes

  • Prior to the command sending the message, the Delegation_Mode of each focus child is temporarily changed to No_Delegate_Or_Error for receipt of a Broadcast message. This is necessary so that if the child does not understand the message, it will not be delegated back to the parent, and possibly cause an endless loop. After the message returns the Delegation_Mode is restored to its prior value.

  • As an alternative to the Broadcast command, the Broadcaster class may be used if the desired group of objects is not descended from the same parent.


Broadcast_Focus

See Also: Broadcast, Delegate, Forward, Get, Send, Set

Purpose

To send a message to child focus objects of an object.

Syntax

Broadcast_Focus [Recursive | Recursive_Up] [No_Stop] {Get | Set | Send} {message…}

Where {message..} is the name and syntax of the message to broadcast. Refer to the Get, Set or Send commands for more information on their respective syntax.

What It Does

The Broadcast_Focus command sends a message to the focus children of an object. Focus children are those objects who are at the next level of the focus tree. These objects receive the message in the order in which they appear in the focus tree.

The primary difference between the Broadcast and Broadcast_Focus commands is that the Broadcast command uses the object tree for its navigation from node to node whereas Broadcast_Focus uses the focus tree.

The Recursive option allows a message to be sent to all generations descended from an object in the focus tree, instead of just its immediate focus children. The message will be sent to an object's focus child and then to all of the objects in the next level of the focus tree of the focus child. It will continue to descend down to the bottom of the tree before proceeding to the next focus child. This option allows the message to be sent to the focus parent before it is sent to its focus children. This is useful when the parent of an object must be notified of an event before its children are.

If the Recursive_Up option is used, the recursion will proceed to the lowest level that it will go, then send the message to all objects on the way out of the function. This method of recursion will allow the lowest levels to be affected before the parent. It may be used to deactivate children, destroy children, set values of properties etc.

If a recipient object is not specified in the Get, Set, Send, all activated objects will receive the message.

When Broadcast_Focus is used with the Get command, broadcasting will terminate when the first non-zero integer value is returned from an object in the focus tree of the object.

The Broadcast_Focus command will stop when the broadcasted message returns a value not equal to zero. With the No_Stop option, a Broadcast_Focus Get|Set|Send instruction will continue broadcasting when the message returns a non-zero value. Since only functions should return values, this is primarily true for a Broadcast_Focus Get usage. However, there are procedures in Visual DataFlex (runtime and packages) that do return a value. So, the No_Stop option can be useful when calling functions and procedures. When the Broadcast_Focus finishes, the return value will be that of the last object that processed the message.

Notes

  • Prior to the command sending the message, the Delegation_Mode of each focus child is temporarily changed to No_Delegate_Or_Error for receipt of a Broadcast message. This is necessary so that if the child does not understand the message, it will not be delegated back to the parent, and possibly cause an endless loop. After the message returns the Delegation_Mode is restored to its prior value.

  • The broadcaster class provides a similar feature for objects that are not related by either the object tree or the focus tree.


Call_Driver

See Also: Database API Attributes, Implementing Callback Functions, Load_Driver, Unload_Driver

Purpose

To directly access a database driver-specific function.

Syntax

Call_Driver {tableHandle} {sDriverName} ;

Function {iDriverFunction} ;

Callback {callbackObject} ;

Passing {sArg1} {sArg2} {iArg} ;

Result {returnValue}

Argument Explanation

{tableHandle} Is a handle or number to the table that you wish to affect. The table must have been opened.

{sDriverName} A string containing the name of the driver.

If you pass {tableHandle}, you do not need to pass a driver name explicitly, so you pass "" -- {tableHandle} will be used to determine the driver. If you pass {sDriverName}, you do not need to pass {tableHandle}, so you can pass 0.

{iDriverFunction} An integer whose value identifies one of {sDriverName}'s functions.

{callbackObject} Is a handle to an object that will receive the Callback message during the sort operation. Refer to Implementing Callback Functions for more information.

{sArg1} A string variable containing the first argument (if any) for the driver function; must be a variable, and may contain modified data when the driver call is finished.

{sArg2} A string variable containing the second argument (if any) for the driver function; must be a variable, and may contain modified data when the driver call is finished.

{iArg} An integer containing the third argument (if any) for the driver function.

{returnValue} Name of a variable to contain the value returned by the driver function; must be a variable, and may contain modified data when the driver call is finished.

What It Does

Each database driver has certain specific functions. Call_Driver is used to call these from within Visual DataFlex. The parameters to this command were set up to be as generic as possible. Most instances will not use all of them.

Example

DataFlex Driver

This section documents how to use this command for the DataFlex driver. Notice that since all parameters must be used, many null strings and zeroes appear in these examples.

Procedure IncreaseSortBufferSize

String sNull

Boolean bBufferSet

Integer iSortBufferSize

move "" to sNull

move (1024 * 128) to iSortBufferSize

Call_Driver 0 "DATAFLEX" Function FLEX_SET_MAX_SORT_BUFFER ;

Callback 0 ;

Passing sNull sNull iSortBufferSize ;

Result bBufferSet

End_Procedure // IncreaseSortBufferSize

This example sets the maximum amount of memory to be used during sorting to the value of integer iSortBufferSize, which might be (1024 * 128) for 128 Megabytes. FLEX_SET_MAX_SORT_BUFFER interprets its argument as Kilobytes (KB).

Function RetrieveSortBufferSize returns Integer

String sNull

Boolean bBufferSet

Integer iSortBufferSize

move "" to sNull

Call_Driver 0 "DATAFLEX" Function FLEX_GET_MAX_SORT_BUFFER ;

Callback 0 ;

Passing sNull sNull iSortBufferSize ;

Result bBufferSet

function_return iSortBufferSize

End_Function // RetrieveSortBufferSize

This example retrieves the maximum amount of memory to be used in sorting into an integer variable called iSortBufferSize, which is then returned by the sample function.

Procedure RepairDataFlexTable

String sTableName sMode

Boolean bRepairComplete

move "Employee" to sTableName

move "0" to sMode

Call_Driver 0 "DATAFLEX" Function FLEX_REPAIR_FILE ;

Callback 0 ;

Passing sTableName sMode 0 ;

Result bRepairComplete

End_Procedure // RepairDataFlexTable

This example will repair the DataFlex table named in the value of string variable sTableName. The sMode argument has a value of "0", which specifies to sort the table as part of the repair process. If this argument is non-zero, the table will not be sorted, which means that only errors in the table header (.HDR) file will be fixed.

Function RepairNeeded returns String

String sTableName sMode sRepair

Integer iRepairNeeded

move "Employee" to sTableName

move "0" to sMode

Call_Driver 0 "DATAFLEX" Function FLEX_GET_REPAIRS_NEEDED ;

Callback 0 ;

Passing sTableName sMode 0 ;

Result iRepairNeeded

if (iRepairNeeded = FLEX_HEADER_OK) ;

move "None" to sRepair

else if (iRepairNeeded = FLEX_BLOCK0_BAD) ;

move "Bad Block 0" to sRepair

else if (iRepairNeeded = FLEX_HEADER_BAD) ;

move "Bad Header" to sRepair

else if (iRepairNeeded = FLEX_HEADER_INTEGRITY_OFF) ;

move "Header Integrity Turned Off" to sRepair

else if (iRepairNeeded = FLEX_HEADER_UNREADABLE) ;

move "Header Unreadable" to sRepair

function_return sRepair

End_Function // RepairNeeded

This example returns a constant representing the type of repair(s) needed to iRepairNeeded and the function returns a String representation of this to the calling method.

Procedure TurnOffIndexOptimization

String sNull

Boolean bOptimized

move "" to sNull

Call_Driver 0 "DATAFLEX" Function FLEX_SET_INDEX_OPT ;

Callback 0 ;

Passing sNull sNull FLEX_INDEX_OPT_OFF ;

Result bOptimized

End_Procedure // TurnOffIndexOptimization

This example sets index optimization to off.

Function IndexOptimizationMode returns String

String sNull sOptMode

Integer iRepairNeeded

move "0" to sMode

Call_Driver 0 "DATAFLEX" Function FLEX_GET_INDEX_OPT ;

Callback 0 ;

Passing sNull sNull 0 ;

Result iOptimizeMode

if (iOptimizeMode = FLEX_INDEX_OPT_ON) ;

move "None" to sOptMode

else if (iOptimizeMode = FLEX_INDEX_OPT_OFF) ;

move "Bad Block 0" to sOptMode

else if (iOptimizeMode = FLEX_INDEX_OPT_PERMISSIVE) ;

move "Bad Header" to sOptMode

function_return sOptMode

End_Function // IndexOptimizationMode

This example retrieves the index-optimization mode to the variable iOptimizeMode and the function returns a String representation of this to the calling method.

ON is the default setting, allowing programs to use index data where all segments used are not set case-insensitive. OFF prohibits all use of index data by programs; the record buffer is always loaded after every find. PERMISSIVE allows the use of all index data, including that in case-insensitive index segments.

Function StrictTransactions returns Boolean

String sNull

Boolean bStrictTransactions

move "0" to sMode

Call_Driver 0 "DATAFLEX" Function FLEX_GET_STRICT_TRANSACTIONS ;

Callback 0 ;

Passing sNull sNull 0 ;

Result bStrictTransactions

function_return bStrictTransactions

End_Function // StrictTransactions

This example gets the state of enforcement of the requirement for the NetWare shell (True or False) on server atomic files to the variable bStrictTransactions.

Procedure SetStrictTransactions Boolean bStrictTransactions

String sNull

integer iVoid

move "0" to sMode

Call_Driver 0 "DATAFLEX" Function FLEX_SET_STRICT_TRANSACTIONS ;

Callback 0 ;

Passing sNull sNull bStrictTransactions ;

Result iVoid

End_Function // SetStrictTransactions

This example sets FLEX_SET_STRICT_TRANSACTIONS to the value of Boolean function parameter bStrictTransactions.

Notes

  • For specific commands and parameters to use this command with a non-DataFlex driver, refer to the database-driver documentation.

  • A callback function can be implemented to display the progress of long sort operations. Refer to Implementing Callback Functions for further information.


Case

See Also: Execution Control Commands, If command, If function

Purpose

Allows conditional execution of code based on one or more Boolean-expressions.

Syntax

Case Begin

Case {Boolean-expression1}

{statement1}

Case Break

Case {Boolean-expression2}

{statement2}

Case Break

Case {Boolean-expression3}

{statement3}

Case Break

…

Case Else

{else-statement}

Case End

What It Does

If {Boolean-expression1} is True then {statement1} is executed, if {Boolean-expression2} is True then {statement2} is executed, if {Boolean-expression3} is True then {statement3} is executed, and so on. If none of the Boolean-expressions are true then the {else-statement} is executed.

The Case statement will allow any number of Boolean-expressions and statements to be executed. The Case Else and {else-statement} are optional. If it is not present then execution will continue at the next statement in the program when all the Boolean expressions are False.

It is normal to end each case with a Case Break command. The Case Break command will immediately halt execution of the Case statement and program execution will continue at the next statement in the program (following the Case statement). If you do not end each case with a Case Break then execution will continue down through all the cases until a Case Break is executed or the Case statement ends.

Example

Case Begin

Case (sAnimal = "Cat")

Move ("Meow") To sNoise

Case Break

Case (sAnimal = "Dog")

Move ("Arf") To sNoise

Case Break

Case (sAnimal = "Bird")

Move ("Tweet") To sNoise

Case Break

Case Else

Move ("") To sNoise

Case End

Example

String sAnimal

Move "Dog" To sAnimal

Case Begin

Case (sAnimal = "Cat")

Showln "Meow"

Case (sAnimal = "Dog")

Showln "Arf"

Case (sAnimal = "Bird")

Showln "Tweet"

Case break

Case Else

Showln "or else"

Case End

The above sample demonstrates a common mistake in implementing the case command.

The first showln statement will not be executed. The showln statements will start executing after the second case, which is the first case that evaluates to true, until a break (or a Case End) is found.

The result of this case will be that "Arf" and "Tweet" will be displayed, because the second case (dog) is missing a "Case break" statement.


CD_End_Object

See Also: CD_Popup_Object, End_Object, Object

Purpose

To implement dynamic object creation and destruction for popup modal objects and deferred views. It takes the place of End_Object in normal object creation and destruction.

Syntax

Cd_End_Object

What It Does

CD_End_Object is used in place of the End_Object command when declaring a popup object, an object that is created by sending the popup message. The popup object and all of its children are destroyed when the object is deactivated.

Example

The following example shows how to create a selection list that will popup when the popup message is sent to it.

// Create a popup selection list.

Cd_Popup_Object oCustListPromptList Is A selection_list

:

Cd_End_Object

// This is how to pop it up on the screen.

// You might use this to pop the window up after the user hits a button.

Send popup To oCustListPromptList

You may also use Cd_End_Object at the end of a deferred view. In this example a view, oMyViewObject, is created that is activated by the message AccessMyView:

Deferred_View AccessMyView For Object oMyViewOject Is An entry_view_client

:

Cd_End_Object

Notes

  • If a dynamically created contains child objects, use the standard object/End_Object commands to create them.


CD_Popup_Object

See Also: CD_End_Object, End_Object, Object

Purpose

To implement dynamic object creation and destruction for popup modal objects. It is used in place of the Object command to create these objects.

Syntax

Cd_Popup_Object {object-name} Is A {class-name}

Where {object-name} is the name of the object being created; {class-name} is the class to which the object belongs.

What It Does

CD_Popup_Object is used in place of the object command when declaring a popup object. The object created will be activated when the popup message is sent to it. The popup object is not destroyed when the object is deactivated unless its Destroy_Object_State has been set true.

Example

The following example shows how to create a customer lookup.

CD_Popup_Object oCustomer_sl is a dbModalPanel

Set Label to "Customer List"

Set Size to 148 242

Set Location to 4 5

Object Customer_DD is a Customer_DataDictionary

End_Object // Customer_DD

Set Main_DD to Customer_DD

Set Server to Customer_DD

Object oSelList is a dbList

Set Main_File to Customer.File_Number

Set Ordering to 1

Set Size to 100 227

Set Location to 6 6

Begin_Row

Entry_Item Customer.Customer_number

Entry_Item Customer.Name

End_Row

Set Form_Width item 0 to 35

Set Header_Label item 0 to "Number"

Set Form_Width item 1 to 180

Set Header_Label item 1 to "Customer Name"

End_Object // oSelList

CD_End_Object

Notes

  • If a dynamically created object contains child objects, use the standard Object/End_Object commands to create them.


Char

See Also: Declaring Variables, Variable Declaration Commands, Struct, UChar

Purpose

Declares one or more one byte signed Integer variables.

Syntax

To declare Char variables

Char {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Char variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Char

Char{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Char command declares integer variables of one byte in the range -128 to +127.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Example

Procedure Test

Char cMyVar

Move 1 To cMyVar

End_Procedure

This example declares a Char variable named cMyVar and initializes its value to 1.

Char[] cLengthOfJumpInFeet

This example declares 1 dynamic array variable, named cLengthOfJumpInFeet, containing an undefined number of elements of type Char.

Char[5] cLengthOfJumpInFeet

This example declares 1 static array variable, named cLengthOfJumpInFeet, containing 5 of elements of type Char.

Char[][3] cLengthOfJumpInFeet

This example creates a two-dimensional dynamic array variable named cLengthOfJumpInFeet, containing an undefined number of elements of type Char. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Char variable, you should use the global_variable command to do so.


Channel_Command_Component

See Also: File I/O Commands

Purpose

To enable concurrent opening of more than one output destination or input source, and to enable switching from on channel to another as an application executes.

Syntax

Channel {channelNumber}

Where {channelNumber} is the number of the channel.

Values

0 - 9

What It Does

The channel command component is an option in the append_output, close_input, close_output, direct_input, direct_output, read, read_block, readln, write and writeln commands.

Use the New_Seq_Channel function to obtain a new channel, and the Seq_Release_Channel function to release a channel that is no longer used. See the section Sequential File Input and Output to read more about file input and output (I/O) in Visual DataFlex.

It is recommended to always use channels when doing any file I/O to make your code more reusable.

Example

Use seq_chnl.pkg

Procedure WriteTwoFiles

integer iChOut1 iChOut2

string sFileOut1 sFileOut2

// specify the file name of the first output file

move "c:\temp\OutFile1.txt" to sFileOut1

// specify the file name of the first output file

move "c:\temp\OutFile2.txt" to sFileOut2

// obtain 2 open channels

move (Seq_New_Channel()) to iChOut1

move (Seq_New_Channel()) to iChOut2

direct_output channel iChOut1 sFileOut1 // open output channel

direct_output channel iChOut2 sFileOut2 // open output channel

writeln channel iChOut1 "This is line 1 of output file 1"

writeln channel iChOut2 "This is line 1 of output file 2"

writeln channel iChOut1 "This is line 2 of output file 1"

writeln channel iChOut2 "This is line 2 of output file 2"

writeln channel iChOut1 "This is line 3 of output file 1"

writeln channel iChOut2 "This is line 3 of output file 2"

close_output channel iChOut1 // close output channel

close_output channel iChOut2 // close output channel

// release both channels for reuse

send Seq_Release_Channel iChIn

send Seq_Release_Channel iChOut

End_Procedure // WriteTwoFiles

This example writes 3 lines to 2 different output files. Using the channel command component, the code is able to alternate writing between the 2 files.

Notes

  • Whenever a channel is specified and subsequent lines of code do any I/O without specifying a channel, the last specified channel will be used. This is a common cause of coding errors.

Example

writeln channel iChOut1 "This is line 1 of output file 1"

writeln "This is line 1 of output file 2"

If the above change was made to the example in the What It Does section, both lines would be written to the file open in channel iChOut1.


Class

See Also: Visual DataFlex Classes, End_Class, End_Object, Forward, Function, Object, Procedure, Property

Purpose

To create a new Visual DataFlex object class. A class defines a Visual DataFlex object's behavior.

Syntax

Class {sub-class} Is A {super-class}

:

End_Class

Where:

  • {sub-class} is the name of the new class to create; and {super-class} is the name of the class that the new class is based upon.

  • {sub-class} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The class command creates a new class {sub-class} with all the properties, function and procedure methods of its parent class, {super-class}. These inherited characteristics are then modified in the succeeding commands (until the End_Class command) to produce the new class.

{Sub-class} may be any unique class name. Objects of the new class are created using the Object command. The {sub-class} name should be descriptive of its use in the program.

{super-class} is the class from which the new class inherits. The new class begins with all of the procedures, functions, properties and key definitions of the parent class. The job of the Class command is to add, change, or cancel the abilities of {super-class} to achieve the goals of the new {sub-class}.

{super-class} must be defined in the program before it is used as a parameter to the Class command.

Class definitions are commonly placed in package files, so that the code can be reused; however, this is not a requirement. Definitions of classes of broad applicability are best placed in package files so that many programs may use them.

Within the class definition, there are declarations of procedures and functions. These methods define an object's behavior. An object can also store its state in properties. Property declarations are made in the Construct_Object message, the message sent by the system when an object is created. Class definitions are terminated by the End_Class command.

Example

The following example demonstrates sub-classing and inheritance:

Class cBasicButton Is A Button

Procedure Proc_1

Showln "Overridden: This line never prints."

End_Procedure

Procedure Proc_2

Showln "Forwarded: Inside Proc 2 of cSuperClass"

End_Procedure

Procedure Proc_3

Showln "Inside Proc 3 of cSuperClass"

End_Procedure

End_Class

Class cMyButton Is A cBasicButton

Procedure Proc_1 // Override Proc 1

Showln "Override. Inside Proc 1 of cSubClass"

End_Procedure

Procedure Proc_2 // Forwarding example.

Showln "Before forwarding. Inside Proc 2 of cSubClass"

Forward Send Proc_2

Showln "After forwarding. Inside Proc 2 of cSubClass"

End_Procedure

Procedure Proc_4 // Procedure only declared in cSubClass.

Showln "Inside Proc 4 of cSubClass"

End_Procedure

End_Class

Object oTest Is A cMyButton

Procedure OnClick

Showln "This program demonstrates inheritance"

Send Proc_1

Send Proc_2

Send Proc_3

Send Proc_4

End_Procedure

End_Object

The following example demonstrates declaring a new class with new properties:

Class cOK_Button is a Button

// Constructor:

Procedure Construct_Object

Forward Send Construct_Object // very important!

Property Integer piClickCount 0

Property String psBusyLabel "-Busy-"

End_Procedure

End_Class

This example declares a class, cOK_Button, with two new properties, piClickCount and psBusyLabel. Note that the properties are declared inside the class constructor method, Construct_Object. An important part of the Construct_Object method is the "Forward Send Construct_Object" statement. This is the line that ensures that all of the definitions in the superclass's constructor are inherited by the new class.

Notes

  • New properties must be declared in the class constructor method Construct_Object. Refer to the Visual DataFlex Language Guide for more information on declaring properties.

  • Important! Class declarations may not be nested.


Clear

See Also: Understanding File Buffers and DDO Field Buffers, Constrained_Clear, Find, Save, Saverecord

Purpose

To erase all data from the record buffers of one or more database tables. The status of the tables is set inactive. The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax

Clear {DF_ALL | table} […{table}]

Where {table} is the name or filelist number of one or more database tables. The table must be open.

What It Does

Clear deactivates the record buffer for {table}, sets all string fields to blanks, all numeric and date fields to zero, and the record number to zero.

The DF_ALL parameter clears all record buffers of all open tables.

Example

Clear vendor customer employee

This clears the record buffer for the vendor, customer, and employee database tables. Assuming these tables are number 1, 4, and 6 in the table list, the following command would be equivalent:

Clear 1 4 6

Notes

  • Use the Clear command any time you want a freshly initialized record buffer, such as just before you enter data for a new record, or on which to execute a find command.

  • To save a copy of the active record, only distinguished by the record number, set the table status inactive by using the following command:

Move 0 To df_table.recnum

  • The record buffer must not be cleared after changes have been made to an existing record in the record buffer or those changes will be lost. Use the Save command or Saverecord command to save changes to your database tables.

  • A Find GT or GE command on a cleared record buffer will find the first record in the table. A Find LT or LE command will find the last record in the table.


CLI_Get_Database_Attribute

Purpose

Get a database level attribute of a database connected to via a CLI Connectivity Kit.

Syntax

CLI_Get_Database_Attribute <DriverId> <AttrId> <dbHandle> To <sVar>

or

CLI_Get_Database_Attribute <DriverId> <AttrId> <dbHandle> <iIndex> To <sVar>

Where:

  • <DriverId> is the name of the database driver. The names of drivers available from Data Access Worldwide are:

  • DATAFLEX for the embedded database

  • DB2_DRV for the DB2 Connectivity Kit

  • DFBTRDRV for the Pervasive.SQL Connectivity Kit

  • MSSQLDRV for the Microsoft SQL Connectivity Kit

  • ODBC_DRV for the ODBC Connectivity Kit

    If you are using drivers provided by other vendors, check the driver documentation for the driver name.

  • <dbHandle> is the handle to the database.

  • <AttrId> is the attribute identification. Attribute identifications can be:

Attribute Identification

Short Description

DF_DATABASE_ID

This attribute will return the handle of a database connection. The handle should be used when getting any of the other database level attributes.

The database handle that should be passed when getting the DF_DATABASE_ID attribute is the index in the global driver and connection list.

DF_DATABASE_NUMBER_TYPES

The number of types supported by the database.

DF_DATABASE_TYPE_NAME

The name of the Nth type.

DF_DATABASE_TYPE_ID

The identification of the Nth type.

DF_DATABASE_TYPE_AUTOINC

Boolean that indicates if the type has the auto increment attribute.

What it does

The CLI_Get_Database_Attribute command returns information about a database connected to via a CLI Connectivity Kit. The connection must exist, i.e. a login must have been executed or at least one table in the database must be open.

The database handle required to get the DF_DATABASE_ID attribute is the index in the lists maintained by the database API of the database connections. These lists can be enumerated using the DF_NUMBER_DRIVERS, DF_DRIVER_NAME, DF_DRIVER_NUMBER_SERVERS and DF_DRIVER_SERVER_NAME global attributes. The handle returned by the DF_DATABASE_ID attribute must be used when getting any of the other database level attributes. An alternative way to obtain such a handle is via the DF_FILE_DATABASE_ID table attribute.

The individual attributes are discussed in the Database API Attributes section.


CLI_Set_Driver_Attribute - CLI_Get_Driver_Attribute

CLI_Set_Driver_Attribute and CLI_Get_Driver_Attribute

Purpose

Set or get a CLI Connectivity Kit configuration attribute.

Syntax

CLI_Set_Driver_Attribute <DriverId> <AttrId> To <sVar>

CLI_Get_Driver_Attribute <DriverId> <AttrId> To <sVar>

Where:

  • <DriverId> is the name of the database driver. The names of drivers available from Data Access Worldwide are:

  • DATAFLEX for the embedded database

  • DB2_DRV for the DB2 Connectivity Kit

  • DFBTRDRV for the Pervasive.SQL Connectivity Kit

  • MSSQLDRV for the Microsoft SQL Connectivity Kit

  • ODBC_DRV for the ODBC Connectivity Kit

    If you are using drivers provided by other vendors, check the driver documentation for the driver name.

  • <AttrId> is the attribute identification. Attribute identifications can be:

ATTRIBUTE IDENTIFICATION | SHORT DESCRIPTION
DRVR_DEFAULT_NULLABLE_ASCII | Boolean that indicates if ASCII columns allow NULL values when new columns are created. See the DF_FIELD_NULL_ALLOWED field attribute.
DRVR_DEFAULT_NULLABLE_NUMERIC | Boolean that indicates if Numeric columns allow NULL values when new columns are created. See the DF_FIELD_NULL_ALLOWED field attribute.
DRVR_DEFAULT_NULLABLE_DATE | Boolean that indicates if Date columns allow NULL values when new columns are created. See the DF_FIELD_NULL_ALLOWED field attribute.
DRVR_DEFAULT_NULLABLE_TEXT | Boolean that indicates if Text columns allow NULL values when new columns are created. See the DF_FIELD_NULL_ALLOWED field attribute.
DRVR_DEFAULT_NULLABLE_BINARY | Boolean that indicates if Binary columns allow NULL values when new columns are created. See the DF_FIELD_NULL_ALLOWED field attribute.
DRVR_DEFAULT_DEFAULT_ASCII | String that stores the default value of ASCII columns when new columns are created. See the DF_FIELD_DEFAULT_VALUE attribute.
DRVR_DEFAULT_DEFAULT_NUMERIC | String that stores the default value of Numeric columns when new columns are created. See the DF_FIELD_DEFAULT_VALUE attribute.
DRVR_DEFAULT_DEFAULT_DATE | String that stores the default value of Date columns when new columns are created. See the DF_FIELD_DEFAULT_VALUE attribute.
DRVR_DEFAULT_DEFAULT_TEXT | String that stores the default value of Text columns when new columns are created. See the DF_FIELD_DEFAULT_VALUE attribute.
DRVR_DEFAULT_DEFAULT_BINARY | String that stores the default value of Binary columns when new columns are created. See the DF_FIELD_DEFAULT_VALUE attribute.
DRVR_MAX_ACTIVE_STATEMENTS | Integer that holds the maximum number of statements allowed for a connection.
DRVR_ERROR_DEBUG_MODE | Boolean that indicates if the Connectivity Kit should popup errors in a message box before passing them to Visual DataFlex.
DRVR_USE_CACHE | Boolean that indicates if structure caching should be used.
DRVR_REPORT_CACHE_ERRORS | Boolean that indicates if read errors on structure cache files should be reported.
DRVR_CACHE_PATH | The path where structure cache files are stored.
DRVR_USE_CACHE_EXPIRATION | Boolean that indicates if cache expiration must be checked.
DRVR_DEFAULT_TABLE_CHARACTER_FORMAT | String that stores the default table character format.
DRVR_DUMMY_ZERO_DATE_VALUE | The value used as dummy zero date. This attribute cannot be set.
DRVR_DEFAULT_USE_DUMMY_ZERO_DATE | The default for the table attribute to use dummy zero dates. This default is used when creating new tables.
DRVR_LASTERRORTEXTLENGTH | The length of the text of the last error generated by the Connectivity Kit. It is recommended to use the cCLIHandler class's LastDriverError function to get the last error text.
DRVR_LASTERRORTEXT | The text of the last error generated by the Connectivity Kit. It is recommended to use the cCLIHandler class's LastDriverError function to get the last error text.
DRVR_DEFAULTRECORDIDHIDING | Indicates if record identities are hidden when opening "old style" tables.
DRVR_REPORTACTIVECOLUMNERRORS | Indicates the level of selective column fetching errors that are reported.

What it does

The CLI_Set_Driver_Attribute and CLI_Get_Driver_Attribute commands can be used to set and get API driver level attributes. The API driver attributes can also be set through the Connectivity Kit's configuration file. The commands allow a DataFlex programmer more control over the driver level attributes. Setting the attributes will not change the Connectivity Kit configuration file.

For more information on API driver level attributes, see Configuration file MSSQLDRV.INT.


Close

See Also: Lock, Memory, Open, Reread, Runprogram

Purpose

To close a database table.

Syntax

Close {table} [… {table}]

or:

Close DF_ALL [DF_TEMPORARY | DF_PERMANENT]

Where {table} is the name or filelist number of one or more database tables. The option DF_ALL closes all open database tables. The close-type parameter allows tables to be temporarily closed (using DF_TEMPORARY), so that system resources may be recovered. The behavior of a table that is temporarily closed depends on the database driver used to access the table.

What It Does

Close closes one or more database tables named in the command. When a database table has been closed, any program command that addresses the table, or fields in it, will cause DataFlex errors to occur, as if the table had never been opened.

Using the DF_TEMPORARY option may allow you to recover the use of system resources—it is dependent on the driver. For the DataFlex driver, using this option will close the physical table(s). The next time the table is accessed (e.g., by doing a find) it will automatically be re-opened.

You may close a database table when a record is in its record buffer. The buffer data is lost to the program, and the buffer may not be addressed after the table has been closed.

Using Close to stop accessing unneeded tables may improve the speed at which your program runs. The time required for processing Lock and Reread commands, required with every save in multi user environments, is proportional to the number of open database tables. When inactive tables are closed, Lock and Reread commands operate on fewer tables, reducing the time required for saves.

Example

Close Inventory Vendors

In this example, the database tables Inventory and Vendors are closed.

Notes

  • Although it would usually be inefficient to do so, you may reopen database tables that you have closed.

  • Make certain that no Relate, Attach, or other command addresses a closed table through a relationship with a child table.

  • Never use the Close command within a transaction.


Close_Input

See Also: File I/O Commands , Close_Output, Direct_Input, Channel command component, Sequential File I/O

Purpose

To close a sequential input file.

Syntax

Close_Input [Channel {channel-no}]

If {channel-no} is not specified, channel 0 will be assumed.

What It Does

Close_Input closes files opened for input by the Direct_Input command.

Example

Here is a small procedure that reads a sequential file (hello.txt) to the end of the file. It uses Close_Input to close the text file.

Procedure OnClick

String sBuffer

Direct_Input "hello.txt"

Showln "Contents of Hello.Txt"

While (Not (Seqeof))

// Read from the text file.

Readln sBuffer

Showln sBuffer

Loop

Close_Input // Close the sequential input file, hello.txt

End_Procedure

Notes

  • Sequential input files are closed when a new sequential file is opened on the same channel. Sequential files are also closed when a program issues the Abort command. Sequential files may also be closed during program chaining, if the Seq_Export option is not set.

  • Runprogram (without the Wait) option also closes sequential input files.


Close_Output

See Also: File I/O Commands, Append_Output, Close_Input , Despool, Direct_Output, Save, C hannel command component, Sequential File I/O

Purpose

To close a sequential output file.

Syntax

Close_Output [Channel {channel-no}]

If {channel-no} is not specified, channel 1 will be assumed.

What It Does

Close_Output closes sequential files opened for output by the Append_Output and Direct_Output commands.

Example

// Open and close the default I/O channel

Direct_Output "hello.txt"

Writeln "hello"

Close_Output

// Open and close I/O channel 3

Direct_Output Channel 3 "HelloAgain.txt"

Writeln Channel 3 "hello again"

Close_Output Channel 3

Notes

  • A sequential file is closed whenever another file is opened on the same sequential file channel.

  • A sequential file is closed when Abort is executed, when Runprogram (without the Wait option) is executed, or when Chain is executed without the Seq_Export option.

  • By closing the sequential output file, Visual DataFlex requests the operating system to write the file to disk. The actual time the data is written depends on how Windows buffers its disk writes; however, it can be generally assumed that once the Close_Output is issued, the data will be safely written to disk.


Constrain

See Also: Constraints and Filters, Editing Data-Dictionary Structures, OnConstrain method, Constrain_File property

Purpose

To specify the constrained set of records for a DataDictionary object. It may be used outside of DataDictionaries as well using Constraint_Sets.

Syntax

Constrain table.field

Constrain {table.column} {mode} {value} [And {value}]

Constrain relates-to

Constrain {child-table} Relates To {parent-table}

Constrain as

Constrain {table} As (expression)

Argument Explanation

Argument

Explanation

{table}

Is the name of the database table that is being constrained.

(expression)

Is any Boolean expression. The expression is tested for each possible record in the constrained set of data. A False result excludes the record from the constrained set.
These Boolean expressions may not contain any local variables.

{table.column}

Is the database table.field that is being tested. The test is performed for each possible record in the constrained set of data. A False result excludes the record from the constrained set.

{mode}

May be any one of…
LT, LE, EQ, NE, GE, GT, Contains, Matches, or Between.

{value}

Is a variable or constant. The Between mode requires an And between two values.

What It Does

Constrain commands are used in the OnConstrain event method of data dictionary-objects to define a constrained set of records. OnConstrain is an event method defined in the DataDictionary class.

Each Constrain command in the OnConstrain method is evaluated for each record in the data dictionary-object's main file. The result of this evaluation will determine if the record will be part of the object's constrained set of data. If a record fails any Constrain command then it will be excluded from the constrained data set. If there are no Constrain commands in the OnConstrain event of a data-dictionary object, then all records in the object's main file will be part of the object's data set.

There are three types of constraints: Constrain Table.Column, a Constrain Relates-to, and a Constrain-as.

The Between mode is inclusive of the two values that indicate the beginning and end of the constraint. You can think of it as a combination of the GE and LE modes.

Constrain Table.Column

The Constrain Table.Column is used to create a static constraint for a table.field value. This table.field value, almost always a field value from the data-dictionary's main_file, is constrained by a static expression. The expression is static in that it is created once when the constraint set is built and is not rebuilt every time a new record is found. Because this expression is built by the runtime, it can be optimized. If the appropriate index is used, the constraint engine will attempt jump in and out of an index whenever possible. When properly set up, these types of constraints can be very fast.

The following example sets up constraints for an order data-dictionary object (DDO) so that only the active orders are found. If records were being found on an index whose first segment was orders.status, the constraint finding process would be optimized (the DDO would be able to jump to the first valid record and jump out after the last valid record). If the records were being found on any other index, the finding process would not be optimized (the DDO would have to start and the beginning of the table and possibly search all records).

Object Orders_DD is an Orders_DataDictionary

Procedure OnConstrain

Constrain Orders.Status eq "A"

End_Procedure

End_Object

A constraint set can consist of multiple constraint commands. When there are multiple constraints, only those records that satisfy all the constraints will be found. The following example sets up constraints for an order data-dictionary object so that only active orders in 1999 are found. If the first two segments of the finding index was Status x OrdDate, the find process could be optimized:

Object Orders_DD is an Orders_DataDictionary

Procedure OnConstrain

Constrain Orders.Status eq "A"

Constrain Orders.OrdDate Between "1/1/1999" And "12/31/1999"

End_Procedure

End_Object

A constraint is "built" when the data-dictionary is initialized. It is not built each time the record is found. In the following example, the order status is determined by checking a property value.

Object Orders_DD is an Orders_DataDictionary

Property String psValidStatus

Procedure OnConstrain

String sValidStatus

Get psValidStatus to sValidStatus

Constrain Orders.Status eq sValidStatus

End_Procedure

End_Object

Note that the property value is checked only once when the DDO is initialized. If you change the property value while you are finding records, the constraint will not be affected. If you wish to notify the DDO that a constraint has changed you must rebuild the constraints by sending the message Rebuild_Constraints to the DDO.

Object Orders_DD is an Orders_DataDictionary

Property String psValidStatus

Procedure OnConstrain

String sValidStatus

Get psValidStatus to sValidStatus

Constrain Orders.Status eq sValidStatus

End_Procedure

End_Object

Procedure ChangeStatus String sNewStat

Set psValidStatus of Orders_DD to sNewStat // change property

Send Rebuild_Constraints of Orders_DD // rebuild the constraint

End_procedure

You may change constraints in a more dynamic fashion using the Constrain As type of constraint.

Constrain Relates-to

The "relates to" clause limits the constrained set of data to records in the {child-table} that are related to the current record in the data-dictionary belonging to the {parent-table}. Note: the respective data-dictionary objects must be correctly connected with each other. Refer to Editing Data-Dictionary Structures for more information on connecting data-dictionary objects.

Because relates-to constraints are use so often a special data-dictionary property, Constrain_File, has been created that allows you to set a child parent constraint. When the Studio creates DDO structures it uses this Constrain_File property and not the relates-to constraint command. For this reason, you will rarely see this variant of the constrain command used.

The following example shows how a relates-to constraint is created using the Constrain_File message.

Object Orderdtl_DD is a Orderdtl_DataDictionary

Set DDO_Server to (Orderhea_DD(Self))

Set Constrain_File to Orderhea.File_Number // this is the suggested syntax

End_Object

If, for some reason, you wanted to create the same constraint using the constrain command, the same constraint could be coded as follows (this technique is not recommended):

Object Orderdtl_DD is a Orderdtl_DataDictionary

Set DDO_Server to Orderhea_DD

Procedure OnConstrain

Constrain OrderDtl Relates To Orderhea

End_Procedure

End_Object

Relates-to constraints (and the Constrain_File property) can be used with other constraints. In the following example, orders are limited to records that are related to a customer record and have an open status.

Object Orders_DD is a Orders_DataDictionary

Set DDO_Server to Customer_DD

// create a relates to constraint to customer

Set Constrain_File to Customer.File_Number

Procedure OnConstrain

Constrain Orders.Status eq "O"

End_Procedure

End_Object

Relates-to constraints (whether defined with the Constrain_File message or the constrain command) can and almost always should be optimized. This means that the first segment of the child table index should be the field that relates to the parent table.

Constrain-as

You can use the constrain-as constraint to use expressions to set constraints. Unlike the other types of constraints the expression defined to the right of the "as" parameter is evaluated each and every time a record is found.

The constraint engine has no idea what the expression actually contains. Therefore it is unable to optimize constrain-as constraints. This means that you cannot jump into and out of an index when finding a record. The advantage of the constrain-as method is that any type of expression may be used and you do not need to rebuild your constraints when the conditions of the expression change. The constrain-as constraint therefore represents a trade-off between speed and flexibility.

In the following example, records in the Invoice table will be found when either their InvDate field has a value less than the date limit stored in the pdDateLimit property or their Balance field has a balance in excess of 1000.

Property Date pdDateLimit

Object Invoice_DD is an Invoice_DataDictionary

Procedure OnConstrain

Constrain Invoice As ((Invoice.InvDate < (pdDateLimit(self)) ) OR ;

(Invoice.Balance > 1000) )

End_Procedure

End_Object

Only use constrain-as constraints when other constraint cannot be used. While the following two code segments will find the same records, the expression based "constrain … as" can be significantly slower.

// These can be optimized

Constrain Orders.Status eq "O"

Constrain Orders.Balance gt O

// This cannot be optimized

Constrain Orders as (Orders.Status="O" AND Orders.Balance>0)

When a constrain-as constraint is in use, every record will be moved into the buffer and tested — index jump-in/jump-out optimization cannot be used. However, if an expression-based constraint is used with other constraints that are capable of index optimization, the optimizations implied by the other constraints will be used. The non-optimized record searching will be limited to the smaller set of optimized records. This technique greatly increases the usability of expression based constraints.

In the following example orders are limited to records that relate to a customer, are open, and have a balance that is less than or equal to zero or greater than or equal to 1000. If the index used to find these records was Customer_Number x Status x Number, the record finding will be partially optimized.

Object Orders_DD is a Orders_DataDictionary

Set DDO_Server to Customer_DD

// create a relates to constraint to customer

Set Constrain_File to Customer.File_Number

Procedure OnConstrain

Constrain Orders.Status eq "O"

Constrain Orders as (Orders.Balance<=0 OR ;

Orders.Balance>=1000)

End_Procedure

End_object

Important: When using Constrain ... As, do not use any local variables in the constraining expression. Since record scanning and expression evaluation occurs outside of the procedure in which the constraint is set those local variables will not exist when the expression is evaluated.

Changing Constraints

Constraints can be changed at runtime. Any time the conditions of a constrain-as constraint is changed, the change will be immediately applied to the next record found. If the conditions of a constrain table.field or relates-to constraint is changed, the constraint must be rebuilt by sending the DDO the message Rebuild_Constraints.

The following example has an OnConstrain method that creates a constraint block that is controlled entirely by properties defined in the view.

// these are being defined within the view

Property Boolean pbRelatesToCust // if true, relate to customer

Property String psOrderStatus // show: ""=all, "O"=open, "C"=closed

Property Boolean pbShowBadOrders // If true, show only bad orders

Object Orders_DD is a Orders_DataDictionary

Set DDO_Server to (Customer_DD(self))

Set DDO_Server to (SalesP_DD(self))

Procedure OnConstrain

Boolean bRelatesToCust bShowBadOrders

String sOrderStatus

// set relates to constraint based on pbRelatesToCust property

Get pbRelatesToCust to bRelatesToCust

If bRelatesToCust Set Constrain_File to Customer.File_Number

Else Set Constrain_File to 0

// set conditional constraint for status. Only set this if

// a status exists

Get psOrderStatus to sOrderStatus

If (sOrderStatus <> "") Constrain Orders.Status EQ sOrderStatus

// only test for bad orders if we are constraining the order

If bRelatesToCust Begin

Get pbShowBadOrders to bShowBadOrders

If bShowBadOrders ;

Constrain Orders as (Orders.Balance <= 0 OR ;

Orders.Completed = "N")

End

End_Procedure

End_Object

// call this procedure to change constraint rules

Procedure ChangeConstraints Boolean bRelatesTo string sStatus Boolean bShowBad

// set new property values

Set pbRelatesToCust to bRelatesTo

Set psOrderStatus to sStatus

Set pbShowBadOrders to bShowBad

// reinitialize the constraints

Send Rebuild_Constraints of Orders_DD

// find the first valid record in the new set

Set Request_find of Orders_DD FIRST_RECORD Orders.File_Number 1

End_Procedure

Notes

  • Constraints in data-dictionaries are additive. Within a DDO structure, the constraints of parent DDOs structure are applied to (ANDed to) a child DDO's constraint set.

  • Between ... And may be used only as a comparison operator in a simple Constrain command. It may not be used with other commands or in expressions.

  • In older programs, you may see constrain commands used within the Begin_Constraints / End_Constraints command block. These commands are obsolete and can be replaced with the OnConstrain procedure. You may also see constrain commands used within the procedure Constrain. While this technique is valid, the preferred method is to use the OnConstrain method.

  • You can use the predefined global variables, Constrain_Found_Count and Constrain_Tests_Count to determine if constrained records are being found in an optimized manner.

  • The Constrain command is also used to specify a constrained set of records outside of data-dictionary objects. The Constrain command is used in the same way but commands must be used to create, initialize, clear and find records. See the Constraint_Set and Constrained_Find commands. If you are using data dictionaries you will probably never need to use these lower level constraints.


Constrained_Clear

See Also: Clear, Constrain, Constrained_Find, Find

Purpose

To clear a table's record buffer so that records may be found.

The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax

Constrained_Clear {mode} {table} by {-1 | Recnum | index.#}

Where {table} is the name or filelist number of a database table; and {mode} must be one of LT, LE, EQ, GT, or GE.

What It Does

Constrained_Clear clears the record buffer and seeds the buffer with values appropriate for a subsequent Constrained_Find or Find command in the direction implied by an LT, LE, GE, or GT used in the command. It also establishes the table and index for subsequent Constrained_Find Next command.

Example

Constrained_Clear GE Tran_typ By index.1

In this example, the record buffer of table tran_typ is cleared. A large negative number is moved into all numeric fields used in index 1 so that the next Find GE ... or Constrained_Find Next command will begin at the start of the index. The next Constrained_Find Next command would find the succeeding (GE) record.

Constrained_Clear LE Tran_typ By index.1

In this example, the record buffer of table tran_typ is cleared. A large value is moved to all numeric fields used in index 1 so that the next Find LE ... or Constrained_Find Next command will begin at the end of the index. The next Constrained_Find Next command would find the preceding (LE) record.

Constrained_Clear is most frequently useful for situations where user input into a clear buffer is required for finding records.

The behavior of Constrained_Clear is independent of the constraint set in effect. If a constraint set specifies field values, Constrained_Clear may load the fields of the record buffer with initial values that are not within the constraints set. For this reason, a Constrained_Find First or Last command should be used before the Constrained_Find Next commands.


Constrained_Find

See Also: Constraints, Constrain, Constrained_Clear, Constraint_Set, Constraint_Validate, Find, Found, OnConstrain

Purpose

To find records within the constraints in the current constraint set.

The DataDictionary class provides superior functionality that replaces the need for this command in some cases.

Syntax

Constrained_Find {mode} {table} by {-1 | recnum | Index#}

Where {table} is the name or filelist number of a database table; and {mode} must be one of LT, LE, EQ, GT, GE, FIRST, LAST or NEXT.

When the last argument is -1, the index to use will be determined automatically from the constraints in force themselves.

What it Does

Constrained_Find finds records that qualify under the current constraint set according to the find {mode} (First | Last | Next | LT | LE | EQ | GE | GT), in the table and index specified. A Relate command is then performed to find all related records (according to which records in {table} may also be constrained).

Constrained_Find next respects the direction (GT, LT), table, and index of the last Constrained_Find or Constrained_Clear command executed for the current constraint set.

Open Vendor

Constraint_Set 1

Constrain Vendor.State Between "CA" and "CT"

Constrain Vendor.Name Matches "D*"

Constrained_Find First Vendor By 1

While (Found)

Showln Vendor.Name

Constrained_Find Next

Loop

The above program will print the name field for every vendor record whose state field has a value between "CA" and "CT", and whose name field starts with a "D". Since index one is based on the name field, only the records with name starting with D will be scanned.

A Constrained_Find executed with no constraint set current behaves exactly like a(n unrestricted) Find command.

Constrained_Find sets the Boolean expressions Found and Finderr differently from the way the Find Command does. Constrained_Find always fills the record buffer when a record can be found, but Found becomes TRUE, only if the record satisfies the constraint set in effect. Found becomes FALSE if the record fails to satisfy the requirements of the constraints.

Notes

  • The First and Last find modes clear the record buffer before finding. The other find modes do not clear the record buffer; all finding is done relative to the current contents of the record buffer.

  • When no more records qualifying for the constraints can be found, Found will return False.

  • The table parameter may be passed as a table name or a table number.

  • All constrained finds attempt to optimize the find by using the index specified. If possible, Constrained_Find will seed the record buffer with data to "jump in" to the index and will "jump out" of the index when no qualifying records could exist past the current point in the index.

  • The use of Constrained_Find Next instead of Constraint_Find with the LT, LE, GT, or GE is more efficient and therefore recommended. Use the LT, LE, GT, GE, or EQ mode with the Constrained_Find First (or Last) and then use Constrained_Find Next for subsequent finds.

  • An ending argument of -1 will allow the constraint set to pick the best index to use for the search. If a constraint set contains an expression (constrain ... as (expression)), no index will be used, and records will be accessed in record number order.

  • Constrained_Find Next is useful even with no constraint set in effect, when used after a Constrained_Clear command to set the table, index and direction for constrained finds.


Constraint_Set

See Also: Constrain

Purpose

To allow groups of constraints to be created and used.

The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax

Constraint_Set [{integer}] [Clear | Delete]

If {integer} is not specified, it will be considered 1.

What it Does

The Constraint_Set command sets the active constraint set. If the constraint set does not exist, a new one is created. Otherwise, the constraints set the last time the named constraint set was in effect now become the current constraint set. It remains in effect until the next Constraint_Set command.

Since any open database file may be addressed by constrain commands in a constraint set, constraints may be included within a single constraint set as long as they do not conflict. Only use multiple constraint sets if necessary.

Constraint_Set {integer} Clear removes all constraints and find-status from the current constraint set, and leaves {integer} in effect as the current constraint set. This is normally used to reset the constraints for a particular set.

Constraint_Set {integer} Delete removes the identified constraint set. If {integer} is the current constraint set, no constraint set will be active after this command executes until a new Constraint_Set is executed.

There is no need for the constraint set identifiers assigned to be contiguous, or in any particular order. You may use any unique number (such as an object id) to refer to a constraint set.


Constraint_Validate

See Also: Constrain, Found

Purpose

Tests whether all the constraints in the current constraint set are satisfied by the data in the record buffers.

The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax

Constraint_Validate

What It Does

Constraint_Validate applies all the constraints in the current constraint set to the data in the record buffers. If the validation is successful, the Boolean expression Found will be set to TRUE. Otherwise, Found will be set to false.

Constraint_Validate is most-frequently used for enforcing compliance with the current constraint set on records to be saved.

// How to validate on a set of constraints.

Object Constrainer is an Array

Procedure SetConstraints

Constraint_Set Self

// Constrain customers from California whose names start with "R"

Constrain customer.state EQ "Ca"

Constrain customer.name Matches "R*"

End_Procedure

Function ConstraintValidation Returns Integer

Constraint_Set Self

Constraint_Validate

If (Not (Found));

Send Stop_Box "Error" "Validation Failed!"

Function_Return (Found)

End_Procedure

End_Object

Notes

  • Constraint_Validate does not affect any record buffer.


Copy_DB

See Also: Implementing Callback Functions, Copy_Records, Delete_db, Zerofile

Purpose

The Copy_db command is used to copy a database table to or from a client or a server, or from one directory to another.

Syntax

Copy_db {source-table} To {dest-table} [Callback {callback-object}] ;

[Compression {compression-type}]

Argument Explanation

{source-table} Is a name and path of the database table to be copied.

{dest-table} Is a name and path that the database table is copied to.

{callback-object} Is a handle to an object that will receive the Callback message during the sort operation. Refer to Implementing Callback Functions for more information.

{compression-type} Indicates the form of file compression that will be used to save the destination table. The compression used in the source file has no bearing on what compression is used in the copy. The valid types are:

DF_FILE_COMPRESS_NONE no data compression.
DF_FILE_COMPRESS_FAST uses run-length encoding
DF_FILE_COMPRESS_STANDARD uses compression based on the relative frequency of characters in a typical DataFlex file.

What It Does

Copy_db copies the database file (.DAT, .VLD [if any], .TAG, and .K files) identified by {source-table} from the source directory to the destination as specified in the command.

This command will not execute if {source-table} or {dest-table} is open to the user executing this command (they are allowed to be open to other users, however).

Copy_db works by calling the Copy_Records command. All records in the {source-table} are copied to the {dest-table} in record-number order.

Usage of the callback object is exactly as described for Copy_Records. Copy_db, however, can create a destination file where none previously exists. Copy_Records does not do this.

Examples

1) In the following example, database table Vendor is copied to the database table Vendor2.

copy_db "demo/vendor" to "vendor2"

2) In this example, sPhysName will be copied to the root directory of drive C:

String sPhysName

Integer iCompressionType

String sFileDriver

String sDestination

Open Customer

Get_Attribute DF_FILE_PHYSICAL_NAME of Customer.File_Number to sPhysName

Get_Attribute DF_FILE_COMPRESSION of Customer.File_Number to iCompressionType

Get_Attribute DF_FILE_DRIVER of Customer.File_Number to sFileDriver

showln "File " sPhysName " (" sFileDriver ") with compression " iCompressionType " will be copied."

move (sFileDriver+":C:\CopyOfFile") to sDestination

Copy_DB sPhysName To sDestination CallBack 0 Compression iCompressionType

showln "End of Copying Process."

Notes

  • This command neither uses nor changes any file list. All database tables must be identified by their directory rootnames.

  • If {dest-table} already exists and has one or more fields whose name matches one in the source table, records from the source table will be appended to the records already present. If any copied record contains a field value matching the value in any other record in the destination table and the field participates in an on-line unique index, Error 28 Duplicate records not allowed in file will be returned, and the record will not be copied.

  • The callback message is sent each time the number of records in the global attribute DF_RUNTIME_PROGRESS_FREQUENCY is copied, with parameters indicating the number of records copied and the total number of records to be copied.


Copy_Records

See Also: Implementing Callback Functions, Copy_DB, DF_RUNTIME_PROGRESS_FREQUENCY

Purpose

The Copy_Records command is used to copy records from one database table to another.

Syntax

Copy_Records {from-table-number} To {to-table-number} [{num-records}] ;

[Using {index-num}] ;

[Callback {callback-object}]

Argument Explanation

{from-table-number} Is the filelist number of the database table from which records are to be copied.

{to-table-number} Is the filelist number of the destination database table to which records are to be copied.

{num-records} Is the maximum number of records to be copied. If this parameter is not specified, all records will be copied. Also, a value of 0 will copy all records.

{index-num} Is the index that will be used to determine the order of the records to be copied. If not specified, records are copied in the order of recnum.

{callback-object} Is a handle to an object that will receive the Callback message during the sort operation. Refer to Implementing Callback Functions for more information.

What It Does

Copy_Records copies {num-records} records from {from-table-number} to {to-table-number}. If the Using parameter is used, records are copied using the specified {index-num}. If not, then recnum is used. If any copied record contains a field value matching the value in any other record and the field participates in an on-line unique index, Error 28 Duplicate records not allowed in table will be returned, and the record will not be copied.

This command copies record data between database tables of the same or different types and/or structures. Data is copied from each field in the source table for which a field of the same name exists in the target table. Other than name, the fields do not have to have the same size or type attributes, since data conversions will take place automatically.

Data may be truncated in the destination table if the target field is not large enough to contain all of the converted data. In addition, when converting an ASCII, text, or binary field to a numeric or date field, the target field will contain a zero if the source field was not a valid number or date as required.

If the record buffer of the {from-table-number} table is active, the copy starts from the active record and proceeds until {num-records} records have been copied to the target table. If the record buffer of the source table is inactive, the copy starts at the first record (based on {index-num}) in the source table.

If {num-records} is zero, all records from the starting point to the end of the source table will be copied. If {num-records} is greater than the number of records from the starting point to the end of the source table, only the records from the starting point to the end will be copied.

After each record is copied, the callback function (if specified) will be called and passed a string containing the number of records copied.

Example

Object oCopyRecords is a Array

Function Callback String sText Integer iLogicalID Returns Integer

showln sText

// Tell operation to continue

Function_Return False

End_Function

Procedure DoRecordCopy

// This is needed to return a callback for each record

Set_Attribute DF_RUNTIME_PROGRESS_FREQUENCY to 1

Copy_Records Prospect.File_Number To Customer.File_Number ;

0 Callback Self

End_Procedure

End_Object

If the record buffer of Prospect is inactive when Procedure DoRecordCopy is called, all records in Prospect will be copied to Customer, in recnum order. Note that only fields with the same name in both tables get copied.

Notes

  • Instead of the index number to find by, {index-num} be a negative field number. This signifies that the index to be used for the source table is the main index of that field. For example, if {index-num} is -5, the main index of the fifth field will be used for copying the records.

  • Upon successful completion, the source and target table record buffers will contain the last record copied.

  • If {num-records} is 0, all records will be copied.

  • The destination table does not have to contain all the fields that the source table does; whichever ones it has will be copied.

  • The callback message is sent each time the number of records in the global attribute DF_RUNTIME_PROGRESS_FREQUENCY is copied, with parameters indicating the number of records copied and the total number of records to be copied.


Copyfile

See Also: Copy_DB, EraseFile

Purpose

To copy one or more operating-system files to another file(s).

Syntax

Copyfile {source-file(s)} To {destination}

What It Does

Copyfile copies the file(s) identified by {source-file(s)} to the file, drive, and/or folder identified by {destination}, creating any destination files which do not already exist, and overwriting any that do.

Example

This is an example that copies some Order data files into a backup directory:

Set_Directory "C:\VDF\EXAMPLES\ORDER\DATA"

Make_Directory "BACKUP"

// Copy Vendor files to backup.

Copyfile "VENDOR.*" to "BACKUP"

Notes

  • If a Copyfile command is executed on a non existent source file, no error will be triggered. Use the File_Exist command to determine whether a file exists before copying the file.

  • You may use wildcard characters in the source file specification, but not in the destination file specification. When {source-file(s)} contains ambiguous filenames, {destination} must contain only the name of the drive and/or folder to which the files are to be copied.

// Make a copy of the DAT files.

Make_Directory "C:\VDF#\EXAMPLES\ORDER\DATA\BACKUP"

Copyfile "C:\VDF#\EXAMPLES\ORDER\DATA\*.DAT" to ;

"C:\VDF#\EXAMPLES\ORDER\DATA\BACKUP"

IMPORTANT! Use extreme caution when invoking this command. It overwrites existing destination files of the same name without warning.


Create_Field

See Also: Creating Column, Set_Attribute, Structure_End, Structure_Start

Purpose

To add a field to the structure of a database file.

Syntax

Create_Field {file-handle} [At {field-num}]

Where {file-handle} is a handle to the database file where the new field should be added; and {field-num} is the number to use for the new field. {field-num} should be passed as a variable, since the number of the field created will be returned here.

What It Does

This command creates a new field. If {field-num} is omitted or 0, the field will be appended to the end of the existing record structure (if any). The field number assigned is returned in {field-num}. {file-handle} must be the handle of a database file currently being restructured or created.

The numbers of all fields above {field-num} (if any) will be incremented by one. Thus, if {field-num} is 4, the current field number 4 will become field number 5, field number 5 becomes 6, etc.

By default, the field created will be of type ASCII with a length of 0 (zero) bytes. The name of the field will be FIELDn, where n is equal to {field-num}. Use the Set_Attribute command to change these defaults.

Example

Handle hFile

Integer iNewField

// Open the Employee file, and retrieve its number to hFile

Open "employee" As hFile

Structure_Start hFile

// Add a new field to the Employee file.

Move 0 to iNewField

Create_Field hFile At iNewField

// Set the attributes of the newly created field

// iNewField now contains the new field number that was added.

Set_Attribute DF_FIELD_NAME Of hFile iNewField to "Hire_Date"

Set_Attribute DF_FIELD_TYPE Of hFile iNewField to DF_DATE

Structure_End hFile

This example creates a new field, Hire_Date, as the second field in the file Employee as a date field.

Notes

  • This command should be used within a Structure_Start . . . Structure_End block. If not, you will get an error message.

  • If you specify a field number greater than the last existing field, you will receive an error. Thus, if the file currently contains five fields, the maximum value for {field-num} would be 5.

  • To create fields in a new file that has no fields, use {field-num} of zero to create the first field, and to append fields, in the order they are listed in your code, to the record structure.

  • If possible, use the DataBase Builder to create your data files, instead of doing it programmatically.


Create_Index

See Also: Creating indexes with Database Builder, DF_INDEX_NUMBER_SEGMENTS, Set_Attribute, Structure_Start

Purpose

To create an index for a database table.

Syntax

Create_Index {table-handle} [At {index-num}]

Where {table-handle} is a handle to the database table where the new index should be added; and {index-num} is the number assigned to the new index. {index-num} should be passed as a variable, since the number of the field created will be returned here.

What It Does

This command will create a new index for table {table-handle}. Create_Index must be used in a Structure_Start…Structure_End block. When the Structure_End executes, it will create the new index and populate it with data.

After the execution of the Create_Index command, {index-num} will contain the number of the index created. You cannot specify the number of the new index—it will be appended to the existing index structure. For example, if {table-handle} has 4 indexes, executing Create_Index will create index 5.

After creating an index, you can use the Set_Attribute command to set up the fields and other characteristics of the index.

Example

Handle hTable

Integer iIndex

Open "Customer" As hTable

Structure_Start hTable "DATAFLEX"

Create_Index hTable At iIndex

// Set Index Attributes: 3 segments; batch type.

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_TYPE Of hTable iIndex To DF_INDEX_TYPE_BATCH

// Set the first segment of the index to be case insensitive.

// NOTE: If field used for this segment is not ASCII, the attribute

// will still be set, although it will be meaningless.

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 2

Set_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex 1 To DF_CASE_IGNORED

// Set the second segment of the index to be in descending order.

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 4

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

// Set the third segment of the index to use RECNUM—using 0 for

// field number represents RECNUM.

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 0

Structure_End File_Number DF_STRUCTEND_OPT_NONE

This example opens the Customer table and creates an index consisting of three segments—the second field, fourth field, and RECNUM. In addition, it will be a batch index, with a case-insensitive segment and a descending segment.

Notes

  • If you want the new index to have more than one segment, be sure to set the DF_INDEX_NUMBER_SEGMENTS attribute. If this attribute is not set, it defaults to one, and any attempt to set more segments will result in an error (Bad parameter).


Currency

See Also: Declaring Variables, Variable Declaration Commands, Struct, Number, Decimal

Purpose

Declares one or more Currency variables.

Syntax

To declare currency variables

Currency {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Currency variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Currency

Currency {dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Currency command declares Currency variables. The Currency type is useful for storing fixed point numbers with 4 or fewer digits to the right of the decimal point and up to 14 to the left. The purpose of this data type is to facilitate integration with COM and ODBC.

A currency types range is from 922337203685477.5807 to -922337203685477.5808.

Up to nine variables may be declared on one command line, with their names separated from each other by spaces. Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

Currency cyMyVar

Move 1234.56 To cyMyVar

send Info_Box (string(cyMyVar))

End_Procedure

This example declares a currency variable named cyMyVar, moves 1234.56 to it and displays it in a message box.

Currency[] cyBalances

This example declares 1 dynamic array variable, named cyBalances, containing an undefined number of elements of type currency.

Currency[5] cyBalances

This example declares 1 static array variable, named cyBalances, containing 5 of elements of type currency.

Currency[][3] cyBalances

This example creates a two-dimensional dynamic array variable named cyBalances, containing an undefined number of elements of type currency. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Currency variable, you should use the global_variable command to do so.


Date

See Also: Declaring Variables, Variable Declaration Commands, Time and Date Functions, Struct, String Functions

Purpose

Declares one or more Date variables.

Syntax

To declare Date variables

Date {date-identifier} [… {date-identifier}]

Where

  • Where {identifier} is a variable name for the new date variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Date

Date{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Date command creates variables that contain date values.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Date dAnniversary dSpousesBirthday dVacation dDeadline

This example declares four date variables: dAnniversary, dSpousesBirthday, dVacation, and dDeadline.

Date[] dBirthdays

This example declares 1 dynamic array variable, named dBirthdays, containing an undefined number of elements of type date.

Date[5] dBirthdays

This example declares 1 static array variable, named dBirthdays, containing 5 of elements of type date.

Date[][3] dBirthdays

This example creates a two-dimensional dynamic array variable named dBirthdays, containing an undefined number of elements of type date. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • Dates are stored as Julian numbers. Julian dates are numbers equal to the number of days from Day 1, Year 0 to the date.

  • Years may be in the range of 01 (or 0001) to 2500.

  • If you are using a field_mask, years may be in the range of 01 to 2200.

  • You may do calculations on dates. Subtracting one date from another will yield the number of days between them. You may also add a number of days to a date. Here is a simple example that shows Y2K compliance. Notice it uses both 2-digit and 4-digit year constants to show how the epoch setting works.

Object oTest Is A Button

Function DaysAgo Date dSomeDate Returns Integer

Date dToday

Integer iDaysBetween

Sysdate4 dToday

Move (dToday - dSomeDate) To iDaysBetween

Function_Return iDaysBetween

End_Function

Procedure Test Date dTest

Integer iDaysAgo

Move (DaysAgo(self, dTest)) To iDaysAgo

If (iDaysAgo > 0);

Showln dTest " was " iDaysAgo " days ago."

Else;

Showln dTest " is " (-iDaysAgo) " days from now."

End_Procedure

Procedure OnClick

// Test various 2 and 4 digit dates.

Send Test "01/01/1980"

Send Test "01/01/80"

Send Test "01/01/2000"

Send Test "01/01/00"

Send Test "01/01/2010"

Send Test "01/01/10"

End_Procedure

End_Object

  • The display of the date depends on the format chosen. Typically, Visual DataFlex will conform to your Windows operating system locale settings. Use the Set_Attribute command and the DF_DATE_FORMAT attribute to change the attribute from the default.

    DF_DATE_USA 12/31/2005
    DF_DATE_EUROPEAN 31/12/2005
    DF_DATE_MILITARY 2005/12/31

  • You may use string functions (left, right, mid, etc.) to extract date information from a Date variable. The string operation will be performed on a string representation of the date that is consistent with the date format in effect.

  • If an illegal value (such as 13/31/05) is moved to any Date-type variable, Visual DataFlex will declare an error.

  • Visual DataFlex is Y2K-robust. We recommend using 4-digit years in your date fields. If 2-digit years are used, the epoch settings must be set correctly so that the correct century (19xx or 20xx) is selected for any given date with 2-digit years. Epoch settings are made with the Set_Date_Attribute command. By default, Epoch settings are set to use 4-digit years.

  • You may convert a two digit year date to a four digit year date by adding 01/01/1900 or 693975 to the date.

  • If you need to define a global Date variable, you should use the global_variable command to do so.


DateTime

See Also: Declaring Variables, Variable Declaration Commands, Time and Date Functions, Struct, Date, Time, TimeSpan

Purpose

Declares one or more DateTime variables.

Syntax

To declare DateTime variables

DateTime {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a variable of type DateTime. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type DateTime

DateTime{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The DateTime command declares DateTime variables. This is useful for storing dates and performing calculations. String conversions to DateTime variables are locale specific, so use the date functions, DateSetMonth, DateSetDay, DateSetYear, DateSetSecond, DateSetMinute, and DateSetHour to place constant values in a DateTime variable.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain space

Examples

Procedure Test

DateTime dtVar

Move (DateSetSecond(dtVar, 30)) To dtVar

Move (DateSetMinute(dtVar, 10)) To dtVar

Move (DateSetHour (dtVar, 10)) To dtVar

Move (DateSetDay (dtVar, 30)) To dtVar

Move (DateSetMonth (dtVar, 1)) To dtVar

Move (DateSetYear (dtVar, 2006)) To dtVar

End_Procedure

This example declares a DateTime variable and initializes it to 01/30/2006, 10:10:30am.

DateTime dtNow

TimeSpan tsWeek

move (CurrentDateTime()) to dtNow

move (DateSetDay(tsWeek, 7)) to tsWeek

move (DtNow + tsWeek) to dtNow

This example adds one week to the current date and time.

DateTime[] dAppointments

This example declares 1 dynamic array variable, named dAppointments, containing an undefined number of elements of type DateTime.

DateTime[5] dAppointments

This example declares 1 static array variable, named dAppointments, containing 5 of elements of type DateTime.

DateTime[][3] dAppointments

This example creates a two-dimensional dynamic array variable named dAppointments, containing an undefined number of elements of type DateTime. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global DateTime variable, you should use the global_variable command to do so.


Decimal

See Also: Declaring Variables, Variable Declaration Commands, Struct, Currency, Number

Purpose

Declares one or more Decimal variables.

Syntax

To declare decimal variables

Decimal {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Decimal variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Decimal

Decimal{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Decimal command declares Decimal variables. Internally, Decimal is a fixed point variable with up to 32 significant digits - 16 to the left of the decimal point and 16 to the right of the decimal point.

The Decimal type is compatible for storing SQL data of the Decimal or Numeric types.

The valid range of this data type is -9999999999999999.9999999999999999 to 9999999999999999.9999999999999999.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Example

Procedure DoTest

Decimal decMyVar

Move 10000.999999999999 To decMyVar

End_Procedure

This example declares one variable of type decimal, named decMyVar, and initializes it.

Decimal[] decSharePrices

This example declares 1 dynamic array variable, named decSharePrices, containing an undefined number of elements of type Decimal.

Decimal[5] decSharePrices

This example declares 1 static array variable, named decSharePrices, containing 5 of elements of type Decimal.

Decimal[][3] decSharePrices

This example creates a two-dimensional dynamic array variable named decSharePrices, containing an undefined number of elements of type Decimal. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Decimal variable, you should use the global_variable command to do so.


Declare_Datafile

See Also: Changing File-List Information of a Database File, Open

Purpose

To declare the definition of a database table available for use in programs.

Syntax

Declare_Datafile {table-name}

Where {table-name} is the DataFlex Name of a database table. {table-name} cannot contain a path; only a table name.

What It Does

Declare_Datafile includes the .FD for the named file and defines any related symbols (e.g., FILE.FILE_NUMBER). Declare_DataFile allows the file to be used in your program code before it is open.

Example

Declare_DataFile Customer

Object oMyObject is an cObject

Procedure Close_File

// Without Declare_DataFile the next line would not compile.

Close Customer

End_Procedure

Procedure Open_File

Open Customer

End_Procedure

End_Object

Notes

  • Declare_Datafile has no effect if used on an already-open table.


Decrement

See Also: Increment, Integer, Repeat, While

Purpose

To reduce the value of a variable or database field by one.

Syntax

Decrement {variable}

Where {variable} is any integer, date or numeric variable or a numeric or date database field.

What It Does

Decrement subtracts one from the value of {variable}. Decrement works with any variable or field that contains a date or numeric value.

The Decrement command is especially useful for maintaining descending counters, especially those which control While ... End, Repeat ... Until, and similar structured loops.

Example

Procedure CountDown Integer iFromWhatNumber

Integer iCounter

Move iFromWhatNumber to iCounter

Repeat

Showln iCounter "."

Decrement iCounter

Until (iCounter < 1)

End_Procedure


Deferred_View

See Also: CD_End_Object, Object

Purpose

To defer creation of a view object until the first time it is accessed by a user, and to link its access/creation to a desktop-level activation message.

Syntax

Deferred_View {access-message} For Object {object-name} Is A {class-name}

:

Cd_End_Object

Where {access-message} is the name of the activation message; {object-name} is the name of the view object to be activated; and {class-name} is the class of the object to be created.

What It Does

The Deferred_View command allows the view object to be created when accessed through {access-message}, rather than when the program starts.

Notes

  • Before the object is used, its access message must be sent.

  • Use the Cd_End_Object command (instead of End_Object) to end a deferred view.


Define

See Also: Array Types, Structured Types, Enum_List, #IFDEF, #REPLACE

Purpose

To create or rename compiler variables, and to assign values to them.

Syntax

Define {new-symbol} [{… {new-symbol}]

Define {new-symbol} For {old-symbol}

Define {new-symbol) {integer}

Where {new-symbol} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Define allows you to create one or more compiler symbols with integer values. The For phrase allows you to set a value for the symbol, {new-symbol}.

When surrounded by an Enum_list / End_Enum_List pair, Define assigns a symbolic replacement for a sequential series of integer values for as many {new-symbol}s as are named in the command block:

Example

The following example shows how the definition of a symbol can be used to change program behavior.

// To change the program comment out the next line.

Define C_EvaluationVersion

Define C_EvaluationAllowedSaves For 1000

Object oEvalTester Is A Button

Function CheckEvalSave Integer iTotalRecords Returns Integer

// Conditional compilation.

#IFDEF C_EvaluationVersion

// Test record count versus evaluation limit.

If (iTotalRecords <= C_EvaluationAllowedSaves) Function_Return TRUE

Else Function_Return FALSE

#ELSE

Function_Return TRUE // Allow all saves.

#ENDIF

End_Function

Procedure OnClick

Integer bEvalTest

Get CheckEvalSave To bEvalTest 500

Showln "500 saves = " bEvalTest

Get CheckEvalSave To bEvalTest 1500

Showln "1500 saves = " bEvalTest

End_Procedure

End_Object

In the above example example, when the symbol C_EvaluationVersion is defined, evaluation restrictions are enabled in the program. Another symbol defines the limit for evaluation saves.

Enum_List // _htmlControlAlign

Define htmlControlAlignNotSet

Define htmlControlAlignLeft

Define htmlControlAlignCenter

Define htmlControlAlignRight

Define htmlControlAlignTextTop

Define htmlControlAlignAbsMiddle

Define htmlControlAlignBaseline

Define htmlControlAlignAbsBottom

Define htmlControlAlignBottom

Define htmlControlAlignMiddle

Define htmlControlAlignTop

Define htmlControlAlign_Max FOR 2147483647

End_Enum_List

Object oTest Is A Button

Procedure OnClick

Showln "These are some HTML Control Alignment Variables..."

Showln "Alignment not set: " htmlControlAlignNotSet

Showln "Right Alignment: " htmlControlAlignRight

Showln "Top Alignment: " htmlControlAlignTop

Showln "Max value: " htmlControlAlign_Max

End_Procedure

End_Object

Notes

  • Note that the Define command creates no program overhead. You may use Define freely to make your program more readable.

  • Use it to simplify your program logic by giving meaningful names to your system constants.

  • Define is also useful for representing external component interface constants.

  • When For is used with the Define command in an enumeration list to assign a constant integer value, enumeration continues sequentially from the value given in subsequent Define commands.


Delegate

See Also: Delegation, Broadcast, Forward, Get, Send, Set

Purpose

To direct a message to the parent of a named object.

Syntax

Delegate {Get |Set |Send} {message}...

What It Does

Delegation is the redirection of a message to the parent of a named object. Normal delegation of a message occurs if an object that receives a message can not process it. What this means is that there is no implementation of the message defined in the object declaration, or in the object's class.

The Delegate command is used to explicitly delegate a message to an object's parent. Any message may be delegated to a parent. The command is functionally equivalent to using a Get, Set, or Send command of the parent of an object.

Example

// These two lines do the same thing.

Delegate Send DoSave Param1 Param2

Send DoSave Of (Parent(Self)) Param1 Param2

In the following example, a nested set of objects are defined where a child is a parent of one object that is the child of the other. One message, Procedure Test, is defined at every level of the hierarchy. The child delegates Test to its parent, and the parent delegates Test to the grandparent. Two other messages, Proc_1 and Function_1, are implemented in the parent, but not in the child. The Delegate Send and Delegate Get commands of the child object execute the code defined in the parent object.

Object oGrandParentObject Is A Group

Procedure Test

Showln "In Test Function of " (Name(Self))

End_Procedure

Object oParentObject Is A Group

Procedure Test

Showln "In Test Function of " (Name(Self))

Delegate Send Test

End_Procedure

Object oChildObject Is A Button

Procedure Test

Integer iTest

Showln "In Test Function of " (Name(Self))

Delegate Send Test

Showln "Before Delegation of Proc_1"

Delegate Send Proc_1

Showln "After Delegation of Proc_1"

Showln "Before Delegation of Function_1"

Delegate Get Function_1 "Hello" "World" To iTest

Showln "After Delegation of Function_1"

End_Procedure

End_Object

Procedure Proc_1

Showln "In Proc_1 of " (Name(Self))

End_Procedure

Function Function_1 String sParam1 String sParam2 Returns Integer

Showln "In Function_1 of " (Name(Self)) ;

". Parameters are " sParam1 ", " sParam2

Function_Return 1

End_Function

End_Object

End_Object

Object oTest Is A Button

Procedure OnClick

Send Test Of ;

(oChildObject(oParentObject(oGrandParentObject(DESKTOP))))

End_Procedure

End_Object

The arguments to the Delegate command are the same as those to any Get, Set or Send command for the object. The parameter list is added to the end of the command just like a normal Get, Set, or Send command. See the example of Function_1 in the example above to see how to use the parameter list with Delegate.


Delete

See Also: Clear, Find, Open, Zerofile

Purpose

To remove the record currently in the record buffer from each database table named in the command. The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax

Delete {table} […{table}]

Where {table} is the name or filelist number of one or more open database tables. Integer variables may be used as well.

What It Does

Delete erases the record that is currently in the record buffer from the database table and removes the entries in associated indexes.

Example

This example deletes the first record in the customer table:

Procedure DeleteFirstCustomer

Open Customer

// Get first record.

Find GE Customer.Recnum

// Remove the record from the database.

Delete Customer

Close Customer

End_Procedure

Notes

  • To delete a record, you must first open its database table and find the record.

  • Delete updates all on line indexes, removing entries for the deleted record.

  • Delete only erases one record from each {table}. To erase all the data of an entire database table, leaving only its definition intact, use the Zerofile command.

  • Delete sets the table status to inactive.

  • Delete does not clear the record buffer. All the values that were in the deleted record are still loaded in memory after the Delete command.

  • The use of the DataDictionary class can eliminate problems such as deletion of records with relationships in child tables.

  • Once a record has been deleted, it cannot be recovered from the disk.

  • You can pass either the table's DataFlex Name or its table number (in FILELIST.CFG) to the delete command.


Delete_db

See Also: Copy_DB, Zerofile

Purpose

Deletes a database table.

Syntax

Delete_Db {table} [IGNORE_ERRORS]

Where {table} is the name or filelist number of one or more database tables. The IGNORE_ERRORS parameter suppresses all errors. This can be used when deleting a table that may or may not exist.

What It Does

Delete_Db deletes a database table. All the components of the data table are destroyed. Native Visual DataFlex tables consist of .DAT, .K files, .TAG, .FD files, and possibly .VLD files

Example

Delete_Db "Vendor"

In this example, database table Vendor is deleted. If the vendor table is number 6 in the filelist, then the following command line would be equivalent:

Delete_Db 6

Notes

  • No variable table numbers may be used with this command.

  • Use this command with caution. Once a database table is deleted, it cannot be recovered.

  • You can pass either the table's logical name or its table number (in FILELIST.CFG) to the Delete_Db command.

  • Delete_Db will attempt to gain exclusive access to the table. If it cannot do so (e.g., if the table is in use by someone else), the command will fail.

  • Delete_Db will delete open tables—it doesn't make any difference whether or not the table is open.


Delete_Field

See Also: Create_Field, Structure_Start

Purpose

To delete a field from the structure of a database file.

Syntax

Delete_Field {file-handle} {field-num}

Where {file-handle) is a handle to the database file; and {field-num} is the number of the field to delete.

What It Does

This command will delete the field {field-num} from the file {file-handle).

Example

Procedure DeleteField String sFileName Integer iFieldNo

Integer hFile

// Open your database file

Open sFileName As hFile

// Start of the structure operation.

// The Visual DataFlex driver name is "DATAFLEX".

Structure_Start hFile "DATAFLEX"

// Select the field to delete—in this case, field #4

Delete_Field hFile iFieldNo

Structure_End hFile DF_STRUCTEND_OPT_NONE

End_Procedure

Notes

  • The {file-handle) must be for a file for which a Structure_Start process is currently running.

  • Because DataFlex maintains relationships based on field numbers, an invalid relationship may result when a field is deleted. For example, if field 3 is deleted from the parent file, and a child field relates to it, the relationship will now be pointing to a different field.

  • The Structure_End command that terminates the structural changes of the database file will automatically reindex the file, if necessary.

  • If possible, use the DataBase Builder to create your data files, instead of doing it programmatically.


Delete_Index

See Also: Create_Index, Structure_Start

Purpose

To delete an index from the structure of a database table.

Syntax

Delete_Index {table-handle} {index-num}

Where {table-handle) is a handle to the database table; and {index-num} is the number of the index to delete.

What It Does

This command will delete the index {index-num} from the database table {table-handle}. The {table-handle} must be for a table that has had a Structure_Start done on it. The index table (rootname.K##) is also deleted.

Example

Procedure DeleteIndex String sTableName Integer iIndexNo

Integer hTable

// Open database table

Open sTableName As hTable

// Start of the structure operation.

// The embedded database driver name is "DATAFLEX".

Structure_Start hTable "DATAFLEX"

// Select the field to delete—in this case, field #4

Delete_Index hTable iIndexNo

Structure_End hTable DF_STRUCTEND_OPT_NONE

End_Procedure

Notes

  • If you delete the main index of a field, and then attempt to execute a Find command by this field, you will get an error "Field not Indexed". For example, assume index #2 is the main index for field Employee.Salary. If you delete index #2, the following find command would return an error:

Find GT Employee.Salary

  • Remember that if you delete the main index for a related-to field, the relationship will no longer be valid for finding records.


DFBTR_Add_Owner

Purpose

Add an owner name to the list of owner names.

Syntax

DFBTR_ADD_OWNER Owner

Owner The owner name to add to the internal list. It may be a constant or a string variable.

What it does

This command adds an owner name to the list of owner names kept by the Connectivity Kit. These owner names will be used when opening a Pervasive.SQL data table. An owner name has a maximum length of 8 characters and is case sensitive.

The Connectivity Kit keeps an internal list of owner names to use when opening Pervasive.SQL tables. Whenever a Pervasive.SQL table needs to be opened which has not been assigned an individual owner name, the Connectivity Kit will try the first owner name of the list to open the table. If it doesn't succeed, it will try the next owner name in the list, until it has reached the end and it still could not open the table. When it reaches the end without opening the table, it will try to open the table without owner name. When the owner name list is empty, it will immediately try to open the table without owner name. If it still could not open the table, it will generate an error 21051 (BTR:51).


DFBTR_Clear_Owner

Purpose

Clear the owner name of a table.

Syntax

DFBTR_CLEAR_OWNER FileNumber [CALLBACK ObjectId]

Where:

  • FileNumber is the number of the table to change.

  • CALLBACK ObjectId is an option may be used if the program wants to be informed about the progress of the command’s execution. Advised when encrypting an existing table with a lot of data.

What it does

This command can be used on an opened table to clear its owner name. If an owner name was specified for this table, it will be cleared. If the data was encrypted, the data will be restored to its normal format

NOTE:

This command may not be executed within a transaction!


DFBTR_DDF_Owner

Purpose

Set owner name for DDF tables.

Syntax

DFBTR_DDF_OWNER Password

What it does

This command can be used to supply the password to be used to open DDF tables that have Database Security switched on. Pervasive.SQL 8.5 introduced secure database mode. Before that version it was possible to switch on a form of database security. Basically this would add an owner name to the DDF tables used by Pervasive.SQL as meta database. This security mechanism can only be used in pre-8.5 versions of Pervasive.SQL.


DFBTR_Get_Explicit_Locking

Purpose

Get current explicit locking setting.

Syntax

DFBTR_GET_EXPLICIT_LOCKING to Variable

What it does

This command returns the current state of the EXPLICIT_LOCKING setting. When set to TRUE or non-zero, the Connectivity Kit will automatically place a lock on the Pervasive.SQL tables and/or records when a LOCK or BEGIN_TRANSACTION command is being executed.

Refer to Transactions and Locking for more information.


DFBTR_Get_Transaction_Type

Purpose

Get the current transaction type setting.

Syntax

DFBTR_GET_TRANSACTION_TYPE to Variable

What it does

This command returns the currently active transaction type. Possible return values are: DFBTRTT_NONE, DFBTRTT_EXCLUSIVE , DFBTRTT_CONCURRENT.

Refer to Transactions and Locking for more information.


DFBTR_Remove_All_Owners

Purpose

Remove all owner names from the owner name list.

Syntax

DFBTR_Remove_All_Owners

What it does

This command clears the complete list of owner names. This includes all owner names added by the program using DFBTR_ADD_OWNER and all owner names added to the Connectivity Kit upon start up by reading the DFBTRDRV.INT file.

The Connectivity Kit keeps an internal list of owner names to use when opening Pervasive.SQL tables. Whenever a Pervasive.SQL table needs to be opened which has not been assigned an individual owner name, the Connectivity Kit will try the first owner name of the list to open the table. If it doesn't succeed, it will try the next owner name in the list, until it has reached the end and it still could not open the table. When it reaches the end without opening the table, it will try to open the table without owner name. When the owner name list is empty, it will immediately try to open the table without owner name. If it still could not open the table, it will generate an error 21051 (BTR:51).


DFBTR_Set_Explicit_Locking

Purpose

Set the explicit locking setting

Syntax

DFBTR_SET_EXPLICIT_LOCKING to iValue

What it does

This command can be used to control the way a lock command works. When set to TRUE or non-zero, the Connectivity Kit will automatically place a lock on the Pervasive.SQL tables and/or records when a LOCK or BEGIN_TRANSACTION command is being executed.

Refer to Transactions and Locking for more information.


DFBTR_Set_Owner

Purpose

Set the owner name of a table.

Syntax

DFBTR_SET_OWNER FileNumber TO OwnerName [READONLY| ENCRYPT] [CALLBACK ObjectId]

Where:

  • FileNumber is the number of the table to change.

  • OwnerName is the new ownername of the table. May be a constant or a string variable. An ownername has a maximum length of 8 characters and is case sensitive.

  • READONLY - When this option is used, the Pervasive.SQL engine will allow opening the table without ownername for read-only access. This is only useful when an ownername has been specified.

  • ENCRYPT - When this option is used, the Pervasive.SQL engine will encrypt the data in the data table. It may take a while for this operation to complete depending on the amount of data in the table. This is only useful when an ownername has been specified.

  • CALLBACK ObjectId - This option may be used when the program wants to be informed about the progress of the command’s execution. Advised when encrypting an existing table with a lot of data.

What it does

This command can be used on an opened table to change its ownername.

NOTE:

This command may not be executed within a transaction!


DFBTR_Set_Transaction_Type

Purpose

Set the transaction type setting.

Syntax

DFBTR_SET_TRANSACTION_TYPE TO [DFBTRTT_NONE | DFBTRTT_EXCLUSIVE | DFBTRTT_CONCURRENT]

What it does

This command can be used to switch the type of transaction to be used at runtime.

NOTE:

This command may not be executed within a transaction!


DFCreate_Menu

See Also: MenuBar class, End_Menu

Purpose

Creates a menu object or menu item.

Syntax

DFCreate_Menu ObjectName

DFCreate_Menu MenuItemText ObjectName

DFCreate_Menu MenuItemText ObjectName is a PopupMenuClass

What It Does

This command can be used with 1, 2 or 3 parameters.

1 Parameter

Creates a MenuBar object named ObjectName.

Example

DFCreate_Menu Accounts

2 Parameters

Creates a menu item with the text MenuItemText. It also creates a popup menu named ObjectName based on the PopupMenu class. When MenuItemText is selected, it will invoke ObjectName.

Example

string sItemName

move "Log In" to sItemName

DFCreate_Menu sItemName Accounts

3 Parameters

Creates a menu item with the text MenuItemText. It also creates a popup menu named ObjectName based on the class specified in the third parameter. When MenuItemText is selected, it will invoke ObjectName.

Example

string sItemName

move "Log In" to sItemName

DFCreate_Menu sItemname Accounts is a MyPopupMenu

Example

DFCreate_Menu Main_Menu

#Include File_PM.inc // file pulldown menu

DFCreate_Menu "&View" ViewPopupMenu Is A ViewPopupMenu

On_Item "&Contacts\aCtrl+1" Send Activate_Contacts

Set Status_Help To "View / Add / Edit / Delete contacts."

End_Pull_down

Set Status_Help To "Available Views"

DFCreate_Menu "&Report" ReportPopupMenu Is A ViewPopupMenu

On_Item "&List Contacts (Summary)" Send Activate_Contacts_List_Rpt1

Set Status_Help To "List summary contact information"

On_Item "List Contacts (&Detail)" Send Activate_Contacts_List_Rpt2

Set Status_Help To "List full detail contact information"

End_Pull_down

Set Status_Help To "Available Reports"

DFCreate_Menu "&Maintenance" MaintenancePopupMenu Is A ViewPopupMenu

On_Item "&Contacts Maintenance" Send Activate_ContactsMaint

Set Status_Help To "Import contacts, Delete duplicate contacts"

End_Pull_down

Set Status_Help To "Maintenance functions"

#Include Navi_pm.inc // Naviation pulldown menu

#Include win_PM.inc // Window of available views

#Include Helpa_PM.inc // help pulldown menu w/ About

End_Menu


Direct_Input

See Also: File I/O Commands, Close_Input, Direct_Output, Get_Channel_Position, Get_Channel_Size, Open, Read, Read_Block, Readln, Set_Channel_Position, Seq_New_Channel, Seq_Release_Channel, Seqeof, Channel command component, Sequential File I/O

Purpose

To open a file or device for sequential input.

Syntax

For sequential file input:

Direct_Input [Channel {channel-num}] fileName}]

For Windows clipboard input:

Direct_Input [Channel {channel-num}] "clipboard:"

For database input:

Direct_Input [Channel {channel-num}] dbms df_file.field

Where

{filename} is a string with any valid file name

{channel-num} may be 0 through 9, and if omitted, will be assumed to be 0 (default for input) or the last channel number explicitly specified in code executed previously

Only filename and {channel_num} may be contained in variables; the terms Channel and dbms must be hard-coded, as must the arguments of dbms.

File Modes:

Mode may be either binary: or pc-text:. If omitted, it will be pc-text:.

Option may be any or all of:

cr: asciiValue (defaults: binary: -1, pc-text: 13)

eol: asciiValue (defaults: binary: 10, pc-text: 10)

eof: asciiValue (defaults: binary: -1, pc-text: 26)

width: bytes (default: 2048)

AsciiValue -1 means not used (no value).

If any option is omitted, its default asciiValue or bytes will depend on the mode.

Drivers:

[driver:] file/device may be:

file: fileName

clipboard: (the Windows clipboard)

direct: fileName

dbms: df_fileNumber, fieldNumber

dir: [fileSpec] (default is *.*)

resource: resourceName or resourceID

If driver is omitted, it will be file:.

What It Does

The Direct_Input command opens sequential files for input. Use the Read, Read_Block, or Readln commands to read the data from the file.

A sequential file is generally opened at the beginning of file. Use Set_Channel_Position command to change the point from which data will be read. Get_Channel_Position returns the current position of the input channel.

The Direct_Input command is also a shortcut for reading text lines from the Windows clipboard.

A text field in a database file may be addressed with the dbms: df_file.field driver. Used as a driver (with the colon, through a variable or as a quote-embedded constant), this specification requires that the numbers of the database file and field be given, separated by a comma. Used as a command option (with a space instead of the colon, without quotes), this specification requires that the names of the database file and field be given, separated by a period. In either case, the database file must be open in the program.

Example

The following example shows a function method that calculates how many lines are in a sequential file.

Function LineCount String sFilename Returns Integer

Integer iLineCount

String sBuffer

// Look for an available sequential file channel.

// Use ReadLn to check that file is not already open.

ReadLn Channel 9 sBuffer

If (Seqeof) Begin // If we have an available sequential file channel.

Send Stop_Box "Error!" "Cannot open file. Channel 9 is busy."

Function_Return 0 // Cannot open file

End

Else Begin

Direct_Input Channel 9 sFilename

If (Not(Seqeof)) Begin // File exists.

Showln "File " sFilename " is open on channel 9."

Move 0 to iLineCount

ReadLn sBuffer

While (Not(Seqeof))

Increment iLineCount

ReadLn Channel 9 sBuffer

Loop

Close_Input Channel 9

End

Function_Return iLineCount

End

End_Function

Example

The following example reads the contents of the clipboard and shows them on the screen:

String sBuffer

Direct_Input "Clipboard:"

Showln "Contents of Clipboard"

While (Not (Seqeof))

// Read from the clipboard

Readln sBuffer

Showln sBuffer

Loop

Close_Input

Drivers:

Various drivers permit input in different formats from different types of files and devices. If no driver is named, the file: driver is used. This driver is suitable for input from con:, or from a sequential file. The desired file must be named in fileName, complete with subdirectory path, if desired. If Visual DataFlex buffering of file input is not desired, the direct: driver may be substituted.

Example

direct_input "direct: com2:"

In this example, channel 0 is defined to take input without Visual DataFlex buffering from Device com2:.

Input from the clipboard: device is from the Windows clipboard. The contents of the clipboard may be accessed the same as for any text file—it can be read from via read... statements in a loop until the seqeof predefined indicator is true.

An operating-system directory may be opened like a file with the dir: [fileSpec] driver. If fileSpec is omitted, the value of *.* (all files) will be assumed. Once the directory has been opened, it may be read from, line by line, with readln commands. Readln loops terminating when predefined indicator seqeof becomes true will read in the entire directory.

Example

String sLine

Direct_Input "dir: c:\program files\visual dataflex 11.0"

Repeat

Readln sLine

Showln sLine

Until (Seqeof)

This example would display a list of all contents of the "C:\Program Files\Visual DataFlex 11.0" folder. The output would probably look something like this:

[.]
[..]
[Bin]
[Bitmaps]
[Documentation]
[Examples]
[Help]
[Lib]
[Pkg]
[Projects]
[Usr]
Visual DataFlex License.rtf
Visual DataFlex 11.0.60.0 ReadMe.rtf

Example

open Customer

move 5 to Customer.Id

find eq Customer by Index.1

Direct_Input dbms Customer.Notes "binary:"

In this example, database file Customer is opened and the customer record with id 5 found. The subsequent direct_input command opens text field Notes for input to the program, first clearing the field of any content it may have. A close_input command should be executed before any further database manipulation of Customer is done.

File Modes:

For file input, three modes are available, along with options for the Carriage Return (cr:), End of Line (eol:), and End of File (eof:) characters, and maximum argument width.

The pc-text: (default) mode provides default values for cr:, eol:, and eof:. Cr: is set to ASCII 13, eol: to 10, and eof: to 26. The binary: mode, intended for (non-text) files, sets both cr: and eof: invalid, and eol: to 10. Any mode name must be followed by a colon (:).

Cr:, eol:, eof:, and width: can be specified in separate options, but it is recommended that such options be given after any mode specifications, since the mode specifications may override the options. If the keywords cr:, eol:, eof:, or width: are included followed by the desired asciiValue or (for width:) bytes, the parameter will be reset. The value -1 may be used to specify no character for cr:, eol:, or eof:. A colon (:) must be used after each asciiValue or bytes.

Example

string sMergeFile sFileName

move "florPlan.pcx" to sMergeFile

move ("PC-TEXT:"+"EOF: -1:"+sMergeFile) to sFileName

direct_input sFileName

In this example, florPlan.pcx is moved to String Variable sMergeFile. Then, an append is done on the strings pc-text:, eof: -1:, and the value of sMergeFile to Variable sFileName. Finally, input through channel 0 is directed from File florPlan.pcx in the pc-text: format with the end-of-file character stripped, through the value of sFileName.

Notes

  • When a Direct_Input command is used on an open channel, the open file is closed, and the new file, fileName, is opened.

  • When direct_input is issued when a different source is already open for input, the old source is closed, and the new source is opened.

  • Certain devices, such as bar-code readers, require unbuffered input. For such devices, use the direct: driver. Using direct_input to work with serial devices is very limited. Use FlexCOM for more advanced reading from devices such as serial communication ports.

  • When two or more output destinations or input sources need to be open at the same time, use the channel channel_num option to open additional channels.

  • Using Direct_Input with the Channel {channel-num} component, but without a device name causes the current input channel number to change to the mentioned channel, and does not close the previously opened device on that channel. This technique is useful when the channel dependent variables (such as SeqEOF) need to be processed.

    Caution:     Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.

Example

Direct_Input Channel 1 "MyFile.Txt"

// Now the current input channel is 1

Direct_Input Channel 2 "MyOtherFile.Txt"

// Now the current input channel is 2

Direct_Input Channel 1

// Now the current input channel is 1 again


Direct_Output

See Also: File I/O Commands, Append_Output, Direct_Input, Close_Output, Get_Channel_Position, Get_Channel_Size, Open, Output, Set_Channel_Position, Write, Writeln, Seq_New_Channel, Seq_Release_Channel, Seqeof, Channel command component, Sequential File I/O, Using the Euro Symbol with a Printer

Purpose

To write output to a sequential file, a printer, or the Windows clipboard.

Syntax

For sequential file output:

Direct_Output [Channel {channel-num}] {filename}

For output to the Windows clipboard:

Direct_Output [Channel {channel-num}] "CLIPBOARD:"

For output to a printer:

Method 1

Direct_Output [Channel {channel-num}] ;

"WinLST: [{printer-name}:] [PORTRAIT: | LANDSCAPE:] [Font: {font-name}:] [Points: {num-points}:] [NO_OEMTRANSLATE:]"

Method 2

Direct_Output [Channel {channel-num}] "WinLST: [{port-name}]"

Where

{filename} is a string with any valid file name

{channel-num} may be 0 through 9, and if omitted, will be assumed to be 1 (default for output) or the last channel number explicitly specified in code executed previously.

What It Does

Direct_Output identifies the destination for sequential output (output from the write and writeln commands) from the program. There are three supported sequential file output options for Visual DataFlex: a sequential file, the printer, or the clipboard.

Direct_Output to a Sequential File

This is the simplest case of sequential file output.

Example

The following program shows how easy it is to write a sequential file.

Procedure DoOutputData String sFileName

Integer iCount

// Create a text file. Replaces the file if it already exists.

Direct_output sFileName

For iCount From 1 To 10

Writeln "Line: " iCount " - Hello!"

Loop

Close_Output

End_Procedure

Example

This example is a slightly modified version of the above example to properly use channels. We highly recommend using channels in all sequential input and output operations to improve code reusability. However, for the purposes of what needs to be demonstrated in the examples of the Direct_Output command this is not necessary and we will not repeat the channel usage in each example.

If you place code that uses channels and code that does not use channels in the same program, you may encounter unexpected and undesirable behavior. See the Seq_New_Channel function for proper use of the channel command option.

Use Seq_chnl.pkg

Procedure DoOutputData String sFileName

Integer iCount iChOut

// obtain an available channel for output

move (Seq_New_Channel()) to iChOut

// no channel available

if (iChOut=DF_SEQ_CHANNEL_NOT_AVAILABLE) begin

send Info_Box "No Channel Available for Output" "Error"

procedure_return

end

// Create a text file. Replaces the file if it already exists.

Direct_Output Channel iChOut sFileName

For iCount From 1 To 10

Writeln Channel iChOut "Line: " iCount " - Hello!"

Loop

// close output channel

Close_Output Channel iChOut

// release channel for reuse

send Seq_Release_Channel iChOut

End_Procedure // DoOutputData

Direct_Output to a Printer

The printer allows a set of options to be defined. The following are all examples of valid Direct_Output commands:

Direct_Output "WinLST: Font: Arial"

Direct_Output "WinLST: Font: Courier New: Points: 20"

Direct_Output "WinLST: LANDSCAPE: Font: Comic Sans MS: Points: 9"

Direct_Output "WinLST: PORTRAIT: NO_OEMTRANSLATE"

Direct_Output "WinLST: LaserJet 4M Plus: LANDSCAPE: Points: 24"

Direct_Output "WinLST: LPT1:"

Direct_Output "WinLST: \\OurServer\HP4MPlus"

Each parameter must be separated from the next parameter by a colon, ':', character. There is no need for a trailing colon after the last parameter. A printer name can be added to the WinLST: device name. This feature allows a printer that is not the default printer to be used as the printer for a given sequential file channel.

The Portrait and Landscape options allow the paper orientation to be selected. Landscape allows the page to be printed so the top of the page is really the left side of the paper. This allows for very wide reports. Portrait is the typical default setting (the top of the page is the top of the page) that is generally used.

The Font and Points setting allow the typeface and size of the printing font to be selected respectively. Windows will do the best it can to find a compatible font for the parameters that you provide.

Printing Raw Escape Sequences

Sometimes, a developer wishes to directly send escape sequences to the printer to control output. The Windows Print Manager and default Windows output device (WiNLST:) normally strip out any printer escape sequences sent to the printer.

In this case, output can be directed to a specific printer port that a printer is captured to, or directly to the printer using the UNC address of the printer.

When accessing a port or printer directly using this method, additional parameters such as points or fonts may not be used.

Example

The following example shows how to print directly to a printer captured to the LPT1: printer port and change the page orientation using printer escape sequences. The escape sequences used in this example are from PCL5.

String sEscSeq sLandscape sPortrait

Move (Character(27)) to sEscSeq

Move (sEscSeq+"+"110") to sLandscape

Move (sEscSeq+"+"100") to sPortrait

Direct_Output "WinLST: LPT1:"

WriteLn sLandscape // set orientation to landscape mode

WriteLn "Line 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"

WriteLn "Line 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2"

WriteLn "Line 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"

WriteLn "Line 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4"

WriteLn "Line 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5"

WriteLn sPortrait // reset orientation to portrait mode

Close_Output

Example

In either of the following example code lines, the direct_output line will generate an error:

status <<32>> Cannot open output device

This is because additional parameters other than the printer port or the printer UNC name are used.

Direct_Output "WinLST: LPT1: LANDSCAPE: Points: 24: Font: Courier New"

Direct_Output "WinLST: \\OurServer\HP4MPlus: LANDSCAPE: Points: 24: Font: Courier New"

Direct_Output to the Windows Clipboard

The Direct_Output command is also a short cut to writing text lines into the Windows clipboard. The following example reads the contents of a file and writes it to the clipboard.

Direct_Input "hello.txt"

Direct_Output "Clipboard:"

Showln "Contents of Clipboard"

While (Not (Seqeof))

// Read from the text file

Readln sBuffer

// Write to clipboard

Writeln sBuffer

Loop

Close_Input

Close_Output

Universal Naming Convention (UNC)

Universal naming convention (UNC) is a naming convention for accessing netword devices, including disk drives and printers. For printers, the UNC naming convention is the following:

\\{ServerName}\{PrinterName}

Where {ServerName} is the name of the server to which the printer is connected and {PrinterName} is the name of the printer connected to the server.

Printer Control Language (PCL)

Printer Control Language (PCL) is a language for accessing a standard set of printer features developed by Hewlett-Packard (HP). PCL5 is the 5th revision of this language. Most modern printers support HP's PCL. You can obtain documentation about PCL directly from HP. Be sure to also check the documentation that came with your printer for escape sequences that can be used with it and whether the printer supports PCL.

Notes

  • When two or more output destinations or input sources need to be open at the same time, use the Channel option to open additional channels. We highly recommend using channels in all sequential input and output operations to improve code reusability. If you place code that uses channels and code that does not use channels in the same program, you may encounter unexpected and undesirable behavior. See the Seq_New_Channel function for proper use of the channel command option.

  • If {filename} does not exist when a Direct_Output is executed, the file is created. Direct_output always opens a file for output at the beginning of the file. The channel position can be set to another value using the Set_Channel_Position command.

  • To open a file without erasing it, use the Append_Output command.

  • When Direct_Output command occurs on a channel already open for output, the old destination is closed, and the new one is opened.

  • In Microsoft Windows 95 and Windows 98, each computer can assign a different name to each commonly accessed printer. In Windows NT 4 and Windows 2000, the name is fixed.

  • If you wish to output the Euro symbol when printg, see the topic Using the Euro Symbol with a Printer.

  • Using Direct_Output with the Channel {channel-num} component, but without a device name causes the current output channel number to change to the mentioned channel, and does not close the previously opened device on that channel. This technique is useful when the channel dependent variables (such as SeqEOF) need to be processed.

    Caution:     Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.

Example

Direct_Output Channel 1 "MyFile.Txt"

// Now the current output channel is 1

Direct_Output Channel 2 "MyOtherFile.Txt"

// Now the current output channel is 2

Direct_Output Channel 1

// Now the current output channel is 1 again


Diskfree

Purpose

To determine the free disk space of a drive.

Syntax

Diskfree {directory} To {variable}

Where {directory} is a variable that contains the name of the root directory of a drive; and {variable} is the name of a variable that will contain the amount of disk space.

What It Does

The value of {variable} is the amount of free space on the drive.

Example

The example below shows how much diskspace is on the C drive:

Function DiskFreeSpace String sPath Returns Integer

Integer iSize

DiskFree sPath To iSize

Function_Return iSize

End_Function


DWord

See Also: Declaring Variables, Variable Declaration Commands, Struct

Purpose

Declares one or more DWord variables.

Syntax

To declare DWord variables

DWord {identifier} […{identifier}]

Where

  • Where {identifier} is a variable name for the new DWord variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type DWord

DWord{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The DWord command declares DWord variables. DWord are Integers.

Visual DataFlex DWord types are typically used to declare variables for storing Windows Registry information (to be read from or written to DWord Registry values) or for interfacing with Windows API calls using the External_Function command.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

DWord dwRegistryValue

End_Procedure // Test

This example declares one variable of type DWord, named dwRegistryValue.

DWord[] dwRegistryValues

This example declares 1 dynamic array variable, named dwRegistryValues, containing an undefined number of elements of type DWord.

DWord[5] dwRegistryValues

This example declares 1 static array variable, named dwRegistryValues, containing 5 of elements of type DWord.

DWord[][3] dwRegistryValues

This example creates a two-dimensional dynamic array variable named dwRegistryValues, containing an undefined number of elements of type DWord. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global DWord variable, you should use the global_variable command to do so.


End

See Also: Begin, If

Purpose

To establish the "bottom" of a Begin…End block.

Syntax

Begin

…

End

What It Does

End marks the point in a program at which execution resumes in the event the block is not executed (skipped).

Example

If (Found) Begin

Lock

Move (Irritant.Counter + 1) To Irritant.Counter

Save Irritant

Unlock

End

Notes

  • If an End command is provided with no preceding Begin, For, Repeat or While command, the compiler will report an error.

  • You may place Begin .. End blocks inside other Begin ... End blocks up to a limit of 40. And you may freely intermingle them with other block control commands (loops). But you may not overlap them — you must end the innermost block first, then the next-innermost, and so on.


End_Class

See Also: Class, Object

Purpose

To terminate a class-definition block.

Syntax

Class {class-name} is a {superclass}

End_Class

What It Does

Each class definition block started by the Class command must be terminated by an End_Class command. This command restores compiler generated information relating to the current class. Class definition blocks may not be nested.

Each class keeps a count of the number of sub-objects that have been defined by the class. The end_class command defines a symbol for each class that declares the number of its sub-objects.


End_Enum_List

See Also: Define, Enum_List

Purpose

To terminate an enumeration list begin with an Enum_List command.

Syntax

Enum_list

Define symbol ... symbol

:

Define symbol ... symbol

End_Enum_List

What It Does

End_Enum_List identifies the end of a block of code containing a set of define commands to which integer values are to be assigned sequentially.


End_Function

See Also: Function, Function_Return

Purpose

To terminate a function-definition block.

Syntax

Function {name}…

…

End_Function

What It Does

End_Function defines the end of a function definition block that begins with a Function command. An End_Function is required for each Function command.

End_function does not use any arguments.

The End_Function command defines the end label for the function command when it is registering the function with the runtime system. The system executes the function command then jumps to the next command line beyond the End_Function command.

The End_Function command will return a zero if it is ever actually executed. In a properly-designed function, this will never happen. Rather, execution of the function will be ended with a Function_Return command.


End_Menu

See Also: MenuBar class, DFCreate_Menu

Purpose

Ends a menu structure created with DFCreate_menu.

Syntax

DFCreate_Menu Main_Menu

#Include File_PM.inc // file pulldown menu

DFCreate_Menu "&View" ViewPopupMenu Is A ViewPopupMenu

On_Item "&Contacts\aCtrl+1" Send Activate_Contacts

Set Status_Help To "View / Add / Edit / Delete contacts."

End_Pull_down

Set Status_Help To "Available Views"

DFCreate_Menu "&Report" ReportPopupMenu Is A ViewPopupMenu

On_Item "&List Contacts (Summary)" Send Activate_Contacts_List_Rpt1

Set Status_Help To "List summary contact information"

On_Item "List Contacts (&Detail)" Send Activate_Contacts_List_Rpt2

Set Status_Help To "List full detail contact information"

End_Pull_down

Set Status_Help To "Available Reports"

DFCreate_Menu "&Maintenance" MaintenancePopupMenu Is A ViewPopupMenu

On_Item "&Contacts Maintenance" Send Activate_ContactsMaint

Set Status_Help To "Import contacts, Delete duplicate contacts"

End_Pull_down

Set Status_Help To "Maintenance functions"

#Include Navi_pm.inc // Naviation pulldown menu

#Include win_PM.inc // Window of available views

#Include Helpa_PM.inc // help pulldown menu w/ About

End_Menu


End_Object

See Also: Self, Class, Object

Purpose

To terminate the current object-definition block.

Syntax

Object {object-name} is a {class-name}

…

End_Object

What It Does

Each object definition is begun with the Object command and terminated with the End_Object command. Object definition blocks may be nested, so the most recent Object command is terminated by the End_Object command.

Within the object definition, the Object command sets the Self variable to the object being defined. End_object pops the Self variable and restores it to the previous value.


End_Procedure

See Also: Procedure, Procedure_Return

Purpose

To terminate a procedure-definition block.

Syntax

Procedure {name}…

…

End_Procedure

What It Does

Each procedure-definition block started with the Procedure command must be terminated with an End_Procedure command. End_procedure defines the end of the procedure command block and is required for each Procedure command. Procedure-definition blocks may not be nested.

End_Procedure does not use any arguments.

The End_Procedure command defines the end label for the procedure command when it is registering the procedure with the runtime system. The system executes the Procedure command and then jumps to the next command line beyond the End_Procedure command.


End_Struct

See Also: Struct Type, Struct Variable Assignments, Struct Properties , Struct

Purpose

To terminate a struct type declaration block.

Syntax

Struct {type-name}

{data-type} {member-name}

[{data-type} {member-name}]

[…]

End_Struct

What It Does

Each struct type declaration block started by the Struct command must be terminated by an End_Struct command.


End_Transaction

See Also: Transactions and DDOs, Abort_Transaction, Begin_Transaction, Lock, Unlock

Purpose

To explicitly mark the end of a database transaction.

Syntax

End_Transaction

What It Does

Transactions begin with a Begin_Transaction command and end with an End_Transaction command. Transactions are comprised of all the database table operations between the Begin_Transaction and End_Transaction commands.

If an error occurs during a transaction, the entire transaction can be rolled back to its original pre-transaction state. After the End_Transaction command executes, the transaction is over and it may not be rolled back.

Notes

  • Abort_transaction commands executed after an End_Transaction command will generate an error.

  • The Begin_Transaction and End_Transaction commands must be matched within the same scope. The following would not be legal:

Begin_Transaction

: // Database update commands.

if (Not(Found)) Begin

End_Transaction

// More code.

End


Entry_Item

Purpose

To define an entry item in a data entry object, such as a dbForm

Syntax

Entry_Item {table.field | expression}

What It Does

An Entry_Item command defines the association between a data entry object and the destination of the data. Entry_Item is used to place data into a field of a database table's record buffer. An Entry_Item command may also be attached to an expression, so that it displays the value of the expression on the screen.

This association provides both for display of the field contents and data entry of the field value. If the argument is a {table.field}, then the item content is transferred between the screen and the data-dictionary buffer.

Entry objects support a wide set of field properties that allow you to control every aspect of the data entry interface. Each of these properties can be set in the DataDictionary objects using DataBase Builder. For more information, please see the class reference topics for DataDictionary.

Example

Below is an example of an entry item for the Customer_Number field of a customer table:

Object Customer_Number is a dbForm

Entry_Item Customer.Customer_number

Set Label to "Customer Number:"

Set Size to 13 42

Set Location to 5 72

End_Object

Below is an example of an expression entry item.

Object Customer_Available_Credit is a dbForm

Entry_Item (Customer.Credit_limit – Customer.Balance)

Set Label to "Available Credit:"

Set Size to 13 48

Set Location to 9 72

End_Object

Below is an example of an expression entry item that calls a function that is defined in its Server DDO.

Object oInvt_DD is a Invt_DataDctionary

...

Function CalcExtended Returns Number

number nExtent

move (Orderdtl.Qty_Ordered*Orderdtl.Price) to nExtent

Function_Return nExtent

End_Function

End_Object // oInvt_DD

Object oInvtDbGrid is a dbGrid

...

Begin_Row

Entry_Item Invt.Item_id

Entry_Item Invt.Description

Entry_Item Invt.Unit_price

Entry_Item Orderdtl.Price

Entry_Item Orderdtl.Qty_ordered

Entry_Item (CalcExtended(Server(Self)))

End_Row

End_Object // oInvtDbGrid


Enum_list

See Also: Array Types, Defining Constants, Structured Types, Define, End_Enum_List

Purpose

To define an enumerated list of constants.

Syntax

Enum_List

Define {symbol} … {symbol}

:

Define {symbol} … {symbol}

End_Enum_List

What It Does

Enum_List assigns sequential integer values to constant identifiers created by embedded Define commands starting with zero.

Example

The following example will create three constant identifiers.

Enum_List

Define zeroth

Define first second third

End_Enum_List

The symbol "zeroth" will have the value of zero (0). "First" will be 1, "second" will be 2, and "third" will be 3.

The following example is an enumeration list that represents sets of Windows mouse messages. Notice the use of the "Define…For" in the list to set ranges of sequential values.

Enum_List // Mouse messages.

Define WM_MOUSEMOVE FOR 512

Define WM_LBUTTONDOWN

Define WM_LBUTTONUP

Define WM_LBUTTONDBLCLK

Define WM_RBUTTONDOWN

Define WM_RBUTTONUP

Define WM_RBUTTONDBLCLK

Define WM_MBUTTONDOWN

Define WM_MBUTTONUP

Define WM_MBUTTONDBLCLK

End_Enum_List


Erasefile

See Also: Zerofile

Purpose

To erase one or more disk files.

Syntax

Erasefile {file-spec}

What It Does

Erasefile erases the file(s) identified by {file-spec}. By default, Erasefile will delete from the current working directory. You may use any valid Windows file-specification (including wildcards) with the Erasefile command.

Example

Delete a single file, hello.txt, from the current directory.

Erasefile "hello.txt"

Erase Vendor files from the Order sample.

Erasefile "c:\data\order\vendor.*"

Erase all files that start with X from the current directory.

Erasefile "x*.*"

Erase all the files in the subdirectory Temp of the current directory.

Erasefile "Temp"

Please exercise great care when using Erasefile.

Notes

  • Erasefile treats all directory files, including Visual DataFlex database files, the same.

  • Only delete files that are not open.

  • If Erasefile is executed on a non existent file, no error will be triggered.

  • You may use "wild card" (ambiguous) filenames for {file-spec}. Be extremely careful when using wildcards in erasefile commands. Erasefile provides no verification or protections unless you program them, and erroneous usage could potentially erase important data!

  • If you want to erase all data from a Visual DataFlex database file but leave its structure intact, use the Zerofile command.

  • Erasefile may behave differently on different operating systems. For example, erasefile "" will delete all files in the current directory on Windows 2000 and XP, and no files on Windows NT and ME.


Error

See Also: Generic Errors, Err global indicator, ErrLine gobal indicator, Error Handling in Transactions

Purpose

To signal an error has occurred.

Syntax

Error {error-num} [{message}]

Where {error-num} is the error number to report; {message} may not be longer than 1000 characters.

What It Does

The Error command signals that an error has occurred. The predefined variable, Errline, is set to the line number that the error occurs. The predefined variable Lasterr is set to the error number, {error-num}. Subsequent calls to the Boolean expression Err will return TRUE.

If {error-num} matches the number of an error in any of the DataFlex error database file, the message from the file for that error will be displayed. Use the Flexerrs Maintenance tool (in the Workspace option of the Visual DataFlex Studio) to maintain the error database file.

Example

Error 999 "This is just a test."

Notes

  • The line number reported in DataFlex error reports is the value of Errline.


External_Function

See Also: Array Types, Structured Types, Field, Function, GetBuff, Put, Type

Purpose

To import an external function defined in a Dynamic Link Library (DLL) file. This command allows a Visual DataFlex program to directly access functions of the Windows operating system and many of its extensions.

Syntax

The syntax is the same as the Function command, except that the parameter list is preceded by a case-sensitive name (as defined in the Dynamic Link Library) and the name of the DLL.

External_Function {function-name} {lib-function} {library-name} ;

{w-type} {parameter} [… {w-type} {param}] ;

Returns {return-type}

Argument Explanation

{function-name} Is the name of the function as it is to be called from the DataFlex program. This must be a literal name, not the value of a variable.

{lib-function} Is the case-sensitive name of the function as it is defined in the external DLL.

{library-name} The filename, optionally including path, of the DLL that contains the function. This must be a literal name, not the value of a variable.

{w-type} Is the data type of the parameter to push. Below is a list of valid types and their respective Byte-size.

Type | Size (bytes) | Note
CHAR | 1 | Converted to Integer.
BYTE | 1 | Converted to Integer
WORD | 2 | Converted to Integer
SHORT | 2 | Converted to Integer
DWORD | 4 |
INTEGER | 4 |
HANDLE | 4 |
NUMBER | 4 | Converted to Integer
DATE | 4 | Converted to Integer
POINTER | 4 |
STRING | 4 |

{param} Is the variable name assigned to passed parameters to the function.

{return-type} Is the return data type of the function. This must be a Visual DataFlex data type or VOID_TYPE. You can use VOID_TYPE to make it more clear that the function does not return anything.

What It Does

The External_Function command creates a global function that allows the Visual DataFlex program to invoke an imported function of a DLL. The function is used like any other Visual DataFlex function.

Example

The following example creates a global function named PlaySound that invokes the PlaySoundA function of the DLL, WinMM.DLL (a Multimedia DLL). Note that while it is a good idea to make the {function-name} parameter as close as possible to {lib-function}, it is not necessary.

External_Function PlaySound "PlaySoundA" WinMM.dll ;

String sFileName ;

Handle hmod ;

DWORD fdwSound ;

Returns Integer

PlaySound returns an integer and takes 3 parameters, a string, a handle, and a DWORD. This function may be invoked as follows:

// Define wave sound constants.

Enum_List

Define SND_SYNC SND_ASYNC SND_NODEFAULT

Define SND_LOOP FOR 9

End_Enum_List

Function WaveLooping String sWaveFile Returns Integer

Function_Return (PlaySound( sWaveFile, 0, SND_LOOP ))

End_Function

Notes

  • {function-name} is global to the program.

  • Visual DataFlex only supports external calls to DLLs built with a 32-bit address model.

  • Visual DataFlex only supports external calls to DLL functions declared using standard calling convention.


Field_Map

See Also: DF_Field_Number attribute

Purpose

To return the field number of a given field of a database file.

Syntax

Field_Map {file-handle} {field-name} To {field-number}

Where {file-handle} is a handle to the file containing the field; {field-name} is the name of the field; and {field-number} is the name of a variable that will receive the field number.

What It Does

The Field_Map command determines the field number of a field of a database file. This command is useful when you have the name of a field, but not its number. The field number is especially useful for getting information about the field:

Example

Integer iField // The field number.

Integer hFile // The file.

Integer iType // The type of field. See Get_Attribute.

Integer iLength // The field length.

// To find Vendor, it must be in your workspace DFPath.

Open "Vendor" As hFile

Field_Map hFile "Name" To iField

// Get the field's metadata.

Get_attribute DF_FIELD_TYPE of hFile iField To iType

Get_attribute DF_FIELD_LENGTH of hFile iField To iLength

// Show the information about the file.

Showln "Field Type of Name is " iType

Showln "Field Length of Name is " iLength

// Close the file.

Close Vendor

Notes

  • If {field-name} is not found in {file-handle}, you will receive Error 4100: Cannot find field.


File_Exist

See Also: Get_Directory, Make_Directory, Make_Temp_File, Remove_Directory, Valid_Drive

Purpose

To report whether a file exists.

Syntax

File_Exist {file-name} {result}

Where {file-name} is the file specification of the file, including the path name. No wildcards may be used; {result} is an integer variable that is set non-zero if the file exists, or FALSE if the file cannot be found.

What It Does

File_Exist returns a non-zero value if the specified file exists, and a zero if it does not. File_Exist will look for the file in the current working directory, unless a path name is provided as part of the file specification. No wild cards may be used with the File_Exist command.

Example

Integer bFileExists

String sWindowsDir

File_Exist "hello.txt" bFileExists

…

Get_Windows_Directory To sWindowsDir

File_Exist (sWindowsDir + "\SYSTEM\KERNEL32.DLL") bFileExists

Notes

  • File_Exist looks for the file in the current directory. It does not use the registry key value DFPATH.

  • No error is returned if there is a nonexistent drive or directory designation in {file-name}. If an error occurs, zero is returned in {result}.

  • {file-name} may not contain "wildcard" characters, such as * and ?.


Fill_Field

Purpose

To seed a record buffer with the highest (maximum) or lowest (minimum) value for the field's data type.

Syntax

Fill_Field {table-handle} {field-number} With {DF_LOW| DF_HIGH}

Where {table-handle} is a handle to the database table; and {field-number} is the number of the field which is to be filled.

What It Does

The Fill_Field command places either a maximum or a minimum value in the field {field-number}. When DF_LOW is specified, minimum values are placed in the field. The DF_HIGH value places a maximum value in the field.

Other databases may have maximum and minimum values that are different from those of the DataFlex database. Seeding the search field in the buffer with DF_HIGH or DF_LOW will prevent data errors of the kind that arise when DataFlex encounters data values that are otherwise invalid. DF_HIGH and DF_LOW use the length of the field to create maximum and minimum values for numbers and strings.

For example, Fill_Field will set a numeric field with length 6 to 999999 if DF_HIGH is specified. For, DF_LOW the value set is 99999. Note that DataFlex tables will "lose" a digit for the minimum—the maximum has six digits, while the minimum has only five.

Example

The following is a small procedure that sets field 2 of a table to maximum value and field 3 to a minimum value.

Procedure DoResetForFind Integer hTable

Fill_field hTable 2 with DF_HIGH

Fill_field hTable 3 with DF_LOW

End_Procedure

Notes

  • The record that has been filled using this command will be first (if the DF_LOW parameter is used) or last (using DF_HIGH) when ordering by this field.

  • Regardless of the native database type, if data is read from a field that was written using the Fill_Field command, the data returned will be the highest or lowest value, in DataFlex format, supported by that field.

  • If a record is saved that has fields that were written using the Fill_Field command, the data written is the highest or lowest value, supported by that field.

  • For DF_BINARY, DF_TEXT, DF_ASCII, and DF_OVERLAP, minimum values are null bytes.

  • For DF_BINARY and DF_OVERLAP, the maximum values are 0xff Hex.

  • For DF_ASCII and DF_OVERLAP, the maximum values are strings filled with the highest character of the collating sequence.

  • For DF_NUMBER and DF_DATE, the maximum value is all 9s for as many digits that the field occupies. That is, an 8-digit field will have a maximum value of 99999999.

  • For DF_NUMBER and DF_DATE, the minimum value is all 9s for as many digits the field occupies minus one. Thus, an 8-digit field will have a minimum value of –9999999 (note: only 7 digits!)

  • For field 0, Recnum, the minimum value is zero.


Find

See Also: Understanding File Buffers and DDO Field Buffers, Found indicator, Clear, Constrained_Clear, Constrained_Find, Open, Vfind

Purpose

To retrieve a record from a database table on disk, and place it in the record buffer. The DataDictionary class provides superior functionality that replaces the need for this command.

Syntax 1

Find LT | LE | EQ | GE | GT {table} By Recnum | Index.#

Syntax 2

Find LT | LE | EQ | GE | GT {table.field}

Where {table} is the table name or filelist number of an open database table; and {table.field} is the tablename.fieldname of a database table and field.

What It Does

The Find command locates a record in {table} based on the data in the record buffer, the index selected, and the find mode (LT, LE, EQ, GE, or GT) specified.

If the Find command is successful (see below), the found record is read from the disk into the record buffer, the record buffer becomes "Active" (it contains a valid record from the database). Subsequent calls to the Boolean expression Found will return TRUE.

If the Find command is not successful, the Boolean expression Found will return FALSE and the record buffer remains as it was prior to the find.

The Find command uses one of five modes for the relationship between the data in the buffer and the data in the found record:

lt record data LESS THAN buffer data

le record data LESS THAN OR EQUAL TO buffer data

eq record data EQUAL TO buffer data

ge record data GREATER THAN OR EQUAL TO buffer data

gt record data GREATER THAN buffer data

Index comparisons take into account the sorting order of the index segments (ascending or descending) when calculating which value is greater. Consider a database table "Scientists" where index 1 is sorted on a Name field in ascending order and index 2 is sorted on the same field, but in descending order.

Example

Suppose there are five names in the database: "Cindy", "Marcia", "Oscar", "Sean", and "Scott". The example below illustrates how the order of the index affects the behavior of the Find Command.

Open Scientists

Move "Oscar" to Scientists.Name

Find Gt Scientists By Index.1

// The record just found will be the record with "Sean"

Move "Oscar" to Scientists.Name

Find LT Scientists By Index.1

// The record just found will be the record with a name field of "Marcia"

Move "Oscar" to Scientists.Name

Find Gt Scientists By Index.2

// The record just found will be the record with a name field of "Marcia"

Move "Oscar" to Scientists.Name

Find LT Scientists By Index.2

// The record just found will be the record with a name field of "Sean"

Close Scientists

Find GT on a clear buffer will find the first record of the table for the given index. Find LT will return the last record in the index.

There are two forms of the Find command:

1. Naming the index explicitly, by number:

Find GE customer By Index.3

In this example, Index 3 (index.3) is used to find a record in Database File customer. The first record will be found according to Index 3 whose value(s) in the field(s) which make up Index 3 is greater than or equal to (GE) the value(s) previously put into the record buffer for the field(s).

2. Naming the field whose main index is to be used:

Find GE customer.name

The main index for the field "name" of the database table customer is used for the Find command. Note that DataBase Builder is used to set up the indices for your database.

Notes

  • Recnum, the record number, is Field 0 in every table, and may always be found by as though it is an index. For tables lacking actual indexes, it is the only "index".

  • A Find GT or GE command on a cleared record buffer will find the first record in the table by the index specified. A Find LT or LE will find the last record for the specified index.

  • Find commands must specify an index or indexed field to use. A find command executed on non indexed fields will generate an error.

  • In the case of a multi segment index, DataFlex uses all segments of the index to execute the find, including the record number if it is part of the index. This is of particular importance in the case of non unique indexes, which always include the record number as the last segment.

  • Indexes may be created in table definitions in the Database Builder. Existing indexes may be redefined in the Database Builder and from DataFlex programs. Indexes may be rebuilt with Database Builder or the sort command. The "uppercase" and "descending" options may be applied to the segments that make up an index. The Uppercase option affects the order of finding, and when the descending option is used, it reverses the effects of LT, LE, GE, or GT.

  • If a Find command is executed on an active, edited record buffer, DataFlex Error 82 (Edited record not saved) will be triggered. The record buffer becomes edited when data has been moved to it. The buffer becomes unedited automatically by saving the record. If you wish to deactivate the buffer and maintain the data without saving, you can do so by moving 0 to df_tablename.recnum.

  • Subsequent calls to the Boolean expression Found after a successful find will return TRUE. After a find error, Found will return FALSE.

  • Subsequent calls to the Boolean expression FindErr after a successful find will return FALSE. Otherwise, FindErr will return TRUE to show that an error occurred.

  • Find EQ commands may only be used with unique indexes. If they are used with non unique indexes, they will never find a record.

  • After a find, programs will not load the record buffer with record data until the program calls for data not contained in a non-case-sensitive segment of the index used for the find. This can improve program performance considerably where no data is called for that would require the record buffer to be loaded. This default behavior of the DataFlex database driver can be changed by using the FLEX_SET_INDEX_OPT function with the call_driver command. Optimization can be turned off, so that the record buffer is always loaded, or it can be set "permissive," in which data in case-insensitive index segments is also eligible for use.


Float

See Also: Declaring Variables, Variable Declaration Commands, Struct

Purpose

Declares one or more single precision 32 bit floating point variables.

Syntax

To declare Float variables

Float {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Float variable. The first {identifier} is required.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Float

Float{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Float command declares Float variables. A Float is a 32-bit IEEE floating point number. The Float data type has a Mantissa precision of 7, and an exponent range of 10^-38 to 10^38.

Up to nine variables may be declared on one command line, with their names separated from each other by spaces. Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

Float fMyVar

Move 3.9999 To fMyVar

End_Procedure

This example declares one variable of type Float, named fMyVar, and initializes it.

Float[] fPrecisionValues

This example declares 1 dynamic array variable, named fPrecisionValues, containing an undefined number of elements of type Float.

Float[5] fPrecisionValues

This example declares 1 static array variable, named fPrecisionValues, containing 5 of elements of type Float.

Float[][3] fPrecisionValues

This example creates a two-dimensional dynamic array variable named fPrecisionValues, containing an undefined number of elements of type Float. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • Compatible with the IEEE specification.

  • If you need to define a global Float variable, you should use the global_variable command to do so.


For

See Also: Boolean Expressions, Execution Control Commands, Loop, Repeat, Until, While, Break, Boolean

Purpose

Executes a block of code in an iteration.

Syntax

For {counter} From {start-value} To {stop-value}

…

Loop

What It Does

When a For ... From ... To command line first executes, the value of {start-value} is moved to the variable {counter}. Then (and upon each re execution of the block) the value of {counter} is compared with that of {stop-value}. If the current value of {counter} is less than or equal to that of {stop-value}, the block of statements executes. Each time the block executes to completion, the value of {counter} is incremented by Loop, and there is a new range test on {counter}. Once the value of {counter} is greater than {stop-value}, the program continues execution on the line after Loop.

Example

This example displays 10 lines of text to the ShowLn console, using each of the loop constructs.:

Integer i

For i From 1 To 10

Showln "For - Line: " i

Loop

Notes

  • {stop-value} is evaluated each time the loop is executed. If {stop-value} is a constant or a variable, the loop will execute faster than if it is a database field or expression.

  • Do not change the values of the loop range or the counter inside the For .. Loop block unless there is no other choice. Visual DataFlex will allow you to change any of these variables, but this practice can lead to many subtle bugs. Changing the start value within a loop will never change the execution of the loop.

  • Use For ... Loop for loops where the counter is incremented by one. Use Repeat…Until and While…Loop for loops of greater complexity.

  • If {start-value} is greater than {stop-value} when the For command line is first executed, the block of statements will not execute.

  • You may place For ... From ... To blocks inside other looping blocks up to a limit of 40.

  • You may freely use For … From … To blocks with Repeat and While blocks, but they may not overlap — you must end the innermost block first, then the next innermost, and so on.


For_All

See Also: Boolean Expressions, Execution Control Commands

Purpose

This set of macros implements a constraint oriented file-scanning and processing structure. The report object has similar capabilities, but for_all is designed for record processing, not report printing. Also, for_all blocks may be nested within other for_all blocks.

Syntax

use for_all.pkg

for_all file {by | down} {index | field} [as {queue | que}] {do |

constraint clauses

:

do}

processing routine

:

end_for_all

Argument | Explanation
file | A database filename.
by | down | Specifies scanning in ascending or descending order, respectively.
index | field | Specifies index to use for sequence of processing; if field is used instead of index, the main index of the field will be used.
as queue | que | Scans for each record from beginning of defined constraints.
do | Do on the for_all command line causes all the records in a file to be used; if do is used on a for_all command line, constraint clauses are not allowed.
constraint clauses | Set of constraint clauses as defined by the constraint package; must be followed by do to mark the end of the constraint clauses and the beginning of the processing routine.
processing routine | Routine (multiple statements are allowed) that processes each record that satisfies the constraint clauses.

What It Does

Starts scanning structure by specifying file and ordering; as queue option indicates that the file should be initialized to the lower boundary constraints before each find; do on for_all command line indicates no constraints—all records in the file.

Example

To output the extension of all line items for all invoices by customer name alphabetically, the following code would suffice:

for_all customer by index.1 do //all Customers by Name

for_all invoice by index.1 //all Invoices for Customer

constrain invoice relates to customer

do

for_all invcitem by index.1 //all Items for Invc

constrain invcitem relates to invoice

do

write customer.customer_name

write ", " invoice.invoice#

write ", $ " invcitem.extension

end_for_all

end_for_all

end_for_all

The above example assumes that index.1 of the customer file is for customer.customer_name (non-unique), index.1 of the invoice file is for customer.recnum + invoice.invoice#, and index.1 of the invcitem file is for invcitem.invoice# (non-unique).

Notes

This structure allows a processing operation to be performed on a set of records. Typical processing operations might be the mass update or deletion of records, adding items to a list or Array object , or copying records from one file to another.

Often, the processing routine performs an update to a field which is part of the scanning index or deletes a record. In some rare cases, this may cause records to be skipped or processed a second time. To avoid this, you may 1) use the queue option, which starts the scan at the beginning every time, or 2) save off the indexed fields (including recnum, if that is part of the index) into temporary variables at the beginning of the processing routine, then clear the file and move the values back into the fields at the end of the routine.

Constraint Clauses

Constraints are used to limit the records which will be scanned. See the constrain documentation for details of command syntax and usage.

Example

Example to display orders for each customer by date, with customers shown alphabetically by name:

for_all customer by index.1 do

showln "Customer: " customer.customer_name

for_all order by index.2

constrain order relates to customer

do

showln order.date " $ " order.total

end_for_all

end_for_all

Option As queue | Que

The use of this option forces the for_all construct to clear and initialize the record buffer prior to each find. It should be used when the processing routine for the for_all construct changes the record so that it no longer belongs to the set being processed. This may occur when the records are being deleted, or when a key field is being edited and the set is constrained by that key field.

Example

For example, we may need to scan all paid invoices, and perform some processing on them (like creating a history and/or accounting records) which changes them into posted invoices. The following code would suffice, assuming that index.1 of invoice is invoice.status +invoice.invoice#:

for_all invoice by index.1 as queue

constrain invoice.status eq status_paid

do

{post accounts, create history records}

:

move status_posted to invoice.status

saverecord invoice

end_for_all

If we executed the above without the as queue option, it would process only the first paid invoice.

Continue Indicator

If the continue indicator is set false, the current processing loop will be terminated and execution will proceed back to the prior level:

Example

For_All Flexerrs By Recnum

Do

Sleep 1

Showln Flexerrs.Error_Descr

If (Flexerrs.Recnum > 6) ;

move False to Continue

End_For_All

In this example, the records of File flexerrs are processed until the first record with recnum greater than 6 is processed, at which point execution exits the loop.


Forward

See Also: Broadcast, Delegate, Get, Send, Set

Purpose

To invoke the superclass implementation of a procedure or function.

Syntax

Forward {Get | Set | Send} {message} ...

What It Does

A function or a procedure of a class sometimes needs to execute the code defined for the same message in an object's superclass. When this is true, we say that the implementation of the message in the class is an augmentation. The Forward command is used to invoke the code defined for a message in a superclass of the object's class.

An object that declares functions and procedures actually creates a class, especially for the object. When the Forward command is used in the functions and procedures within an object declaration, the system will forward to an implementation of the object's class, before forwarding to an implementation of the object's superclass.

Example

The following example shows the augmentation of six messages. Three messages are implemented in the object's class and three messages are implemented in the superclass of the object. All the implementations in the class forward to the superclass. The implementations in the object forward to either the class or superclass, depending on whether there is an implementation in the object's class.

Class cSuperClass Is A Button

Procedure Construct_Object

Forward Send Construct_Object // Always forward construct_object!

Property String psProperty Public "Some Property"

End_Procedure

Procedure OnEvent1 String sString1 String sString2

Showln "In OnEvent1 of the Superclass. "

Showln "String 1 = " sString1 ", String 2 = " sString2

End_Procedure

Procedure OnEvent2 String sString1 String sString2

Showln "In OnEvent2 of the Superclass. "

Showln "String 1 = " sString1 ", String 2 = " sString2

End_Procedure

Function Func1 String sString1 String sString2 Returns Integer

Showln "Inside Func1 of cSuperClass"

Showln "String 1 = " sString1 ", String 2 = " sString2

Function_Return 1

End_Function

Function Func2 String sString1 String sString2 Returns Integer

Showln "Inside Func2 of cSuperClass"

Showln "String 1 = " sString1 ", String 2 = " sString2

Function_Return 2

End_Function

End_Class

Class cSubClass Is A cSuperClass

Procedure Set psProperty String sSomeValue

Showln "In cClass. Setting property to " sSomeValue

Forward Set psProperty to sSomeValue

Showln "In cClass. All done setting property to " sSomeValue

End_Procedure

Procedure OnEvent1 String sParam1 String sParam2

Showln "In OnEvent1 of cClass - Before Forwarding"

Forward Send OnEvent1 sParam1 sParam2

Showln "In OnEvent1 of cClass - After Forwarding"

End_Procedure

Function Func1 String sParam1 String sParam2 Returns Integer

Integer iRetVal

Showln "Inside Func1 of cClass - Before Forwarding"

Forward Get Func1 sParam1 sParam2 To iRetVal

Showln "Inside Func1 of cClass - After Forwarding"

Function_Return iRetVal

End_Function

End_Class

Object oTest Is A cSubClass

Procedure OnEvent1 String sParam1 String sParam2

Showln "In OnEvent1 of the object - Before Forwarding"

Forward Send OnEvent1 sParam1 sParam2

Showln "In OnEvent1 of the object - After Forwarding"

End_Procedure

Function Func1 String sParam1 String sParam2 Returns Integer

Integer iRetVal

Showln "Inside Func1 of object - Before Forwarding"

Forward Get Func1 sParam1 sParam2 To iRetVal

Showln "Inside Func1 of object - After Forwarding"

Function_Return 1

End_Function

Procedure OnEvent2 String sParam1 String sParam2

Showln "In OnEvent2 of the object - Before Forwarding"

Forward Send OnEvent2 sParam1 sParam2

Showln "In OnEvent2 of the object - After Forwarding"

End_Procedure

Function Func2 String sParam1 String sParam2 Returns Integer

Integer iRetVal

Showln "Inside Func2 of object - Before Forwarding"

Forward Get Func2 sParam1 sParam2 To iRetVal

Showln "Inside Func2 of object - After Forwarding"

Function_Return 1

End_Function

End_Object


Function

See Also: Methods, Variable Parameter Lists, End_Function, Function_Return, Get, Procedure

Purpose

To define a function.

Syntax

Function {function-name} [Global/Overloaded] [{type} [ByRef] {param} … ] Returns {return-type}

… // Statements of function body.

End_Function

Argument Explanation

{function-name} The name of the function being created.

{type} The data type of each parameter param in the parameter list.

{param} The name of the parameter passed to the function.

{return-type} The data type of the value returned by the function.

What It Does

A class's behavior is defined by the methods that it implements. In Visual DataFlex, there are two types of methods: functions and procedures. A function is used whenever you require a return value whereas procedures are useful for implementations of events.

The Function command defines an implementation of a function in the object or class where it is defined. Within the scope of the function are the variables on the parameter list and any variables declared within the body of the function.

You may call a function with the various forms of the Get command (e.g; Delegate Get and Forward Get, Broadcast Get) or by using it in an expression:

Object oTest Is A Button

// Define a function that changes the order of the name

// and places a comma separator.

Function SwitchName String sFirstName String sLastName Returns String

Function_Return ( sLastName + "," + sFirstName)

End_Function

Procedure OnClick

String sSwitchedName

Move (SwitchName("John", "Smith")) to sSwitchedName

Showln "Formatted Name is " sSwitchedName

Get SwitchName "John" "Smith" to sSwitchedName

Showln "Formatted Name is " sSwitchedName

End_Procedure

End_Object

The name of the function, fnName, must be unique throughout the program.

The End_Function command defines the end of the function-definition block. You may use the Function_Return command within the body of the function to exit the function, returning a value. If no Function_Return executes before the End_Function command, the function returns zero.

Global Functions

The keyword Global allows you to define a global function. A global function may be used throughout your program. The following is the same example as before, but the function is now defined as global.

Function SwitchName Global String sFirstName String sLastName Returns String

Function_Return( sLastName + "," + sFirstName)

End_Function

Object oTest Is A Button

// Define a function that changes the order of the name

// and places a comma separator.

Procedure OnClick

String sSwitchedName

Move (SwitchName("John", "Smith")) to sSwitchedName

Showln "Formatted Name is " sSwitchedName

Get SwitchName "John" "Smith" to sSwitchedName

Showln "Formatted Name is " sSwitchedName

End_Procedure

End_Object

Note that like VDF expression functions, when a global function is invoked, you do not put an object reference such as "Self". Global functions are not sent to objects. They are defined for the whole system.

By Reference Parameters

The special ByRef keyword can be used to specify a parameter that is passed by reference instead of by value. When a parameter is passed by reference the code that calls the function must pass the address of a variable of the correct type as the parameter. By reference parameters allow the function to directly modify the value of the variable passed to it. For example…

Function LeftMostChar Global String ByRef sValue Returns String

// Returns the leftmost character of the passed string. Removes

// this character from the passed string.

String sReturns

Move (Left(sValue, 1)) to sReturns

Move (Remove(sValue, 1, 1)) to sValue

Function_Return sReturns

End_Function

String sName sChar

Integer iLength

Move "Frank Lloyd Wright" to sName

While (Length(sName) > 0)

Move (LeftMostChar(&sName)) to sChar

Show sChar " "

Loop

For more information refer to Parameter Passing.

Overloaded Functions

The keyword Overloaded allows you to define an overloaded function method. For more information refer to Method Overloading in the Language Guide.

Notes

  • If you call a function and pass an parameter that does not match the type in your function declaration, Visual DataFlex will perform type conversion.

  • The total number of parameters passed to a function is contained in the predefined variable Num_Arguments. This feature allows you to create different implementations for the same function, depending on the number of parameters provided.

  • User defined and predefined functions may be included in user defined functions, down to a maximum depth of 18 levels, but a user-defined function may not be defined within a global function.

  • Global functions may not be overloaded.


Function_Return

See Also: Function, End_Function

Purpose

To return execution from a function with a return value.

Syntax

Function_Return {return-value}

Return_value is the constant or variable whose value is returned.

What It Does

The Function_Return command terminates execution of a function and returns a value to the caller. If no return_value is supplied for the command, zero is returned. Execution returns to the line following the call to the function.

There may be as many Function_Return commands as desired in the body of the function, but no more than one will execute each time the function is called. Functions with many exits often become more difficult to debug.

If return_value is a variable, its type does not have to match the type given in the function command for the return value, but its value must be convertible to that type.

Notes

  • If no Function_Return is executed before execution reaches the End_Function command, execution will return at that point with a return_value of zero.


Get

See Also: Method Overloading, Function, Property, Set

Purpose

To get the value of a function or object property.

Syntax

Get {method-name} [of {object-ID}] [{param1 … paramN}] To {receiving-variable}

Argument Explanation

Argument | Explanation
{method-name} | Is the name of the function method or property;
{object-ID} | Is a handle to the object who's method is being executed;
{param1 … paramN} | Are all parameters that are passed to the Function method
{receiving-variable} | Is the variable that is assigned the value returned by the Function method.

The order of the parameters must match the list of parameters in the method's declaration. The parameters you pass can be either constants, variables or expressions, so long as they are of comparable type to the matching parameters in the method declaration.

What It Does

The Get command is used to get the value of an object's property or call a function method of an object. An object function may be invoked for a given object; however, commonly the destination object is omitted, and the object function operates on the current object, Self.

If the data type of the variable that receives the value variable does not match the return type of the function, the data is converted to the data type of variable. In Visual DataFlex, arguments to functions are passed by value. Type conversion is also performed on the arguments, so that the function parameter requirements are satisfied. For example, if the second parameter of a function is an integer, and the function requires that it is a string, Visual DataFlex will perform type conversion, so the function receives a string parameter.

Properties in Visual DataFlex define two messages: one function Get_propname and one procedure Set_propname. Here is an example of the Get command accessing a property and invoking a function:

Class cTestClass is a cObject

Procedure Construct_Object Integer Image

Forward Send Construct_Object

Property Integer piProperty 1

End_Procedure // Construct_Object

Function Func1 String sParam1 Returns Integer

Showln "In Func1 - String Param is: " sParam1

Function_Return 2

End_Function // Func1

Procedure Test

Integer iValue

Get Func1 "Hello World" To iValue

Showln "Function Func1 returned: " iValue

Get piProperty to iValue

Showln "Property piProperty is: " iValue

End_Procedure // Test

End_Class

Struct Properties

Special consideration needs to be given for accessing data that is stored in class properties that are of struct type. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire struct. This works just like a struct variable assignment.

To read or write individual members of a struct property, it is necessary to get the property to a local struct variable of the same type. You would then manipulate the data of this local struct and write back the changes by setting the struct property once again.

Example…

struct tNameAndAddress

string sName

string sAddress

end_struct

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare a struct property

Property tNameAndAddress pContact

End_Procedure

Procedure StoreName String sName

tNameAndAddress contact // create a local struct variable

// get the struct property to the variable.

Get pContact to contact

// show the current name.

Send Info_Box ("The current name is: " + contact.sName)

// change the name.

Move sName to contact.sName

// Save the change back to the struct property.

Set pContact to contact

End_Procedure

End_Class

Array Properties

Special consideration needs to be given for accessing data that is stored in array properties. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire array. This works just like an array variable assignment.

To read or write individual array property elements, it is necessary to get the property to a local array variable of the same type. You would then manipulate the data of this local array and write back the changes by setting the array property once again.

Example…

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare an array property

Property string[] psNames

End_Procedure

Procedure StoreName String sNewName

string[] sNames // create a local array variable

integer iElementCount

// get the array property to the variable.

Get psNames to sNames

// Add the new name.

Move (SizeOfArray(sNames)) to iElementCount

Move sNewName to sNames[iElementCount]

// Save the change back to the array property.

Set psNames to sNames

End_Procedure

End_Class

Item-Based Properties

The compiler must explicitly recognize that a message requires an index parameter. Special compiler commands are created to identify these messages. The indexed messages identified as current-item based, which means that current_item is used if the index parameter is omitted, are:

Value | Message | Aux_Value
Shadow_State | Select_State | Checkbox_Item_State
Autoclear_State | Center_State | Entry_State
Item_Changed_State | Item_Entry_Msg | Item_Exit_Msg
Item_Validate_Msg | Data_File | Data_Field
Data_Window | Item_Options | Item_Option
Prompt_Object | Zoom_Object |

The indexed messages identified as Form based, which means that zero is used if the index parameter is omitted, are:

Form_Width | Form_Color | Form_Datatype
Form_Options | Form_Font | Form_Row
Form_Column | Form_Typeface | Form_Fontheight
Form_Fontweight | Form_Fontitalics | Form_Fontunderline
Button_Aspect | Form_Height | Form_Guiwidth
Form_Guiheight | Form_Guirow | Form_Guicolumn
Form_Margin | Form_Option | Form_Style
Form_Extended_Style | Form_Border | Password_State
Form_Mask | Form_Button | Form_Button_Value
Form_Window_Handle |  |

The difference between current-item based and form based messages are historical. Since we only recommend that you omit the index parameter on single item objects the current-item should always be zero. This means that both types of messages should be treated the same.

We advise that you always omit the item index parameters for objects that are single item objects (in which case current_item should be zero anyway). Examples of single item objects are dbForms, Forms, and ComboForms. For example, when in a dbForm the Value property should be accessed as follows:

Set Value of oMyDbForm to "form test value"

We advise that you always include the item index parameter in multi-item objects. Examples of multi item objects are Arrays, Grids, dbGrids and dbLists. For example, when in an array the Value property should be accessed as follows:

For iCount from 1 to 10

Set Value iCount to "Array test value"

Loop

Every property has a known data type. If value is a variable of other than the type specified in the property, its value will be converted automatically to the required type.

Notes

  • In older programs you will see the keyword item before the index value (e.g., set Value item 0 to "x"). The item keyword is optional. Its usage is no longer recommended.

  • Some properties, such as Location and Size, define complex return values, where two short integers (16 bits) are packed into a single 32-bit value. Use the Hi and Low functions to extract from the return value.

  • If the data type of the variable that receives the value variable does not match the return type of the function, the data is converted to the data type of variable.

  • The Get command can also be used to call global functions, however the prefered method for doing this is to use an expression. For more information see Calling Functions.


Get_Argument_Size

See Also: Argument Size, Set_Argument_Size

Purpose

To retrieve the current argument size setting. Argument size is the largest size permitted for string variables.

Syntax

Get_Argument_Size To {variable}

What It Does

Get_argument_size places the number of bytes the maximum argument size can hold into variable.

integer iArgSize

get_argument_size to iArgSize

In this example, the maximum argument size is moved to Variable argSize.

The default maximum argument size can be found under Argument Size in the VDF Specifications book. It can be increased or decreased from this value by the set_argument_size command. Get_argument_size is useful for storing the maximum argument size in effect in a program or a part of a program for later use by the set_argument_size command to restore the maximum argument size after it has been changed elsewhere.

set_argument_size argSize

In this example, the maximum argument size in the program has been set to the value of Variable argSize.


Get_Attribute

See Also: Database API Attributes, Set_Attribute

Purpose

To retrieve a global, file, field, or index attribute.

Syntax

Get_Attribute {attribute} [of {table-handle} ;

[{field-num} | {index-num} [{segment-num}]]] ;

To {variable}

Argument Explanation

attribute Attribute ID to be retrieved.

{table-handle} Optional handle for either a table or a structure.

fieldNum Optional field to be interrogated.

indexNum Optional index to be interrogated.

segmentNum Number of a segment in indexNum to be interrogated.

variable A variable to hold the value of the attribute. It should be of the same type as the attribute, if known. Otherwise, you can safely use a String variable here.

What It Does

Visual DataFlex stores information about database tables as a set of system, table, index, and field attributes. Get_Attribute allows your program to retrieve the current setting of a given attribute.

Example – Runtime Attribute

integer iFreq

get_attribute DF_RUNTIME_PROGRESS_FREQUENCY to iFreq

send Info_Box ( (string(iFreq))+" milliseconds") ;

"Runtime progress frequency interval"

This example retrieves and displays the interval between runtime progress updates.

Example – Global Attribute

string sFileListName

get_attribute DF_FILELIST_NAME to sFileListName

send Info_Box sFileListName "Current filelist name & path"

This example retrieves and displays the name and full path to the current filelist.

Example – table Attribute

handle hTable

string sName

open OrderHea

move OrderHea.File_Number to hTable

get_Attribute DF_FILE_ROOT_NAME of hTable to sName

send Info_Box sName ("Root name of table "+(string(hTable)) )

This example retrieves and displays the rootname of the OrderHea table.

Example – Field Attribute

integer iField iIndex

handle hTable

open Customer

move Customer.File_Number to hTable

move 2 to iField

get_attribute DF_FIELD_INDEX of hTable iField to iIndex

send Info_Box ("Index "+(string(iIndex)) ) ("Main index for field "+(string(iField)) )

This example determines the main index for field number 2 in the Customer table.

Example – Index Attribute

integer iIndex iSegments

handle hTable

string sTableName

move 2 to iIndex

open Customer

move Customer.File_Number to hTable

get_attribute DF_INDEX_NUMBER_SEGMENTS of hTable iIndex to iSegments

get_Attribute DF_FILE_DISPLAY_NAME of hTable to sTableName

send Info_Box ( (string(iSegments))+" segments") ;

("Segments of index number "+(string(iIndex))+" of "+sTableName+" table ")

This example retrieves and displays the number of segments for index number 2 of the Customer table.

Example – Index-Segment Attribute

integer iIndex iSegment iField

handle hTable

string sFieldName sTableName

open Customer

move Customer.File_Number to hTable

move 2 to iIndex

move 1 to iSegment

get_Attribute DF_INDEX_SEGMENT_FIELD of hTable iIndex iSegment to iField

get_Attribute DF_FIELD_NAME of hTable iField to sFieldName

get_Attribute DF_FILE_DISPLAY_NAME of hTable to sTableName

send Info_Box sFieldName ("Field name in segment "+(string(iSegment))+" of index ";

+(string(iIndex))+" of table "+sTableName)

This example determines and displays the name of the field in segment 1 of index 2 of the Customer table.

Runtime Attributes

DF_RUNTIME_PROGRESS_FREQUENCY

Global Attributes

DF_ALL_FILES_TOUCHED*

DF_DATE_FORMAT

DF_DATE_SEPARATOR

DF_DRIVER_NAME*

DF_DRIVER_NUMBER_SERVERS*

DF_DRIVER_SERVER_NAME*

DF_DECIMAL_SEPARATOR

DF_FILELIST_NAME

DF_HIGH_DATA_INTEGRITY

DF_LOCK_DELAY

DF_LOCK_TIMEOUT

DF_NUMBER_DRIVERS*

DF_OPEN_PATH

DF_REPORT_UNSUPPORTED_ATTRIBUTES

DF_REREAD_REQUIRED

DF_STRICT_ATTRIBUTE

DF_TRANSACTION_ABORT

DF_TRAN_COUNT

File Attributes

DF_FILE_ALIAS

DF_FILE_CHANGED*

DF_FILE_COMMITTED*

DF_FILE_COMPRESSION+

DF_FILE_DISPLAY_NAME+

DF_FILE_DRIVER+*

DF_FILE_HANDLE_TYPE*

DF_FILE_INTEGRITY_CHECK+

DF_FILE_IS_SYSTEM_FILE

DF_FILE_LOCK_TYPE+

DF_FILE_LOGICAL_NAME+

DF_FILE_LOGIN

DF_FILE_MAX_RECORDS+

DF_FILE_MODE

DF_FILE_MULTIUSER+

DF_FILE_NEXT_EMPTY+

DF_FILE_NEXT_OPENED*

DF_FILE_NEXT_USED+*

DF_FILE_NUMBER*

DF_FILE_NUMBER_FIELDS+*

DF_FILE_LAST_INDEX_NUMBER+*

DF_FILE_OPEN_MODE*

DF_FILE_OPENED*

DF_FILE_OWNER+

DF_FILE_PHYSICAL_NAME+

DF_FILE_RECORD_IDENTITY+

DF_FILE_RECORD_LENGTH+

DF_FILE_RECORD_LENGTH_USED+*

DF_FILE_RECORDS_USED+*

DF_FILE_RESTRUCTURE*

DF_FILE_REUSE_DELETED+

DF_FILE_ROOT_NAME+

DF_FILE_STATUS

DF_FILE_TOUCHED*

DF_FILE_TRANSACTION+

DF_FILE_TYPE+*

Field Attributes

DF_FIELD_INDEX+

DF_FIELD_LENGTH+

DF_FIELD_NAME+

DF_FIELD_NATIVE_LENGTH+*

DF_FIELD_NUMBER+*

DF_FIELD_OFFSET+

DF_FIELD_OLD_NUMBER

DF_FIELD_OVERLAP+*

DF_FIELD_PRECISION+

DF_FIELD_RELATED_FIELD+

DF_FIELD_RELATED_FILE+

DF_FIELD_TYPE+

Index Attributes

DF_INDEX_KEY_LENGTH+*

DF_INDEX_LEVELS+*

DF_INDEX_NUMBER_BUFFERS

DF_INDEX_NUMBER_SEGMENTS+

DF_INDEX_TYPE+

Index-Segment Attributes

DF_INDEX_SEGMENT_CASE+

DF_INDEX_SEGMENT_DIRECTION+

DF_INDEX_SEGMENT_FIELD+

* Read-only attribute.

+ Permanent attribute.


Get_Channel_Position

See Also: File I/O Commands, Append_Output, Direct_Input, Direct_Output, Set_Channel_Position, Sequential File I/O

Purpose

Gets the value of the file offset of a sequential file channel.

Syntax

Get_Channel_Position {channel-num} To {variable}

Argument Explanation

{channel-num} A value between 0 and 9, the sequential channel. 0 is the default for Direct_Input, 1 is the default for Direct_Output.

variable A variable into which the number of the channel is returned.

What It Does

The channel position is the offset to the last byte accessed in a sequential file. If a file is opened with Direct_Input, the channel position will return the last byte read by input commands such as Readln. For files opened with Direct_Output or Append_Output, the channel position will return the last byte written by output commands such as Writeln.

Get_Channel_Position can return two values that have a special meaning. Position 0 is before the first byte in the file, while the value 1 is after the end of the file. The position can be set to after the end of a file using Set_Channel_Position.

Example

Integer iCount

Integer iPos

String sBuffer

// Create a text file

Direct_output "hello.txt"

For iCount From 1 To 10

Get_Channel_Position 1 To iPos

Showln "Writing at offset " iPos " in hello.txt"

Writeln "Line: " iCount " - Hello!"

Loop

Get_Channel_Position 1 To iPos

Close_Output

Showln "Position at end of file in hello.txt is " iPos

// Error returns 0.

Get_Channel_Position 9 To iPos

Showln "Error position is " iPos

// Open file for input.

Direct_Input "hello.txt"

While (Not(Seqeof))

Get_Channel_Position 0 To iPos

Showln "Reading at position " iPos " in hello.txt is " iPos

// Read from the text file.

Readln sBuffer

Loop

Close_Input

Notes

  • When a file has been opened by the Direct_Input command, its channel position is zero (0) (the beginning of the file). After an Append_Output command, the position is at the end of the file.

  • A Get_Channel_Position command immediately after an Append_Output command returns the size of the file.

  • A Get_Channel_Position on a closed channel will return a zero (0).

  • To move the pointer for a sequential input/output channel, use the Set_Channel_Position command.

  • Caution: Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Get_Channel_Size

See Also: File I/O Commands, Direct_Input, Direct_Output, Set_Channel_Position

Purpose

To determine the size (in bytes) of a sequential file opened with append_output, direct_input or direct_output command.

Syntax

Get_Channel_Size {channel-num} To {variable}

Argument Explanation

iChannelNumber A value between 0 and 9, representing the sequential file I/O channel.

variable A variable that is set to the size of the sequential file.

What It Does

This command returns the number of bytes or characters (including line formatting characters, such as carriage return and line-feed) of a sequential file. The specified channel must refer to an open sequential file. Zero is returned if Set_Channel_Size acts on a closed channel.

Example

Integer iCount

Integer iSize

String sBuffer

// Create a text file

Direct_output "hello.txt"

For iCount From 1 To 10

Get_Channel_Size 1 To iSize

Showln "File size of hello.txt is " iSize " bytes."

Writeln "Line: " iCount " - Hello!"

Loop

Get_Channel_Size 1 To iSize

Close_Output

Showln "The size of hello.txt is " iSize

// Error returns 0.

Get_Channel_Size 9 To iSize

Showln "Error channel size is " iSize

// Open file for input.

Direct_Input "hello.txt"

Get_Channel_Size 0 To iSize

Showln "After Direct_Input hello.txt is " iSize " bytes"

Close_Input

Notes

  • Caution: Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Get_Current_Directory

See Also: Direct_Input, Get_Drive_Directory, RunProgram

Purpose

To return the full path of the user's current directory, including the drive letter.

Syntax

Get_Current_Directory To {variable}

What It Does

Get_Current_Directory returns the current working directory in variable, variable. The current directory is generally the ProgramPath value in the selected Workspace key, but it can be changed. The example below demonstrates how the current directory name is fetched, changed to the root directory of drive C, and then queried again.

Example

String sDir

// Retrieve the current directory.

Get_Current_Directory To sDir

Showln "The current directory is " sDir

// Set to the root directory of drive C

Set_Directory "C:\"

// Now, get the new current directory.

Get_Current_Directory To sDir

Showln "Now, the current directory is " sDir

Notes

  • If relative paths are used to describe workspace directories, you should not change the current directory.

  • Caution: Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Get_Current_Input_Channel

See Also: File I/O Commands, get_Current_Input_Channel, Get_Channel_Position, Get_Current_Output_Channel, Sequential File I/O

Purpose

To retrieve the number of the sequential file channel currently being used for input.

Syntax

Get_Current_Input_Channel To {variable}

Argument Explanation

variable A variable that will hold the default input channel.

What It Does

The Get_Current_Input_Channel returns the default input channel into the specified variable, variable. Readln and other sequential input commands read from the default input channel.

Example

Integer iDefaultChannel

// Retrieve the current default input channel.

Get_Current_Input_Channel To iDefaultChannel

Showln "The current input channel is " iDefaultChannel

Notes

  • Using get_Current_Input_Channel causes the current input channel number to change to the mentioned channel, and does not close the previously opened device on that channel. This technique is useful when the channel dependent variables (such as SeqEOF) need to be processed.

    Caution:     Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Get_Current_Output_Channel

See Also: File I/O Commands, Direct_Input, Get_Channel_Position, Get_Current_Input_Channel , Sequential File I/O

Purpose

To retrieve the number of the sequential file channel currently being used for output.

Syntax

Get_Current_Output_Channel To {variable}

Argument Explanation

variable A variable that will hold the default output channel.

What It Does

The Get_Current_Output_Channel returns the default output channel into the specified variable, variable. Writeln and other sequential output commands write to the default output channel.

Example

Integer iDefaultChannel

// Retrieve the current default output channel.

Get_Current_Output_Channel To iDefaultChannel

Showln "The current output channel is " iDefaultChannel

Notes

  • Using get_Current_Output_Channel causes the current output channel number to change to the mentioned channel, and does not close the previously opened device on that channel. This technique is useful when the channel dependent variables (such as SeqEOF) need to be processed.

    Caution:     Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Get_Current_User_Count

See Also: Get_Licensed_Max_Users

Purpose

Returns the number of users currently logged into Visual DataFlex using the same serial number (that use the same serial number as the program executing this code). Note that this is not the number of users on a server. If the license is registered with an unlimited number of users, this command will return 0.

Syntax

get_Current_User_Count integer_variable

Example

integer iUserCount

get_Current_User_Count to iUserCount

This example retrieves the current number of users logged in to the integer variable iUserCount.


Get_Directory

See Also: File_Exist, Make_Directory, Make_Temp_File, Remove_Directory, Valid_Drive

Purpose

To obtain the current working directory for a given drive letter.

Syntax

Get_Directory [{drive}] {variable}

Argument Explanation

drive The letter designating the disk drive. You may terminate the variable with a colon, ':', if you wish. That is, both "C" and "C:" are acceptable values for drive. If the parameter drive is omitted, the current drive is assumed.

What It Does

Get_Directory returns the current working directory in variable, variable, for a given drive. The following example shows how to get current directories for all valid drives.

Example

String sDir

Integer i // Counter for all drives.

Integer bInvalidDrive

// Retrieve the current directory.

For i From 65 To 90 // A to Z

// Check if drive is OK.

// Note: Can still have a media not ready error.

Valid_Drive (Character(i)) bInvalidDrive

If (Not(bInvalidDrive)) Begin

Move "" to sDir // Reset the value

Get_Directory (Character(i)) sDir

Showln "Current directory for drive ";

(Character(i)) " is " sDir

End

Loop

Notes

  • If the specified drive does not exist or contains bad media, an error is reported by the system.


Get_Date_Attribute

See Also: Set_Date_Attribute

Purpose

To return the values of attributes that control the behavior of the date system with regard to the century change at the Year 2000.

Syntax

Get_Date_Attribute {attribute} To {variable}

Argument Explanation

attribute SysDate4_State controls whether the sysdate command returns dates with the year in two or four digits.

Date4_State controls whether entries of dates with two-digit years are converted to and from dates with four-digit years on saving to and retrieving from disk respectively.

Epoch_Value sets the two-digit year value above which dates are considered to be in the 1900s and below which dates are considered to be in the 2000s.

variable To hold True or False for SysDate4_State and Date4_State and Integer values 0 through 99 for Epoch_Value.

What It Does

Get_date_attribute returns the values of the three attributes that manage the running program's behavior in entry of dates with two-digit years with regard to the change of century at the Year 2000.

Get_Date_Attribute Date4_State To iConverted

In this example, Integer Variable converted is zero if the value of Date4_State is False, and one if it is True.

Notes

  • Settings of Epoch_Value have no effect if Date4_State has not been set to True.

  • If the running program has not executed a Set_Date_Attribute Date4_State command, this command gets the values of the UseEpoch registry key. If no Set_Date_Attribute Epoch_Value statement has been executed, it get the value of the Epoch registry key.


Get_Environment

See Also: Get_Current_Directory, Runprogram

Purpose

To read the value of an environment variable into the program.

Syntax

Get_Environment {name} To {variable}

What It Does

Get_Environment searches for a defined environment variable {name} and returns the value of the environment variable in {variable}. If {name} is not found, {variable} is set to null.

Get_Environment only searches the startup environment.


Get_FieldNumber

Purpose

Returns the field number for the file and field passed as argument at compile time.

Syntax

Get_FieldNumber FileName.FieldName to integer_variable

What It Does

This command returns the field number for the file and field passed as argument at compile time. It is very important to note that this happens at compile time.

Example

integer iField iFile hDD

string sValue

move Customer_DD to hDD

Get_FieldNumber Customer.Name to iField

Get_FileNumber Customer.Name to iFile

Get File_Field_Current_Value of hDD iFile iField to sValue

This example retrieves the file and field numbers of the Customer.Name database field and then retrieves the value of that field to the string variable sValue.

Notes

  • Whenever FILE_FIELD is used as a parameter in a get/set command, these commands are used at compile time.


Get_Field_Value

Se Also: Set_Field_Value

Purpose

To retrieve the value of a field in the current record of any database file.

Syntax

Get_Field_Value {file-handle} {field-num} To {variable}

Argument Explanation

{file-handle} The number used to open the file.

iFieldNo The number of the field.

variable The variable that will hold the field value retrieved.

What It Does

Get_Field_Value moves a copy of the contents of a field into a program variable, variable, performing any type conversion necessary. The current record's value for the specified field will be retrieved.

The following example opens the "invt" file, reads a record and shows the value for each field. This code runs in the order workspace.

Example

Integer hFile // File handle to Invt.

Integer iFields // Number of fields.

Integer i // To index through fields.

String sName sValue // Buffers for name and value of field.

// Open file.

Open "Invt" As hFile

// Find first record in the file (by Recnum)

Vfind hFile 0 GT

Showln "Here is the data from record 1: "

// Get number of fields.

Get_Attribute DF_FILE_NUMBER_FIELDS Of hFile to iFields

// Loop through fields printing name and value.

For I From 0 To iFields

// Get name.

Get_Attribute DF_FIELD_NAME Of hFile I to sName

// Get value.

Get_Field_Value hFile I To sValue

Showln "Field: " sName ". Value: " sValue

Loop


Get_File_Mod_Time

See Also: Set_File_Mod_Time

Purpose

Returns the date and time of the last time a file was changed.

Syntax

Get_File_Mod_Time {file-name} To {date-var} [{hour-var} [{minute-var} [{second-var}]]]

What It Does

Get_File_Mod_Time returns the date and time of the last modification of a file. This command moves the date of the last modification into the first variable {date-var} after the keyword To. Optionally, the Get_File_Mod_Time command retrieves the time stamp into the variables that follow the field that obtains the last modification date.

Example

Here is an example that gets the date and time stamp of hello.txt:

Date dFileDate

Integer iFileHour iFileMinute iFileSecond

// Get the values.

Get_File_Mod_Time "Hello.Txt" to dFileDate iFileHour iFileMinute iFileSecond

Notes

  • If the file is not found, error 4358 "Rawfile Command Error" is reported.


Get_FileNumber

Purpose

Returns the file number for the file and field passed as argument at compile time.

Syntax

Get_FileNumber FileName.FieldName to integer_variable

What It Does

This command returns the file number for the file and field passed as argument at compile time. It is very important to note that this happens at compile time.

An equivalent statement to:

Get_FileNumber Customer.Name to iFile

is

Move Customer.File_Number to iFile.

Example

integer iField iFile hDD

string sValue

move Customer_DD to hDD

Get_FieldNumber Customer.Name to iField

Get_FileNumber Customer.Name to iFile

Get File_Field_Current_Value of hDD iFile iField to sValue

This example retrieves the file and field numbers of the Customer.Name database field and then retrieves the value of that field to the string variable sValue.

Notes

  • Whenever FILE_FIELD is used as a parameter in a get/set command, these commands are used at compile time.


Get_File_Path

Purpose

To return the path (among those listed in DFPATH) for a specified file.

Syntax

Get_File_Path {file-name} To {variable}

Argument Explanation

sFileName the name of the file for which the path is to be returned.

variable a String variable to contain the path to sFileName.

What It Does

The DFPATH value in the registry is a list of directories that the system searches to find files. The Get_File_Path command searches the directories in the DFPATH key and returns the full path (including the file name) for the first occurrence of the file sFileName.

Example

// Strings to hold paths.

String sPathHello sPathFileList sPathInvt

// Get the values.

Get_File_Path "Hello.Txt" To sPathHello

Get_File_Path "Filelist.Cfg" To sPathFileList

Get_File_Path "Invt.Dat" To sPathInvt

// Output report.

Showln "Hello.Txt was found at " sPathHello

Showln "Filelist.Cfg was found at " sPathFileList

Showln "Invt.Dat was found at " sPathInvt

Notes

  • If the file is not found, the return value is an empty string.


Get_Icon _Count

Purpose

To return the number of icons in an icon library.

Syntax

Get_Icon_Count {file-name} To {variable}

Argument Explanation

sFilename The name of an icon library file. This must be a full path to the file, including the directory and the file name.

variable A variable into which the number of icons is returned.

What It Does

Get_icon_count returns the number of icons in the icon library file whose name is in sFilename.

Example

Integer iIcons

String sFileName

Get_File_Path "Order.Ico" to sFileName

If (sFileName ne "") Begin

Get_Icon_Count sFileName To iIcons

Showln "There are " iIcons " icons in the file " sFileName

End

Else;

Showln "Cannot find Order.Ico in DFPath"

In this example, the number of icons in the file Order.Ico is reported. Note how Get_File_Path is used to find a complete path for Get_Icon_Count. Get_Icon_Count requires a fully qualified path name to the icon library file. The reason for this is that many icons reside in system files that are unlikely to be in the directories of the DFPATH registry value.


Get_Licensed_Max_Users

See Also: Get_Current_User_Count

Purpose

Returns the maximum number of concurrent users licensed for the current serial number (that use the same serial number as the program executing this code).

Syntax

get_Licensed_Max_Users to integer_variable

Example

integer iMaxUsers

get_Licensed_Max_Users to iMaxUsers

This example retrieves the maximum number of licensed concurrent users to the integer variable iMaxUsers.


Get_Resource_Name Command

See Also: Direct_Input, Set_Resource_Library, Include_Resource, Register_Resource, Total_Resources

Purpose

To retrieve the name of a resource in the current resource library.

Note

This command is a character-mode legacy command that handles embedding of files as resources. This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources.

Syntax

get_Resource_Name integer to resource_name

Argument Explanation

integer The number of a resource ID.

resource_name A string variable into which the name of the resource ID is returned.

What It Does

Get_resource_name allows you to determine the name of a resource ID. Resource IDs have integer values starting with one and continuing sequentially to the total number of resources in the current library.

integer i res_type

string res_name

for i from 1 to total_resources

get_resource_name i to res_name

get_resource_type to res_type

showln (pad(res_name, 30)) res_type

loop

This simple example lists all the resources in the current library of the program running, followed by the resource type of each.


Get_Resource_Type Command

See Also: Direct_Input, Set_Resource_Library, Include_Resource, Get_Resource_Name, Register_Resource, Total_Resources

Purpose

To determine the type of a resource in the current resource library.

Note

This command is a character-mode legacy command that handles embedding of files as resources. This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources.

Syntax

get_Resource_Type resource to resource_type

Argument Explanation

resource The name of a resource or an integer equal to a valid resource ID.

resource_type An integer variable into which the name of the resource type is returned.

What It Does

Get_resource_type allows you to determine the type of a resource specified when the resource was embedded into the program during compilation. The resource_type can be any integer value. Zero and all negative values are reserved for predefined resource types; you may use all positive values for user-defined resource types. The predefined resource types are:

DF_RESOURCE_TYPE_BINARY for resources in binary (undelimited) format.

DF_RESOURCE_TYPE_LINE for line-delimited resources.

DF_RESOURCE_TYPE_ERROR for invalid or unitialized resources.

Resources defined as images use DF_RESOURCE_TYPE_LINE.

Resources included with the include_resource command default to DF_RESOURCE_TYPE_BINARY, but this may be overridden with the type command option (see the include_resource command).

If a resource is registered, but never defined or included, it will have a resource type of DF_RESOURCE_TYPE_ERROR.

integer iResType

string sLine 80

include_resource letter.txt as letter type DF_RESOURCE_TYPE_LINE

direct_input "resource: letter"

get_resource_type letter to iResType

if (iResType = DF_RESOURCE_TYPE_LINE) begin

// process line-delimited file

readln sLine

showln sLine

end

else if (iResType = DF_RESOURCE_TYPE_BINARY) begin

// process binary file

read_block sLine 80

showln sLine

end

else if (iResType = DF_RESOURCE_TYPE_ERROR) begin

showln "Resource 'letter' has not been initialized"

end

This simple example declares a resource, letter, then prints he first line to the screen. The if...else block handles the resource depending on its type.


Get_Transaction_Retry

See Also: Set_Transaction_Retry

Purpose

To return the setting for the number of times to retry a transaction before signaling a deadlock.

Syntax

Get_Transaction_Retry To {variable}

Argument Explanation

variable An integer variable to hold the number of retries.

What It Does

Get_Transaction_Retry returns the number of automatic lock retries that will occur before a deadlock is signaled. A deadlock occurs when two or more tasks or users try to lock each other's records. You may set the retry count with the Set_Transaction_Retry command, thereby allowing more retries to occur, before causing a deadlock condition.

Example

Integer iTransactionRetry

Get_Transaction_Retry To iTransactionRetry

Showln "Number of times to retry transactions: " iTransactionRetry

Notes

  • The default value of the transaction retry count is 15.


Get_Windows_Directory

Purpose

To return the path of the directory in which Windows is installed.

Syntax

Get_Windows_Directory To {variable}

Argument Explanation

variable A String variable that after execution of this command will contain the path of the Windows directory.

What It Does

Get_Windows_Directory returns the entire path (starting with the logical drive identifier) to where Windows is installed. This is useful for finding Dynamic Link Libraries, initialization files, bitmaps, and other files, which are typically installed in or below the Windows directory.

Example

String sDir sBuffer sIniFileName

// Retrieve the directory where Windows is installed.

Get_Windows_Directory To sDir

Showln "Windows is installed in this path: " sDir


GetDskInfo

Purpose

To return the status of a specific drive.

Syntax

Getdskinfo {drive} {status}

Argument Explanation

iDrive The drive for which status is sought. 0 is the current drive. Drive A is 1, Drive B is 2, and so on.

iStatus A variable to receive the Integer value identifying the status of iDrive:

DRIVE_NOT_AVAILABLE

DRIVE_REMOVABLE

DRIVE_FIXED

DRIVE_REMOTE

What It Does

Getdskinfo returns the type of the logical disk drive named in the statement. iDrive is identified with integers starting with 0 for the current drive, 1 for the first drive (typically A:), and so on. DRIVE_NOT_AVAILABLE is returned when iDrive is a value greater than the number of drives defined. Diskette, tape, and other removable-media drives return DRIVE_REMOVABLE, local hard disks return DRIVE_FIXED, and network (bridged, etc.) drives return DRIVE_REMOTE when the user is connected, DRIVE_NOT_AVAILABLE when not.

Example

Integer iDiskType

GetDskInfo 3 iDiskType

If (iDiskType <> DRIVE_REMOVABLE);

Send Stop_Box "Not Removable Drive" "Exit Now"

Else;

Send Stop_Box "Removable Drive" "Exit Now"


Global_Variable command

See Also: Global Variables, Visual DataFlex built-in Global Variables

Purpose

Use the Global_Variable command to ensure a variable declaration is unambiguously defined as being global when so intended.

Syntax

Global_Variable {variable-name} [{maximum-length}]

where

  • {variable-name} is the name of the global string variable that is being declared

  • {maximum-length} is the maximum number of characters that the global string can contain; between 1-255. If {maximum-length} is omitted, the global String variable's length will be 80 characters.

What It Does

Variables declared outside procedures and functions are implicitly global, but using the global_variable command reduces ambiguity and declares the intent for a variable to be global; it reduces any chance of code misinterpretation.

You can also use the global_variable command to declare global variables inside functions and procedures, but this technique is strongly discouraged, as it creates code that is difficult to follow.

Example

global_variable gsCompanyName "ABC Corporation"

This example defines a global String variable named gsCompanyName and sets its initial value to "ABC Corporation".


Goto

Purpose

To move execution to a labeled address of the program.

Syntax

Goto {label}

What It Does

Goto transfers execution to a labelled command line. The following program shows how the Goto command can be used to exit a loop.

Example

String sValue sTest

Integer iCount

Move "hello world" To sValue

For iCount From 1 To (length(sValue))

Move (Mid(sValue, 1, iCount)) To sTest

// If the character 'w' is found, quit the loop.

If (sTest = 'w') Begin

Showln "found a 'w'"

Goto Label

End

Else; // show progress

Showln "Character number " iCount " is a [" sTest "]"

Loop

Label:

Showln "There is almost never a reason to use a Goto"

Notes

  • It is good programming style to use procedures and functions or break in preference to goto whenever possible. Since the break statement only exits from one level of a loop, a goto may be necessary for exiting a loop from within a deeply nested loop.

  • We do not recommend using the Goto command, because programs can become quite error-prone when it is used.


Handle

See Also: Declaring Variables, Variable Declaration Commands, Struct, Integer

Purpose

Declares one or more Handle variables.

Syntax

Handle {identifier} […{identifier}]

Where

  • Where {identifier} is a variable name for the new handle variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Handle

Handle{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Handle command declares handle variables. Handles are integers.

Visual DataFlex handle types are used to declare variables for storing references to some other identifier, such as an object.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Example

Handle hoButton

This example declares 1 handle variable named hoButton, which could be used to store the object handle for a button control.

Handle[] hoButtons

This example declares 1 dynamic array variable, named hoButtons, containing an undefined number of elements of type handle.

Handle[5] hoButtons

This example declares 1 static array variable, named hoButtons, containing 5 of elements of type handle.

Handle[][3] hoControls

This example creates a two-dimensional dynamic array variable named hoControls, containing an undefined number of elements of type handle. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • Use the Move command to initialize the value of a handle. For example;

handle hoButton

Move myButton to hoButton

  • Using global variables is discouraged. The maximum number of global integers you can declare is 32767, which are used for classes (1 global integer is used for each class) and global integers.

  • If you need to define a global Handle variable, you should use the global_variable command to do so.


If

See Also: Boolean Expressions, Compound Statements, Conditional Statements, Continuing a Statement on the next line, Execution Control Commands, Begin, Case, If Function

Purpose

Conditionally controls the execution of one or more statements of code.

Syntax

If {Boolean-expression} {true-statement}

[Else {false-statement} ]

What It Does

The If command evaluates the Boolean expression provided, and if the result is TRUE, the succeeding line of code executes. If the Boolean expression is FALSE, program control changes to the statement immediately after the true conditional code, and if that statement is an Else statement, the false conditional code that follows the Else command will execute.

You can use the Begin…End command to designate a block of code that will conditionally execute.

Example

Procedure Example

Boolean bFileExists

// File_Exist returns non-zero if the file in question exists.

File_Exist "hello.txt" bFileExists

// If the file exists, put up a message box that says it was found.

If (bFileExists);

Send Stop_Box "Hello.Txt was found" "Test!"

End_Procedure // Example

The next example shows how the Else clause is used when the Boolean expression is FALSE:

Example

Procedure Example

Boolean bFileExists

// File_Exist returns non-zero if the file in question exists.

File_Exist "hello.txt" bFileExists

// If the file exists, put up a message box that says it was found.

If (bFileExists);

Send Stop_Box "Hello.Txt was found" "Test!"

Else ; // The file does not exist. Tell the user we cannot find it.

Send Stop_Box "Hello.Txt was not found" "Test!"

End_Procedure // Example

Example

This example uses a Begin…End block for both the If and Else conditions:

Procedure Example

Boolean bFileExists

File_Exist "hello.txt" bFileExists

If (bFileExists) Begin

Send Stop_Box "Hello.Txt was found" "Test!"

// Erase Hello.Txt so that the next time it is not found.

EraseFile "hello.txt"

End

Else Begin

Send Stop_Box "Hello.Txt was not found." "Test!"

// Create Hello.Txt so that the next time it is found.

Direct_Output "hello.txt"

WriteLn "Hello World"

Close_Output

End

End_Procedure // Example

{Boolean-expression} can be any expression that evaluates to True or False.

Example

This example searches an array of structs of type tFriends for a friend's birthday and compares it to today's date. If today is any friend's birthday, it displays a message box stating "Happy Birthday " and the friend's name.

struct tFriends

string sName

string sPhoneNumber

date dBirthday

end_struct

Procedure Example

tFriends[] myFriends

date dToday

integer i iNumberOfFriends

sysdate dToday

// add some code here to initialize array myFriends

move (SizeOfArray(myFriends)) to iNumberOfFriends

for i from 0 to (iNumberOfFriends-1)

if (myFriends[i].dBirthday = dToday) ;

send Info_Box ("Happy Birthday " + myFriends[i].sName)

loop

End_Procedure // Example

Note: normally, you would use the SearchArray function to find an array element.

Notes

  • You may use Not to invert a conditional test:

Procedure Example

Boolean bFileExists

File_Exist "hello.txt" bFileExists

If (Not(bFileExists)) Begin

Send Stop_Box "Hello.Txt was not found." "Test!"

// Create Hello.Txt so that the next time it is found.

Direct_Output "hello.txt"

WriteLn "Hello World"

Close_Output

End

End_Procedure // Example

  • Else commands are paired with the preceding If command. Use indentation to make your code readable. Here is an example that prints one of four message boxes, depending on whether the file "hello.txt" exists, is empty, has one line, or has more than one line:

Procedure Example

Boolean bFileExists

String sBuffer

Direct_Input "hello.txt"

// If the file exists, SeqEof will be FALSE (0)

If (Not(SeqEof)) Begin

Readln sBuffer

// If SeqEof is set, the file is empty. Tell the user.

If (SeqEof) Send Stop_Box "Hello.Txt exists, but is empty" "Test!"

Else Begin // At least one line of text in the file.

Readln sBuffer

If (SeqEof); // At least two lines of text in the file.

Send Stop_Box "Found two lines of text in Hello.Txt"

Else ; // Just one line of text in the file.

Send Stop_Box "Found one line of text in Hello.Txt"

End

Close_Input

EraseFile "hello.txt"

End

Else Begin // If the file doesn't exist…

Send Stop_Box "Hello.Txt was not found." "Test!"

Direct_Output "hello.txt"

WriteLn "Hello World"

Close_Output

End

End_Procedure // Example

  • Notice that when you do not use a Begin…End construct, it is crucial to use a semi-colon continuation character ';' to execute the line after the If command. A semi-colon is not necessary if the command to conditionally execute is on the same line as the If command, such as in the test for an empty file above.

  • An Integer variable or expression with a value of zero (0) is equivalent of FALSE. An Integer or expression with a value other than zero is the equivalent of TRUE.


Import_Class_Protocol

See Also: Multiple-Inheritance, Class, Forward

Purpose

To import the definition(s) of a message or messages from a class that is not the superclass of the class being defined.

Syntax

Import_Class_Protocol {source-class} [{dest-class} [{message} | All]] ;

[Inherit] [No_Overwrite]

What It Does

This command identifies a class not in the ancestry of the receiving class, from which to import the definition(s) of either one identified messages, or all the messages defined in the source class.

Example

The following example shows how a subclass can derive some messages from its superclass and then mix in some messages from an imported class:

Class cActualSuperClass Is A Array

Procedure Proc_1

Showln "Inside Proc 1 of cActualSuperClass"

End_Procedure

Procedure Proc_2

Showln "Inside Proc 2 of cActualSuperClass"

End_Procedure

Procedure Proc_3

Showln "Inside Proc 3 of cActualSuperClass"

End_Procedure

End_Class

Class cMixin Is A Mixin

Procedure Proc_1

Showln "Inside Proc1 of cMixin"

End_Procedure

Procedure Proc_4

Showln "Inside Proc 4 of cMixin"

End_Procedure

End_Class

Class cSubClass Is A cActualSuperClass

Import_Class_Protocol cMixin

Procedure Proc_2 // Forwarding example.

Showln "Before forwarding. Inside Proc 2 of cSubClass"

Forward Send Proc_2

Showln "After forwarding. Inside Proc 2 of cSubClass"

End_Procedure

End_Class

Object oTest Is A cSubClass

End_Object

Showln "This program demonstrates import class protocol"

Send Proc_1 to oTest // executes in cMixin

Send Proc_2 to oTest // executes in cSubClass, forwards to cActualSuperClass

Send Proc_3 to oTest // executes in cActualSuperClass

Send Proc_4 to oTest // executes in cMixin

The class that is defined above will execute the code for Proc_1 of cSuperClass2 rather than the code in cSuperClass1, because cSubClass imports the implementation from cSuperClass2. The code defined in cSubClass for Proc_2 will forward to the definition in cSuperClass1, because no definition for Proc_2 exists in cSuperClass2. The implementation of Proc_3 in cSuperClass1 is the only implementation for Proc_3, so it will be inherited by cSubClass. The same is true for Proc_4 in cSuperClass2 – it will also be inherited by cSubClass.

You can use more than one Import_Class_Protocol in a class definition. When the same message is implemented in more than one imported class, the last imported definition is the one used. The following class inherits from one superclass, cSuperClass1, and then imports from two other classes: cSuperClass2 and cSuperClass3. The difference here is that the code for Proc_4 in cSuperClass3 will execute instead of the implementation in cSuperClass2, because cSuperClass3 is imported after cSuperClass2.

Class cActualSuperClass Is A Array

Procedure Proc_1

Showln "Inside Proc 1 of cActualSuperClass"

End_Procedure

Procedure Proc_2

Showln "Inside Proc 2 of cActualSuperClass"

End_Procedure

Procedure Proc_3

Showln "Inside Proc 3 of cActualSuperClass"

End_Procedure

End_Class

Class cMixin1 Is A Mixin

Procedure Proc_1

Showln "Inside Proc1 of cMixin1"

End_Procedure

Procedure Proc_4

Showln "Inside Proc 4 of cMixin1"

End_Procedure

End_Class

Class cMixin2 Is A Mixin

Procedure Proc_4

Showln "Inside Proc 4 of cMixin2"

End_Procedure

End_Class

Class cSubClass Is A cActualSuperClass

Import_Class_Protocol cMixin1

Import_Class_Protocol cMixin2

Procedure Proc_2 // Forwarding example.

Showln "Before forwarding. Inside Proc 2 of cSubClass"

Forward Send Proc_2

Showln "After forwarding. Inside Proc 2 of cSubClass"

End_Procedure

End_Class

Object oTest Is A cSubClass

End_Object

Showln "This program demonstrates import class protocol"

Send Proc_1 to oTest // Executes in cMixin1

Send Proc_2 to oTest // Executes in cSubClass, fwds to cActualSuperClass

Send Proc_3 to oTest // Executes in cActualSuperClass

Send Proc_4 to oTest // Executes in cMixin2

Base class behavior cannot be imported. Use inheritance for your primary class ancestry and then use the Import_Class_Protocol command to add new behaviors. It only makes sense to use Import_Class_Protocol when the methods the imported class defines are not specific to a single class. When there is no opportunity for reuse of the code, just implement the new methods in your subclass.

You may specify an Import_Class_Protocol command outside of a class definition, but then you must provide the target class name that receives the imported procedures and functions. For example, instead of specifying the Import_Class_Protocol commands in the previous example, you can omit them and add the following two lines after the definition of cSubClass:

Import_Class_Protocol cSuperClass2 cSubClass

Import_Class_Protocol cSuperClass3 cSubClass

The next example shows how a single message can be imported. The next example declares a mixin for a class, cMixin, that implements two messages; but only one of the messages (Proc_2) is imported:

Class cSuperClass Is A Array

Procedure Proc_1

Showln "Inside Proc 1 of cSuperClass"

End_Procedure

Procedure Proc_2

Showln "Inside Proc 2 of cSuperClass"

End_Procedure

End_Class

Class cMixin Is A Mixin

Procedure Proc_1

Showln "Inside Proc1 of cMixin"

End_Procedure

Procedure Proc_2

Showln "Inside Proc 2 of cMixin"

End_Procedure

End_Class

Class cSubClass Is A cSuperClass

Import_Class_Protocol cMixin cSubClass Proc_2

End_Class

Object oTest Is A cSubClass

End_Object

Showln "This program demonstrates import class protocol"

Send Proc_1 to oTest // cSuperClass code executes.

Send Proc_2 to oTest // cMixin code executes.

Note: you must also specify the target class name when you use the option to limit the Import_Class_Protocol to one message. The target class name also must be specified when you use the Inherit or No_Overwrite options. When the Inherit or No_Overwrite options import all the messages rather than just one message, use the keyword All, immediately after the name of the target class, Dest, of the Import_Class_Protocol command.

The Inherit keyword will cause the Import_Class_Protocol to import not only the implementations of messages in the mixin class, but also all its ancestors. The following example shows how the Inherit option can be used to import a class and its ancestors:

Class cMixinSuperClass Is A Mixin

Procedure Proc_1

Showln "Inside Proc 1 of cMixinSuperClass"

End_Procedure

Procedure Proc_2

Showln "Inside Proc 2 of cMixinSuperClass"

End_Procedure

End_Class

Class cActualSuperClass Is A Array

Procedure Proc_3

Showln "Inside Proc 3 of cActualSuperClass"

End_Procedure

End_Class

Class cMixin Is A cMixinSuperClass

Procedure Proc_1

Showln "Inside Proc1 of cMixin"

End_Procedure

Procedure Proc_4

Showln "Inside Proc 4 of cMixin"

End_Procedure

End_Class

Class cSubClass Is A cActualSuperClass

Import_Class_Protocol cMixin cSubClass All Inherit

End_Class

Object oTest Is A cSubClass

End_Object

Showln "This program demonstrates import class protocol"

Send Proc_1 to oTest

Send Proc_2 to oTest

Send Proc_3 to oTest

Send Proc_4 to oTest

The No_Overwrite keyword will cause the system to keep any definition of a message that already exists in the target class, dest, rather than overwrite it with another definition of the same name from the imported class. This option is useful when you want to merge two classes but not lose the implementations already defined in the target class. The default option is to overwrite the subclass with the imported implementation. To see this, you can change the preceding example by substituting the definition of cSubClass as shown below. The new subclass will execute Proc_4 as defined in the class cSubClass, rather than the implementation of cMixin.

Class cSubClass Is A cActualSuperClass

Procedure Proc_4

Showln "Inside Proc 4 of cSubClass"

End_Procedure

Import_Class_Protocol cMixin cSubClass All Inherit No_Overwrite

End_Class

Notes

  • Imported message definitions containing the forward command should not be used. If an imported message definition includes a forward procedure call, the ancestors of the dest class will receive the forward, not the ancestors of source. The ancestors of dest may contain either no such message, or a message of the specified name but definition differing from that required.


Include_Resource Command

See Also: Direct_Input, Get_Resource_Name, Register_Resource

Purpose

To embed the contents of a file in a compiled Visual DataFlex program as a resource.

Note

This command is a character-mode legacy command that handles embedding of files as resources. This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources.

Syntax

include_resource fileName as resourceName [type resourceType]

Argument Explanation

fileName The name of the file (optionally including a path) to embed in the compiled program

resourceName The name to associate with the embedded file.

resourceType A constant integer, or one of the predefined resource type symbols:

DF_RESOURCE_TYPE_BINARY

DF_RESOURCE_TYPE_LINE

What It Does

This command includes a file from disk for use as a resource via the sequential input device commands. The resource can be treated as a sequential file in all respects; i.e. the direct_input command is used to open a resource just like any other sequential file.

A resource ID is also defined for the resource based on the resourceName plus a suffix of .RSC: a resource named account_defaults, for example, would have a resource ID defined as account_defaults.rsc. This resource ID is a constant integer value that can be used at runtime to refer to a resource dynamically.

The direct_input and get_resource_type commands support the use of resource names directly in their syntax; any other reference to a resource must use the resource ID (or its integer value).

The type of a resource is defined during compilation and cannot be reset at runtime. Resources included with the include_resource command use a default type of DF_RESOURCE_TYPE_BINARY. This type may be overridden to be any of the predefined resource types, or any user-chosen constant integer value. (You may not use an Integer variable to specify the resource type; only constant Integer values can be assigned during compilation.) You may use the #REPLACE compiler directive to define symbolic replacements for your own resource types.

Zero and all negative integer values are reserved for the predefined resource types; you may use all positive integer values for your own resource types. (0 is reserved for DF_RESOURCE_TYPE_ERROR). The get_resource_type command is used to determine the type of a resource.

In cases where you need to refer to a resource in source code prior to the point where the resource is included, you can use the register_resource command to cause the resource name and resource ID to be defined.

string linestuff 80

include_resource letter.txt as letter type DF_RESOURCE_TYPE_LINE

direct_input "resource: letter"

readln linestuff

while [not seqeof]

showln linestuff

readln linestuff

end

This example includes the ASCII file letter.txt in the compiled program. The file is then referenced by its resource name, letter.

Notes

  • FileName is not used at runtime—only at compile time.

  • Images cannot be accessed with this command.


Increment

See Also: Decrement, Integer, Repeat, While

Purpose

To increase the value of an integer variable by one.

Syntax

Increment {variable}

Where {variable} is an integer variable.

What It Does

Increment adds one to the value of {variable}.

Increment is generally useful for maintaining ascending counters, especially those which control While ... Loop, Repeat ... Until, and similar structured loops.

Example

The example below displays ten lines of text to the screen, showing the value of iCounter each time the loop iterates.

Integer iCounter

Move 0 to iCounter

Repeat

Showln "The value of iCounter is " iCounter

Increment iCounter

Until (iCounter >= 10)


Integer

See Also: Declaring Variables, Variable Declaration Commands, Struct, Real, Integer Function

Purpose

Declares one or more Integer variables.

Syntax

To declare Integer variables

Integer {identifier} […{identifier}]

Where

  • Where {identifier} is a variable name for the new integer variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Integer

Integer{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Integer declares integer variables. Integers are whole numbers (no decimals) in the range -2147483648 to 2147483647.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

Integer iCounter

End_Procedure // Test

This example declares 1 integer variable named iCounter.

Integer i iCounter iCustomers

This example declares 3 integer variables named i, iCounter and iCustomers.

Integer[] iStudentIds

This example declares 1 dynamic array variable, named iStudentIds, containing an undefined number of elements of type integer.

Integer[5] iStudentIds

This example declares 1 static array variable, named iStudentIds, containing 5 of elements of type integer.

Integer[][3] iColors

This example creates a two-dimensional dynamic array variable named iColors, containing an undefined number of elements of type integer. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • You may do calculations with integers, but any decimal values that results will be truncated without report of error.

  • Use the Move command to initialize the value of an integer. For example;

Integer iCounter

Move 0 to iCounter

  • Using global variables is discouraged. The maximum number of global integers you can declare is 32767, which are used for classes (1 global integer is used for each class) and global integers.

  • If you need to define a global Integer variable, you should use the global_variable command to do so.


Is_File_Included

Purpose

To determine which files will be affected when the entry_update, entry_display, and entry_clear messages are sent during a data-dictionary operation. This command is rarely used by developers.

Syntax

Is_File_Included {file-number} {operation-type}

Where {file-number} is the file list number of the file to be affected; and {operation-type} determines what operation type you are testing: a clear (0) or a find/save operation (1).

What It Does

This command determines if the last data-dictionary operation caused a record in a file to be cleared or found. You pass the file number and the operation type. If the operation type is 0 and the file was cleared, the (Found) expression will return a True value. If the operation type is 1 and a record was found in the file, (Found) expression will return a True value.

This is command is internal and should only be used by developers who thoroughly understand how data-dictionary objects and data-entry objects interact. Examples of its usage can be found by reviewing the DataFlex packages.


Load_Def

See Also: Outputting DEF Files, Make_File, Structure_Copy

Purpose

Loads file-definition information from a sequential (.DEF) file into memory.

.DEF files are designed to work with the embedded database. We recommend using the native tools of the database you are working with to maintain table definitions.

Syntax

Load_Def {def-file} Onto {structure-handle}

Where {def-file} is the name of the sequential file to load; and {structure-handle} is a handle to an existing or new file structure.

What It Does

The Load_Def command loads a file definition from {def-file} into the file structure identified by {structure-handle}. The Load_Def command may only be used within a Structure_Start … Structure_End block. Load_Def may be used on restructure operations for both new and existing files.

No structure operations (other than Structure_Start) should be performed on {structure-handle} prior to executing Load_Def, because the Load_Def command overwrites most of the file definition. Any structural changes prior to executing Load_Def are lost.

The Load_Def command is similar to Structure_Copy. They both copy an existing file structure onto a new one. Load_Def uses a definition (.DEF) file as the source, while Structure_Copy uses an open database file as the source.

When you use Load_Def with (.DEF) files, you need to be aware of some special rules that allow you to easily create new file definitions:

  1. Fields are matched by number.

  2. To delete a field, remove the line from the .DEF file. All fields beneath the deleted field will be shifted up by one position. New field numbers will be assigned automatically.

  3. To add a field, place the field in the position you want it to have, and give it a number of zero (0). All fields beneath this field will be shifted down one position. New field numbers will be assigned automatically.

  4. To modify a field, change the requested data (name, type, etc.) for the field number you want to change. If you modify the type, the data will be converted appropriately.

Example

Integer iFileNumber

String sDataFilename

Integer bDefFileExists

// Check for Wines.Def

File_Exist "Wines.Def" bDefFileExists

If (bDefFileExists) Begin

// The name of the file will be Test1

Move "Test1" To sDataFilename

// Using a file handle of 0 with structure_start indicates

// that we are creating a new file.

Move 0 To iFileNumber

Structure_Start iFileNumber "DATAFLEX"

// Load the definition file of an existing file onto the file

// being created. Use the Wines file definition as a template.

Load_Def "Wines.Def" Onto iFileNumber

Set_Attribute DF_FILE_PHYSICAL_NAME Of iFileNumber To sDataFilename

Structure_End iFileNumber DF_STRUCTEND_OPT_NONE

// Now we create the filelist entry for our new file.

// This command gets the next available number in filelist.cfg

Get_attribute DF_FILE_NEXT_EMPTY To iFileNumber

// These commands set the file names associated with the

// filelist.cfg entry for the new file (Test1)

Set_attribute DF_FILE_LOGICAL_NAME Of iFileNumber To sDataFilename

Set_attribute DF_FILE_DISPLAY_NAME Of iFileNumber To sDataFilename

Set_attribute DF_FILE_ROOT_NAME Of iFileNumber To sDataFilename

Send Stop_Box "Success" "Exit Program."

End

This example creates a new file, Test1, using the definition file of an existing file, Wines. You may use the Wines.Def file in the Wines sample to try this program. A filelist entry is also created for the new file.

Notes

  • Load_def will not modify your file list.

  • Load_Def will not end the restructure operation—to complete the operation, you must execute a Structure_End command.

  • If {structure-handle} is a handle to an existing file, it will not change the directory name of the file.


Load_Driver

See Also: Unload_Driver

Purpose

Loads a database driver.

Syntax

Load_Driver {driver-name}

Where {driver-name} is the name of the database driver. The names of drivers available from Data Access Worldwide are:

  • DATAFLEX for the embedded database

  • DB2_DRV for the DB2 Connectivity Kit

  • DFBTRDRV for the Pervasive.SQL Connectivity Kit

  • MSSQLDRV for the Microsoft SQL Connectivity Kit

  • ODBC_DRV for the ODBC Connectivity Kit

If you are using drivers provided by other vendors, check the driver documentation for the driver name.

What It Does

Load_Driver loads a database driver into Visual DataFlex. Use the Load_Driver command to access database files that are stored in foreign databases.


Lock

Se Also: Transactions and DDOs, Begin_Transaction, Get_Current_Lockcount, Close, DF_File_Mode, Open, Reread, Save, SaveRecord, Unload_Driver, Unlock

Purpose

To prevent other users from making changes to a database while one user is saving a record.

Syntax

Lock

What It Does

Lock prevents any change (save or delete) from being made by any other user in a multi user system to any of a program's open database tables. It does not affect tables whose file-mode attribute has been set to either Alias or Read_Only. Use the Lock command before issuing any Save or Saverecord command. Lock does not interfere with other users' ability to read or process data—only changes to the database are prohibited.

Lock remains in force until an Unlock command is executed. Therefore, Lock commands must be followed immediately by the Save or Saverecord command(s), and these must be followed immediately by an Unlock command to prevent the database from being locked for any appreciable length of time.

Notes

  • Leave lock in force only for the few commands for which it is needed, in order to minimize the time that other users are prevented from updating the database. Used properly, locks are so fast that they seldom interfere noticeably with the activities of other users.

  • On most systems, all tables a program has opened will be locked. Tables are locked in order of their numbers in the filelist.

  • In most cases, the Reread command is used instead of Lock. Reread does a lock and updates all active record buffers from the disk.

  • Locks are cumulative. You must issue an Unlock command for every Lock or Reread that executes. To determine how many locks are currently in effect use the Get_Current_Lockcount command.

  • Tables whose filemode is set to Alias or Read_Only are not affected by lock.


Login

See Also: Logout

Purpose

To log into a database server.

Syntax

Login {server-name} {user-name} {password} [{driver-name}]

Argument Explanation

serverName Name of the server to be logged into.

userName Name of the user for the login.

password Password to use for the login.

driverName Optional database driver to use for the login. If not used, a login will be attempted for all drivers.

What It Does

This command is for use in database-server architectures to allow the user to log into a named server. If the combination of serverName, userName and password is correct, a connection will be established for the server. If the combination is incorrect, an error will be generated. An application can trap these errors and allow additional login attempts.

If serverName is null, an attempt will be made to log into the server specified in the DFDEFAULTSERVER environment variable (if it is set). If one or more of these logins is successful, no error is generated.

If userName is null, the value specified in the DFDEFAULTUSER environment variable will be used. If DFDEFAULTUSER is not set, GUEST is substituted.

If password is null, the login will only succeed if you have no password set for the server(s) specified.

Example

Login "DSN=accounts" "johndoe" "jane" "ODBC_DRV"

This command will log into an ODBC database with a DSN named accounts, user id "johndoe" and password "jane".

In addition, the .INT file for each table that will be accessed via DSN accounts needs to have the following entries:

DRIVER_NAME ODBC_DRV

SERVER_NAME DSN=accounts

For example, this command can be used in Procedure OnCreate of a cApplication object for an application:

Procedure OnCreate

Send DoOpenWorkspace CURRENT$WORKSPACE

Login "DSN=accounts" "johndoe" "jane" "ODBC_DRV"

End_Procedure

The hardcoded user id and password can also be requested from the user via a login dialog and used with the login as variables.

Depending on the database you are using, security will be somewhat different. In most cases, if security for the database is activated, if the login information you are passing to the database via the login command is incorrect, the database will popup a login dialog to request a user id and password. If the login fails, you have to ensure in your code that your application does not open and allow access to the database even though the login failed.

Here is an example of how you can intercept a failed login:

// this is procedure OnClick of a button in a login dialog

// the login dialog has 2 Form objects that accept a user id and password

Procedure OnClick

String sUserId sPW

Handle hoErrorObj

Get Value Of oUserId To sUserId

Get Value Of oPassword To sPW

// change the global error object to the current object

// this allows interception of errors from Login command via Procedure Error_Report below

Move Error_Object_Id To hoErrorObj

Move Self To Error_Object_Id

Login "DSN=pkb" sUserId sPW "ODBC_DRV"

// change the global error object back to what it was before we intercepted it

Move hoErrorObj To Error_Object_Id

// error 12293 is "Login unsuccessful"

If (LastErr=12293) Begin

Send Stop_Box "Login Unsuccessful" "Error"

Send Close_Panel // close password dialog

Send Exit_Application Of Main // close application

End

End_Procedure // OnClick

// this method is here simply to intercept any error that may occur while logging in

// it does not have to do anything with the error, but it suppresses the normal error display

Procedure Error_Report Integer iErrNum Integer iErrLine String sErrMsg

End_Procedure // Error_Report


Logout

See Also: Login

Purpose

To log out from a database server.

Syntax

logout [{driver-name} [{server-name}]]

Argument Explanation

driverName Optional database driver to use for the logout. If not used, a logout will be attempted for all drivers.

serverName Optional name of the server to be logged out of.

What It Does

This command is for use in database-server architectures, whether DataFlex or other.

It logs the user out of the current server (if any).

Notes

  • When a program terminates, a logout command is implicitly executed.


Loop

See Also: Boolean Expressions, Execution Control Commands, Case, For, Repeat, Until, While, Break, Boolean

Purpose

Terminates a repeating block of code initiated with For, Repeat, or While.

Syntax

For

Loop

or

Repeat

Loop

or

While

Loop

What It Does

When loop is executed, execution goes back up to the For, Repeat or While command which began the loop.

Notes

  • If a loop command is provided with no preceding For, Repeat, or While command, the compiler will report an error. Conversely, For and While commands require a terminating loop command.

  • Loop is an unconditional terminator. Use Until as a conditional block terminator.


Make_Directory

See Also: File_Exist, Get_Directory, Make_Temp_File, Remove_Directory, Set_Directory, Valid_Drive

Purpose

To create a new disk directory.

Syntax

Make_Directory {directory-path}

What It Does

Make_directory creates a new directory, as specified in the {directory} argument.

Example

Make_directory "h:\accounting\data"

In this example, a new directory, data, will be created below the existing directory accounting on the H: drive.

Make_directory sAccounts

In this example, a new directory will be created as specified in the value of the variable sAccounts.

Notes

  • If, for any reason, directory cannot be created, an error is reported.

  • Make_Directory can only create a directory one level deep at a time. You cannot create a subdirectory in a non-existant directory. It does not validate the whole path and fill in the missing directories.


Make_File

See Also: Open, Set_Attribute, Structure_Start, Zerofile

Purpose

To create a new, empty database file, or to modify the structure of an existing one.

.DEF files are designed to work with the embedded database. We recommend using the native tools of the database you are working with to maintain table definitions.

Syntax

Make_File {def-root-name} [{path} [{file-number}]] [{driver-name}

Argument Explanation

Def_root_name The root name (without the .DEF extension, but with drive designator and subdirectory path if necessary) of an ASCII source definition file produced by Database Builder.

Path An optional path or drive designator which specifies where the new file is to be created. It must end in the operating system delimiter (e.g., \).

File_number An optional integer which specifies the file number to be used in FILELIST.CFG for the new file (if different from that contained in the .DEF file). This option may be used only if a path is specified.

Driver_name An optional database-driver name. If you wish the created file to be in the format of another database driver, you can specify it through this parameter.

What It Does

Make_file allows a running DataFlex program to read a file definition from an ASCII source definition file created through the Database Builder and create a new, empty database file having the same specifications, or modify an existing file to match the specifications in the .DEF.

Options of make_file permit use of a definition source file on another drive and subdirectory, and permit specification of a different file-list number from that contained in the source definition file.

Example

make_file "vanilla" "\dataflex\mydata\" 99

This reads a database file definition from File VANILLA.DEF in the current directory, and creates a database file in Directory \dataflex\mydata, assigned to File 99.

Notes

  • If you wish to specify file_number but do not wish to specify path, you may give a pair of quotation marks ("") to hold the place of path.

  • The new database file created will have the root name specified in def_root_name.def, which need not match def_root_name itself. Files for indexes, field names, and data will be created as required by driver_name, all with the same root name.

  • If you use the path argument, the .FD file will be created in the current directory; all other files will be created in the directory specified in path.

  • File_number is the number in the file list you are assigning to the new file. It may be any value within the supported range. If you don't specify a number, DataFlex will use the file number in def_root_name.

  • If def_root_name is not found, DataFlex Error 60 (Bad or missing .DEF file) will be reported. If the new database file can't be created, DataFlex Error 72 (File not open) will be reported.

  • In applications which may be run in various operating systems, literal def_root_names and paths should be avoided in favor of variable def_root_names and paths. This is because the syntax of directories and filenames varies from environment to environment, and variable def_root_names and paths can be specified in a separate installation program specifically for the target environment.

  • If path does not end in the delimiter of your operating system for directory and filenames ("\" in DOS), DataFlex Error 75 (Can't open data .DAT file) will be triggered.

  • When make_file is used on an existing file, it will convert the file to match the .DEF, doing any restructuring necessary.

    Caution    : Modifying an existing file through this method is an advanced activity; there are few or no safeguards. For example, if you try to use make_file twice on the same file, the results are unpredictable.

  • Note that any modifications you can do through make_file can also be done in a structure_start/_end block, by setting the field and index attributes (using the set_attribute command).

  • Make_file cannot work on def_root_name files produced under drivers other than DataFlex. With the driver_name argument, however, it will produce files for use by such other driver.


Make_Temp_File

See Also: File_Exist, Get_Directory, Make_Directory, Remove_Directory, Set_Directory, Valid_Drive

Purpose

To create a new, empty file.

Syntax

Make_Temp_File {temp-extension} {file-name}

{file-name} May not be a constant or an expression.

What It Does

Make_temp_file creates a file in the current directory with a unique name, using the specified tempExtension, and returns the unique name that was generated.

Example

Make_Temp_File "tmp" Tfilename

In this example, a file is created with the extension tmp and places the generated rootname in the value of String Variable Tfilename.

Notes

  • If, for any reason, the file cannot be created on the current directory, an error will be reported.

  • Despite the command name, the file that is created is not actually "temporary," i.e., the file will not automatically self-delete at the completion of your program's execution. If you do not wish the file to remain, your program must delete it.


Move

See Also: Understanding File Buffers and DDO Field Buffers, Add, Decrement, Increment, Subtract

Purpose

To assign a value to a variable.

Syntax

Move {expression} to {variable}

What It Does

Move allows you to copy data from any constant, field, window, or variable into any other field, window, or variable. The arguments may be of different types and/or classes. All necessary conversions will be done automatically, except where a value is "impossible" for the variable type. Examples of "impossible" values are 12/31 for a Date, or A1587 for a Number. No combination of characters is impossible for a String type variable.

Where data is impossible for the type of variable, Visual DataFlex will declare an Error 51 "Bad format of expression (operand)", or other error explicitly naming the incompatibility and continue with execution. "Impossible" values for Numbers and Dates result in a value of zero in variable.

Where data is too long for the declared length of variable, the moved data is simply truncated on the right, and execution continues without error. Where this condition is an undesired possibility, it should be trapped with appropriate commands. On the other hand, this function represents a valid and often convenient way of accomplishing truncation where it is desired.

Example

Number nNum

String sString

Move "California" To sString

In this example, the String constant "California" is moved to string variable sString. If that variable were other than a string type variable, this command would report an error at runtime, because the value California cannot be a number.

Example

String sActive

Move Vendor.Name To sActive

In this example, the value of Field name in Database table vendor is moved to string variable sActive.

Example

Move 07/12/1999 To Sales.Order_date

In this example, the literal date 07/12/86 is moved to Field order_date in database table sales. If Field order_date were not of Type Date, this command would trigger an error.

Example

Move (Sales.Ord_date + 30) To Sales.Due_date

In this example, the value of Field due_date in Database table sales, plus 30, is moved to Field due_date in the same table.

Example

Initializing struct variable members:

In the example below, move is used to initialize members of the myBillingAddress struct variable.

struct tUSAddress

string sFirstName

string sLastName

string sAddressLine1

string sAddressLine2

string sCity

string sState

integer iZipCode

end_struct

Procedure CreateBillingAddress

tUSAddress myBillingAddress

// initialize myBillingAddress

move "John" to myBillingAddress.sFirstName

move "Smith" to myBillingAddress.sLastName

move "Data Access Worldwide" to myBillingAddress.sAddressLine1

move "14000 SW 119 Ave" to myBillingAddress.sAddressLine2

move "Miami" to myBillingAddress.sCity

move "FL" to myBillingAddress.sState

move "33186" to myBillingAddress.iZipCode

End_Procedure // CreateBillingAddress

Example

Copying struct variable members:

Assume that the example below is a continuation of the sample above, using the same struct declaration for tUSAddress. Here, move is used to copy the value of myBillingAddress to myShippingAddress. Using move to copy struct variables uses a deep memberwise copy operation to copy each struct variable member value from the first struct variable to the second struct variable.

Procedure CreateShippingAddress tUSAddress myBillingAddress

tUSAddress myShippingAddress

move myBillingAddress to myShippingAddress

End_Procedure // CreateShippingAddress

Example

Initializing array variable members:

In the example below, move is used to initialize members of the iValues array variable. You can also use FillArray to initialize array values.

Procedure Example

integer[10] iValues

integer i

for i from 0 to 9

move [i+1] to iValues[i]

loop

End_Procedure // Example

Example

Initializing array variable members:

In the example below, move is used to initialize members of the myFriends array variable, which is a dynamic array of tFriends structs.

struct tFriends

string sName

string sPhoneNumber

end_struct

Procedure Example

tFriends[] myFriends

move "John" to myFriends[0].sName

move "305-238-0012" to myFriends[0].sPhoneNumber

move "Susie" to myFriends[1].sName

move "305-555-1212" to myFriends[1].sPhoneNumber

End_Procedure // Example

Example

Copying array variable members:

The example below move is used to copy the value of array variable sValues1 to sValues2. Using move to copy array variables uses a deep memberwise copy operation to copy each array variable member value from the first array variable to the second array variable. To copy a range of array elements to another array, rather than the whole array, use CopyArray.

Procedure Example

string[5] sValues1 sValues2

// some code to initialize sValues1

move sValues1 to sValues2

End_Procedure // Example

You can use the Move command to move an object access name to handle variable. The following example moves the object ID of object oMyObject to a handle variable:

Move oMyObject To hoMyObject

The command actually move the result of an object access expression to the handle variable. At runtime, the following samples are identical.

Move oMyObject To hoMyObject

Move (oMyObject(Self)) to hoMyObject

This value of the object is determined at runtime and uses the standard Visual DataFlex object access evaluation process. This non-expression move syntax is supported to make it easier to read and write programs.

If you will be using an object name many times in the same program it is more efficient to move the object name to a handle variable and use the handle variable.

Procedue ShowAll

Handle hoMyList

String sValue

Integer iCount i

Move oMyList to hoMyList // this access method is only evaluated once!

Get Item_Count of hoMyList to iCount

For i from 0 to (iCount-1)

Get Value of hoMyList i to sValue

Send ProcessValue sValue

Loop

End_Procedure // ShowAll


Number

See Also: Declaring Variables, Variable Declaration Commands, Struct, Number Function

Purpose

Declares one or more Number variables.

Syntax

To declare Number variables

Number {identifier} […{identifier}]

Where

  • Where {identifier} is a variable name for the new number variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Number

Number{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Number defines in memory variables which are to contain numeric type data. Numeric variables allow for 14 digits to the left of the decimal point and eight to the right of the decimal point.

A Number can have any value in the range of ±99,999,999,999,999.99999999.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure CalculateTotal

Number nQuantity nTot nSum nAmount

…

End_Procedure

In this example, four variables of type Number variables are declared:. nQuantity, nTot, nSum, and nAmount.

Number[] nCreditBalances

This example declares 1 dynamic array variable, named nCreditBalances, containing an undefined number of elements of type number.

Number[5] nCreditBalances

This example declares 1 static array variable, named nCreditBalances, containing 5 of elements of type number.

Number[][3] nCreditBalances

This example creates a two-dimensional dynamic array variable named nCreditBalances, containing an undefined number of elements of type number. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • When a calculation exceeds the precision capacity of Type Number (eighth digit to the right of the decimal point), the rightmost digit is not rounded. The digits to its right are simply truncated.

  • If you need to define a global Number variable, you should use the global_variable command to do so.


Object

See Also: Object Declaration, Class, End_Object, Naming Conventions

Purpose

To create an object instance of a class.

Syntax

Object {object-name} is a {object-class}

…

End_Object

Where {object_name} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Each object used by a running program must be created either by the object. Object definition blocks are terminated with the end_object command. Each object is identified by a user supplied name (object-name).

Example

Object oCustomer_Number is a dbForm

Entry_Item Customer.Customer_number

Set Label to "Customer Number:"

Set Size to 13 42

Set Location to 5 72

Set peAnchors to anTopLeft

Set Label_Col_Offset to 2

Set Label_Justification_Mode to jMode_Right

End_Object // oCustomer_Number

Example

Object oOK_bn is a Button

Set Label to "&Ok"

Set Location to 116 228

Set peAnchors to anBottomRight

Procedure OnClick

Send OK To oSelList

End_Procedure

End_Object // oOK_bn

When on_key, function, procedure, and other object or create_menu blocks are included within an object definition block, the resultant components are local to Object object-name. An object defined in a block that is itself nested in another object definition block is said to be the "child" of the surrounding object, and the parent property of the child object acquires the value of the id of the surrounding (parent) object. Item definition (item_list) blocks must be within object definition blocks.

Throughout an object definition block (except for the interiors of the object definition blocks of child objects), the value of Integer Self is the id of Object object-name. This applies at runtime for procedures and functions within object-name's object definition block.

A child object acquires accelerator key assignments from its parent object through delegation, except where any of these components is overridden by a new definition within the child. Objects can send messages to their child objects by use of the broadcast command.

The names of all children of a given parent must be unique, but this rule does not extend beyond one generation. For example, if there is an Object Joe that is a child of the desktop, no other child of the desktop may be named Joe, regardless of its class. If another child of the desktop, Lee, has a child named Sue, however, that is no reason why Joe may not also have a child named Sue (Sue of Lee is distinguishable from Sue of Joe). Further, Joe may have a child named Joe (Joe of Joe can be distinguished from Joe), and so on. Within a class creation block, this rule does not apply. No object created within a given class creation block may have a name matched by another object created in the same block.

Object-class must be the name of one of the Visual DataFlex-supplied or user-defined object classes. The remainder of the object definition command line is actually class dependent.

Objects inherit messages, procedures, functions, properties, and creation syntax from their class.


Offset_Of_Field

See Also: Field, Put_String, Type

Purpose

To get the position of a field in a complex data structure as a number of bytes from the beginning of the structure.

Syntax

Offset_Of_Field {field} To {variable}

Argument Explanation

field The name of the field whose offset is to be returned.

variable The name of a variable to contain the returned value.

What It Does

Offset_of_field places the number of bytes between the beginning of field and the beginning of the complex data structure that contains it into the variable named at the end of the statement.


On_item Command

See Also: Item_list Command, Send Command

Purpose

To define an item for objects descended from the Menu Class.

Syntax

on_item [value] [send message [to object] |begin_pull_down;

pull_down_name [pull_down_image]]

What It Does

On_item commands define the items of objects whose base class is menu. This includes objects of Class list, form, entry, and subclasses of those classes. Every on_item command must be contained within an item definition block begun with an item_list command.

Each item created with on_item can be given an initial value, a string, which is displayed in the visible portion of the item (window). Value may be longer than the window, but it will be truncated on display to the length of the window. If value is omitted, blanks are displayed. The value passed to the item may be a constant, variable or function. The value of the item will be set to the evaluated argument.

Each item may send a message when the user interacts with the item. The message to be sent is specified using the send keyword followed by the name of the message. By default, message is set to none and it is sent to the current_object.

You may specify a different receiver of the message with the to keyword. If the to keyword is used, the object_id of object is placed in the aux_value property of the item.

Within object definition blocks started with the create_menu command, begin_pull_down may be used to define a child object of Class pull_down_menu whose name is specified in pull_down_name. Begin_pull_down begins a nested item definition block within which the items of the menu may be specified with additional on_item commands. These nested item definition blocks must be terminated with an end_pull_down command. Where desired, nested on_item commands may themselves use begin_pull_down to create deeper levels of nesting.


On_Key

See Also: Procedure KeyAction, Accelerator Key Assignments, Class, Object

Purpose

To assign a message to be sent upon the pressing of a key assigned to an accelerator key function, or of a particular key on the keyboard.

Syntax

On_Key {key-name} Send {message}

What It Does

With on_key, you can assign a message (message) to be sent upon the pressing of a particular key. Message may be a predefined message or user-defined. A key to which a message has been assigned with on_key is called an accelerator key.

KeyName may be the name of a physical key on a keyboard or one of the 50 function names mapped to physical keys. The physical references always point to one actual key on the keyboard, while function references can be remapped to different physical keys.

Example

On_Key KCancel send AskIfUserWantsToCancel

Example

On_Key Key_Alt+Key_T send DoTest

The 50 logical key functions of Visual DataFlex bear "generic" names that describe processes that are common throughout applications generally. As such, they can be used in different objects to perform processes that, although not identical, still bear a functional resemblance to each other. Khelp, kuparrow, kcancel, and ksave_record are examples of logical key names. Logical key functions are used extensively in on_key commands in the object classes supplied with Visual DataFlex, and provide a good example of this process of "functional analogy." Otherwise, it is up to you to maintain consistency of usage across objects, object classes, programs, and applications.

Message may not have arguments. Only messages that function without arguments may be called from the on_key message parameter. Message is sent to the focus object.

Accelerator keys are typically defined either within the object creation block or the construct_object procedure of a class. When the on_key command is used outside of all object definition blocks and classes, the key is assigned to the desktop. As with all messages, the keys of the desktop are inherited by all objects. These keys become global throughout the application.

Key definitions of on_key commands are inherited by the descendants of an object. If a key is defined in an object, all of the object's descendents will also have the same key definition. If the key is redefined in one of the descendents, then the definition in the ancestor is overridden, and the descendent (and all of its decendants) will use the new definition of the key. If the private keyword is used, then the inheritance is not performed. The key will operate only if the object where the key is defined is the focus object.

The class (as opposed to ancestral) definition of a key may be restored for an object with an on_key command whose message is default_key. This will cause the key to be sent to the focus as a key_keyname message, as if there were no key definition for the key in the focus object or any of its ancestors. This is the same function as private, except in the opposite direction. Just as private is used in a parent object relative to its descendents, so default_key is used in a descendent relative to its ancestor. Where all descendents of an object are to be affected, private should be used in the parent. Where, on the other hand, only a minority of descendents are to revert to a class key, default_key should be used.

Objects act on messages received through an on_key command irrespectively of whether the sending key is defined in the receiving object or one of its ancestors. If the on_key message is process_key, however, the message defined for the key locally or in an ancestor is received, just as if the key had been typed from the keyboard.

There is no limit to the number of keys that an object may define.


Open

See Also: Close, Declare_Datafile, Relate

Purpose

To open a table using the specified table name or table number.

Syntax

Open [{rootName} As] {table-name} [Mode {table-mode}] [{index}]

table-mode is the mode to open the table in: either DF_SHARE or DF_EXCLUSIVE. If omitted, DF_SHARE is used (the table is opened non-exclusively).

What It Does

Open opens table, including all associated index files and makes its fields and records available for processing by the program.

Open opens the table set identified in the filelist for table unless you use the as option. Open as allows you to specify the full path (with no extension) of the table set to open, regardless of what is contained in the filelist. This path may contain a driver name (e.g., odbc_drv:person would open the table person in an ODBC data source). If the as option is used, and table contains 0, the table's number (from the FILELIST.CFG) will be retrieved, and placed into table.

If you are using a database other than the embedded database, consult the documentation for the Connectivity Kit you are using for more information about opening tables in the database you are using.

Example

Integer hTable

Move 0 to hTable

Open "employee" as hTable

In this example, if employee is Number 7 in the filelist, then hTable will contain 7. If employee is not in your current filelist, you will get an error (see the note later in this article to open a table that is not in your filelist).

This method can be employed when you would like to use a string variable to open a table, and you need to know its table number. Commands which take a table number as a parameter (e.g., get_attribute) can then be called for this table.

Index at the end of the command causes the index of that number to be buffered in memory. This is of use if your program produces a report of record data from table in the order of an index.

Open customer

This command opens the customer table.

Open vendor 3

This example opens database table vendor and buffers part of its third index in memory, thereby making sequential access to its records faster.

Open "account\delinqs" as vendor

This example opens table set delinqs.* in Directory \account. The table is referred to throughout the program as vendor, even though that is not its Directory Rootname in the filelist.

The as option is useful when you would like to choose a physical table set to process at runtime. In this case, the value of rootName may be input at runtime through a variable before as.

To do this, table should be in your filelist, and its fields must have the same names, and be of the same types (String, Number, Date, or Text) and in the same order, as they are in rootName.

Another use for the as option is for opening a table with a generic table definition. For example, you have three vendor tables: vendor1, vendor2 and vendor3. If they all have the same physical structure (field names, types and lengths), then you could have one .FD file for all three: vendor.fd.

open "vendor1" as vendor

This example looks for the file vendor.fd, and if it is found, opens vendor1 using the table definition in vendor.fd.

open Customer Mode DF_EXCLUSIVE

This example opens the customer data table in exclusive mode.

Notes

  • Index buffering increases the speed of processing only when access to records is sequential by the specified index, as in a report. When access is random, as in data entry to non-sequential records, index buffering won't increase speed. It only consumes memory unnecessarily. Note that this behavior is specific to the DataFlex Driver—other drivers may behave differently.

  • When the as option is not used, the Directory Rootname used is that specified in FILELIST.CFG for table, unless that name specifies no path, and a value is in force for the DFPATH System Variable. In such a case, the physical table set is located by the pathname given in DFPATH. Directory Rootnames in FILELIST.CFG of DataFlex database tables can be set using the DF_FILE_ROOT_NAME attribute, or in the Administration Tool.

  • In applications which may run on various operating systems, literal rootnames should be avoided in favor of variable rootnames. This is because the syntax of directories and tablenames varies from environment to environment, and variable rootnames can be specified in a separate installation program specifically for the target environment.

  • The Predefined Indicator found is set true (and finderr set false) if an open command was successful. Found is set false (and finderr set true) if an open command was not successful.

  • With the as option, it is possible to open a table that is not in your FILELIST.CFG, but doing so is not advised because relates to, and attaches from, table will not work. On the other hand, security reasons might incline you to keep table out of FILELIST.CFG.

  • When compiling a program using a table not in FILELIST.CFG, the tablenumber used may be any number that does not conflict with the number of another table used in the same program.

open "test" as 11

This example opens test, regardless of whether it is in your filelist, and regardless of whether or not test.fd exists.

  • When a table is opened whose table definition specifies that its Maximum Records is one (1), the table buffer is automatically filled with the data of the first record (by record number) of table. Such tables (with Maximum Records of 1) are referred to as "system tables," and customarily do not support record finding and have no indexes.

  • If table is taken from a database field, you should pass it through the trim function before opening it with the open as command. If you don't use trim, the string containing the field name will include a trailing space, which confuses the command. For example, if the tablename field of the monument table contains the names of tables, you could open one of them with the following statement:

Open (Trim(monument.tablename)) as rushmore

  • This command should not be used within a transaction; it will cause an error. A transaction starts with a begin_transaction or lock command and ends with end_transaction or unlock.

  • Whenever a program attempts to open a data table in exclusive mode, there is the possibility that another program already has the same data table open. If a program attempts to open a table exclusively and cannot obtain exclusive access, error 4177 will be triggered.


Output

See Also: BasicReport class, Append_Output, Direct_Output, Print, Output_Wrap, Set_Channel_Position

Purpose

To write an image to a sequential file, device, or text field. This command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Syntax

Output [Channel {channel-num}] [{page-name}]

What It Does

Output transfers data, prompts and formatting to the device named in the direct_output or append_output command in force.

Data in windows is usually the purpose of outputting an image. All data desired to be present in the output must be in the windows of pagename before the output command is executed.

Empty windows in pagename will be output as underscores unless they are blankformed before the output command.

When append_output is in force, the point in a file at which writing is done can be changed by use of the set_channel_position command. Outputting before the end of a file overwrites existing data. There is no insert mode for sequential output.

It is unnecessary ever to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program.

Example

Direct_Output "LST:"

Output invoice

This example outputs Image invoice to the printer.

Notes

  • If pagename is omitted, the current image will be output. If channel channelNum is omitted, the channel will be that specified in the last append_output, direct_output, output, write, or writeln command in which channel was specified or implied. If no output destination has been specified for the channel used, output sends output to the printer.


Output_Aux_File

See Also: Direct_Output, Make_File

Purpose

Outputs an auxiliary file (.FD or .DEF).

.DEF files are designed to work with the embedded database. We recommend using the native tools of the database you are working with to maintain table definitions.

Syntax

Output_Aux_File {type} For {file-num} [Number {aux-file-num}] [To {path-name}]

Argument Explanation

type The type of file to create: DF_AUX_FILE_FD or DF_AUX_FILE_DEF.

FileNum File number for an existing file, or a handle to a new structure.

AuxFileNum The number that will be used in the .FD or .DEF to represent a new file.

pathname The pathname for the auxiliary file. This can be a file or any destination valid for sequential output (e.g., LST: for printer).

What It Does

This function will create an FD or DEF file for fileNum. If fileNum is a handle to a file being created, auxFileNum will specify the file-list number that the file has or will have; otherwise, it is ignored.

Example

Open 11

Output_Aux_File DF_AUX_FILE_DEF For 11 To "c:\temp\emp.def"

This example creates a .DEF file, called emp.def, for File 11, and places it in the C:\TEMP directory.

Notes

  • See the direct_output Command for a description of valid destinations for sequential output.

  • FileNum must be open before executing this command.


Output_Wrap

See Also: BasicReport class, Append_Output, Direct_Output, Output, Print_Wrap

Purpose

To output an image repeatedly as necessary to output the contents of database fields or sequential text files through windows addressed by the print_wrap command. This command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Syntax

Output_Wrap [Channel {channel-num}] [{page-name}]

What It Does

Output_Wrap outputs the static and dynamic content of pagename to the device named in the direct_output or append_output command in force, outputting pagename repeatedly until all data in the input file or device for every window in pagename that was addressed with a print_wrap command has been output.

Example

Direct_Output "report.txt"

Output_Wrap liaisons

In this example, Image liaisons is output to Sequential File REPORT.TXT.

For output_wrap to accomplish its intended purpose, at least one window in pagename must have a Text-type database field or an input sequential file or device assigned to it with a print_wrap command. Print_wrap and output_wrap require each other in order to work. Where no such window is present, a more efficient command to use is output.

/confessionimg

_________________ _________ ______________________________

/*

Open inmate

Find ge inmate.name

Print inmate.name To confessionimg.1

Print inmate.number To confessionimg.2

Print_Wrap inmate.confession To confessionimg.3

Output_Wrap confessionimg

in this example, the first two fields, addressed by print, are non-wrapping and the third, intended to contain multi-line output, is addressed by print_wrap. After output of the name, number and first line of Field confession, additional portions of confession would be output in repetitions of confessionimg until the contents of the field had been output in their entirety. The first two fields would be blank in any such repeated outputs, as would any other print_wrap window whose input data had been exhausted.

Data in windows is the usual purpose of output_wrapping an image. All data desired to be present in the output must be printed, print_wrapped, or otherwise moved to the windows of pagename before the output_wrap is executed.

Empty windows in pagename will be output the first time as underscores unless they are blankformed before the output_wrap command.

When append_output is in force, the point in a file at which writing is done can be changed by use of the set_channel_position command. Output_wrapping before the end of a file overwrites existing data. There is no insert mode for sequential output.

Notes

  • If pagename is omitted, the current image will be output. If channel channelNum is omitted, the channel will be that specified in the last append_output, direct_output, output, write, or writeln command in which channel was specified or implied. If no output destination has been specified for the channel used, output_wrap sends output to the printer.

  • Output_wrap can output images containing no windows addressed by print_wrap, but the process is slower than it is when the output command is used.


Playwave

Purpose

This command is used to play a Windows sound (.WAV) file from within a DataFlex application. In addition to using this command, you must also have a sound driver for your computer, in order to play one of these files.

Syntax

PlayWave {wav-file} {player-option}

Argument Explanation

WavFile The name of the sound file to play, and

PlayerOption This parameter tells Windows how the file should be played. The full list of values for this parameter are as follows:

SND_SYNC play synchronous

SND_ASYNC play asynchronous

SND_NODEFAULT play with no defaults

SND_LOOP play in a loop

SND_NOSTOP play non-stop

Notes

  • In order to make this command available, your program must use wave.pkg.


Pointer

See Also: Declaring Variables, Variable Declaration Commands, Struct, AddressOf Function, Address Command

Purpose

Declares one or more Pointer variables.

Syntax

To declare Pointer variables

Pointer {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Pointer variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Pointer

Pointer{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Visual DataFlex Pointer types are used to declare variables for storing the memory address of a string variable.

You can assign a value to a pointer variable with the AddressOf function. This command will retrieve the memory address of a named variable and return it to the pointer variable. The Pointer data type has a valid range of -2147483648 to 2147483647.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

Pointer lpComputerName

End_Procedure // Test

This example declares a Pointer variable named lpComputerName.

Pointer[] lpDiskDriveInfo

This example declares 1 dynamic array variable, named lpDiskDriveInfo, containing an undefined pointer of elements of type pointer.

Pointer[5] lpDiskDriveInfo

This example declares 1 static array variable, named lpDiskDriveInfo, containing 5 of elements of type pointer.

Pointer[][3] lpDiskDriveInfo

This example creates a two-dimensional dynamic array variable named lpDiskDriveInfo, containing an undefined pointer of elements of type pointer. Conceptually, this represents a rectangular array with an undefined pointer of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • The Pointer type is primarily designed to be used when making DLL calls to the Windows API. It is used to store the address of Structure variables.

  • If you need to define a global Pointer variable, you should use the global_variable command to do so.


Print

See Also: BasicReport class, Output, Print_Wrap, Subtotal

Purpose

To move data to an image window and to update its subtotal accumulator. This command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Syntax

Print {variable} [To {window}] {[format option …, option]}

Window may be omitted where an autopage command is in effect.

What It Does

Print moves variable to window and formats the data according to any format option(s) which are on the command line or a format command addressing window.

print pay.amount

In this example, the value of Field amount in Database File pay is printed to the next autopaged window in the program

print employee.fica {signrt}

In this example, the value of Field fica in Database File employee is printed to the next autopaged window with a minus sign at the right for negative numbers. You may use the option with or without a window designation, as shown above.

If window is of type Numeric, Integer, or Real, a subtotal accumulator for window will be maintained internally. You may access the value of any subtotal accumulator by appending a percent sign (%) to the name of window. So long as you do not move or calc to the accumulator, this does not zero or otherwise affect the value of the accumulator.

move body.8% to cume

In this example, the subtotal accumulator for the eighth window in Image body is moved to Variable cume.

If a subtotal command anywhere in the program addresses window, the subtotal accumulator for window will be zeroed.

The following are the print format options:

capslock

fill=

float$

signrt

suppress

Certain output formats may be specified by embedding certain characters among the underscores making up a window:

__,__.__Comma will embed the thousands' separator in long numbers

__C_____C will uppercase all lowercase letters

__0_____Zero will replace blank spaces with zeroes

__Z_____Z will blankform windows that have a value of zero

__@_____At will remove leading or trailing spaces

__$__.__$ will "float" the currency character(s) on left

__*__.__Asterisk will replace blank spaces with asterisks

These options apply only to the print command, not to the move command.

Notes

  • Print is the only command that updates subtotal accumulators.

  • You may apply format options to windows by placing them directly on print command lines or by using the format command.

  • DataFlex also uses window-formatting characters directly in data windows in screen images. Except for the C(apslock) letter, they only apply to output using the print command.

  • Print only moves data to a window. Actual output of the window data and surrounding image to the printer or other output device is done by the output_pagecheck command.


Print_Wrap

See Also: BasicReport class, Output_Wrap, Print

Purpose

To move to an image window, text data that may be longer than the window, for output through repeated outputs of the image containing the window. This command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Syntax

Print_Wrap {field} | {source} [To {window}]

Argument Explanation

Window Must be a window in a Visual DataFlex image. It may be omitted where an autopage command is in effect.

Source Must be a single constant or string variable.

What It Does

Print_wrap moves the contents of a sequential file or Text-type database field to a window for outputting through successive repetitions of the image. When an image containing one or more fields addressed in print_wrap commands is output using the output_wrap command, the field(s) is filled with as much material as it can hold, and the image is output. This process is repeated until all fields addressed with print_wrap have reached the end of the sequential file or Text field to which they are assigned.

When a report is running and output repetitions trigger a pagebreak, page headers and subheaders, if used, are output in the normal manner. The output of subtotals, if used, is likewise unaffected by the use of wrapping fields.

Multiple print_wrap fields can be used to output the contents of different sequential files and fields in columns.

Where multi-line output is desired from the image for each record, use of a separate image containing no print_wrap windows is required. Such an image may precede the image containing print_wrap windows, follow it, or both. Where the report class is used, subheader and subtotal facilities may be adapted to such purposes.

Notes

  • If output (instead of output_wrap) is used to output an image containing a field addressed with print_wrap, the field(s) addressed with print_wrap will be blank in the output.

  • If the image containing one or more fields addressed with print_wrap is more than one line high, the output of any one such field will be separated from the previous output by the number of lines the image is high, less one, normally an undesirable effect. Therefore, images containing wrapped fields should be only one line in height.

  • Fields addressed by the print command may be freely intermingled with fields addressed by the print_wrap command.

  • Print_wrap breaks lines on spaces, tabs, and end of line characters. Where no such character can be found in the portion of the input field or file to be output, the break in output occurs wherever the end of the field falls.

  • Windows addressed by print_wrap may not be of type Date or Number. Format options other than capslock are unlikely to yield desirable results on such windows.

  • It is not necessary to use direct_input to open sequential text files for print_wrap. This is accomplished by print_wrap itself, which should be considered functionally equivalent to direct_input.


Procedure

See Also: Variable Parameter Lists, End_Procedure, Function, Procedure_Return

Purpose

To define a procedure.

Syntax

Procedure [Set] {message} [Overloaded] [ {type} [ByRef] {param}… ]

…

End_Procedure

Or

Procedure [Set] {message} [Overloaded] For {class} [ {type} [ByRef] {param}… ]

…

End_Procedure

Or

Procedure {name} GLOBAL [ {type} [ByRef] {param}… ]

…

End_Procedure

Or, Legacy Syntax

Procedure [Set] {message} [For {class} ] [{type} {param}… ] Returns {type}

…

End_Procedure

Argument Explanation

{type} The data type of each parameter.

{param} The local variable name assigned for purposes of processing inside the procedure to parameter values passed on invocation.

What It Does

User defined actions can be defined with procedures. A procedure can be defined within an object (or its class) or it can be defined globally. The code that performs the action must be placed between the procedure command and a matching end_procedure command. Procedures may be defined anywhere in the program relative to the point(s) from which they are called.

The code may utilize the value of each parameter declared on the procedure command line. Each type parameter pair declares a local variable, so names may be used without concern for conflicts with any other local variables in other procedures. Any number of type parameter pairs may be used.

The action specified in procedure may be initiated from other parts of the program by sending a message of form send name value ... value, where each value ordinally corresponds to an parameter in the procedure command line.

Example

Procedure DebitAcct Number nAmount Date dCheckdate Integer bShowIt

Number nBalance

GET pnBalance To nBalance

Move (nBalance - nAmount) To nBalance

Set pnBalance To nBalance

If bShowIt ;

Send WriteDebit nBalance dCheckData iCheckNumber

End_Procedure

This procedure could be called as follows:

Send DebitAcct nTotal dToday 0

Or

Send DebitAcct of hSomeObject nTotal dToday 0

If you are augmenting a procedure (adding a procedure to a sub-class or object where the procedure is already defined in the super-class) you have the choice of forwarding the procedure message or cancelling it. If the previous example, was an augmented message, it was cancelled because the message was not forwarded. Below is an example of a forwarded message:

Procedure DebitAcct Number nAmount Date dCheckdate Integer bShowIt

If (nAmount<0) ; // if amount is less than zero always

Move 1 to bShowit // show the value.

Forward Send DebitAcct nAmount dCheckDate bShowIt

End_Procedure

The total number of parameters passed to a procedure is contained in the variable Num_Arguments. This variable can be used to check that the proper number of parameters have been passed to a procedure. Omitted parameters may cause incorrect assignment of values to the procedure's parameters. If an parameter for which no value at all was passed is accessed, the error is issued.

If the procedure set option is used, the invoking command should be of form set message {of object} to arg. A procedure of this form is usually create to simulate a property. Often a Procedure Set and Function will be created using the same name allowing the developer to access the methods as a "get/set" pair.

The End_Procedure command defines the end of the procedure-definition block.

Global Procedures

Global procedures may be defined by adding the keyword GLOBAL after the procedure name.

Procedure DoTask GLOBAL string sTaskName

:

End_Procedure

Send DoTask "StartLog"

Global procedures may be called from anywhere within an application. Since global procedures are defined outside of any object so they cannot be augmented.

By Reference Parameters

The special ByRef keyword can be used to specify a parameter that is passed by reference instead of by value. When a parameter is passed by reference the code that calls the procedure must pass the address of a variable of the correct type as the parameter. By reference parameters allow the procedure to directly modify the value of the variable passed to it. For example…

Procedure AddOne Integer ByRef iValue

Move (iValue + 1) to iValue

End_Procedure // AddOne

Procedure Example

Integer iCount

for iCount from 1 to 10

Send AddOne (&iCount)

loop

End_Procedure // Example

For more information refer to Parameter Passing.

Procedure Overloading

Overloaded Procedures may be defined by adding the keyword Overloaded after the procedure name. For more information refer to Method Overloading in the Language Guide.

Notes

  • Each of the values passed to the procedure on invocation may be of any type, but their values must be convertible to the named type when used in the procedure. Type mismatches will not be detected at compile time, but will cause failures at run time.

  • User defined procedures may be called from within user defined procedures, down to a maximum of 18 levels, but a procedure may not be defined within the definition of another procedure.

  • Unlike functions, procedures should not return values. Where a value is needed to be returned to the caller, a function should be used instead.

  • Some legacy procedures return values. You should no longer create procedures that return values.

  • Global Procedures may not be overloaded.

  • A Procedure Set should not take more than one parameter, it was designed for use with properties.


Procedure_Return

See Also: End_Procedure, Function_Return, Procedure

Purpose

To return execution from a procedure.

Some existing Visual DataFlex procedures return values. This technique is now discouraged. You should not create any new procedures that return values (use functions for this purpose).

Syntax

Procedure_Return

or, legacy syntax

Procedure_Return [ {return-value} ]

What It Does

The procedure_return command is used to terminate a procedure. This command is optional and is only needed if you wish to return from a procedure before the End_Procedure command is encountered.

Example

Procedure RunLoop integer iCounter

Integer iCount

String sName

For iCount from 1 to iCounter

Get TheName to sName

// if we run out of names…end the procedure

If (sName="") Procedure_Return

Send ShowTheName sName

Loop

// if the loop is completed, end_procedure will terminate the procedure call.

End_procedure

Notes

  • There may be as many Procedure_Return commands as necessary in the body of the procedure.

  • Some procedures return values. If a procedure returns a value the return value is passed as a parameter of this command. Return_value can be a constant, variable or an expression.


Property

See Also: Properties, Struct Properties, Array Properties, Class, Get, Object, Set

Purpose

To create properties in class and object definitions.

Syntax

Property {type} {name} {initial-value}

or, legacy syntax

Property {type} {name} public|private {initial-value}

Argument Explanation

type Must be a Visual DataFlex data type.

initialValue May be of any type.

What It Does

You may define properties of classes and objects with the property command. Each property must have a defined data type, which may be string, number, date, integer, or real.

Each property must have an initialValue that is assigned whenever an object of the class is created. The values of properties may be changed with the set command, and queried with the get command.

When created in an object, a property's definition must be placed directly within the object and not within a procedure or function.

Object MyEdit is a cDbTextEdit

Property Integer piMyVal 0

:

End_Object

When created in a class, a property's definition must be placed within a function or procedure, usually Construct_Object.

Class cMyEdit is a cDbTextEdit

Procedure Construct_Object

Forward Send Construct_Object

Property Integer piMyVal 0

:

End_Procedure

:

End_Object

Each property's value may be accessed by either the get command or through the use of an expression. The name of the message is the name of the property.

Object oMyEdit is an cMyEdit

Set piMyVal to 10

Procedure AddOne

Integer iVal

Get piMyVal to iVal

Increment iVal

Set piMyVal to iVal

// the expression syntax to access this property is:

// Move (piMyVal(self)) to iVal

End_Procedure

:

End_Object

// the property is accessed outside of the object as follows

Procedure DoIt

Integer iVal

Get piMyVal of oMyEdit to iVal

Increment iVal

Set piMyVal of oMyEdit to iVal

// the expression syntax to access this property is:

// Move (piMyVal(oMyEdit)) to iVal

End_Procedure

Data types are maintained by the property. If a set is done from, or a get done to, a different data type, then automatic type conversion is performed.

There is no limit to the number of properties that an object or class may have. Properties are inherited, so an object that handles a complex process may have many data properties to manage itself.

Properties may also be delegated to. A child of an object may access the properties of its parent without specifically addressing the parent as the destination of the messages.

Struct Properties

Special consideration needs to be given for accessing data that is stored in class properties that are of struct type. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire struct. This works just like a struct variable assignment.

To read or write individual members of a struct property, it is necessary to get the property to a local struct variable of the same type. You would then manipulate the data of this local struct and write back the changes by setting the struct property once again.

Example…

struct tNameAndAddress

string sName

string sAddress

end_struct

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare a struct property

Property tNameAndAddress pContact

End_Procedure

Procedure StoreName String sName

tNameAndAddress contact // create a local struct variable

// get the struct property to the variable.

Get pContact to contact

// show the current name.

Send Info_Box ("The current name is: " + contact.sName)

// change the name.

Move sName to contact.sName

// Save the change back to the struct property.

Set pContact to contact

End_Procedure

End_Class

Array Properties

Special consideration needs to be given for accessing data that is stored in array properties. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire array. This works just like an array variable assignment.

To read or write individual array property elements, it is necessary to get the property to a local array variable of the same type. You would then manipulate the data of this local array and write back the changes by setting the array property once again.

Example…

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare an array property

Property string[] psNames

End_Procedure

Procedure StoreName String sNewName

string[] sNames // create a local array variable

integer iElementCount

// get the array property to the variable.

Get psNames to sNames

// Add the new name.

Move (SizeOfArray(sNames)) to iElementCount

Move sNewName to sNames[iElementCount]

// Save the change back to the array property.

Set psNames to sNames

End_Procedure

End_Class

Legacy Public|Private Property Option

By default, properties are public and may addressed by their name. A property can be defined as private by adding the keyword private after its name. This is a technique that is no longer encouraged, but is one you may see in existing DataFlex applications.

Class cMyEdit is an Edit

Procedure Construct_Object

Forward Send Construct_Object

Property Integer piMyVal Private 0

:

End_Procedure

Procedure DoThis

Integer iMyVal

// you must add the class name to access a private property

Get cMyEdit.piMyVal to iMyVal

End_procedure

:

End_Object

If the property is private, it may be accessed by the object's class name followed by a period and the property name. Normally a private property should only be accessed within the class that defined it.


Read

See Also: File I/O Commands, Direct_Input, Read_Block, Readln, Set_Channel_Position, Seqeof, Seqeol, Write, Channel command component, Sequential File I/O

Purpose

To read "words" of data from a sequential file, device, or text field and move them to one or more variables.

Syntax

Read [Channel {channel-num}] {variable} […{variable}]

The first variable is required, and may be of any type except Indicator, and may be any true class except a constant. Additional variables may be on the command line, separated by spaces, without limit.

If channel {channel-num} is omitted, the channel will be that specified in the last direct_input, read, read_block, or readln command in which channel was specified or implied.

What It Does

The Read command reads data from the input file or device named in the last previous direct_input command. The first read command in the program reads data from the first line of the input file or device until it finds a comma or end of line character. Then it moves the data to variable. If the end character was a comma and there is another variable, data will be read into the next variable until the next comma or end of line.

Example

For the following examples, assume the file INFILE.TXT has two lines, as follows:

One, Dos , "Trois", "Vier ", 'Cinque'

Six, Siete , "Huit", "Neun ", 'Dieci'

String s1 s2 s3 s4 s5 s6

Number n1 n2 n3 n4 n5 n6

Direct_Input "infile.txt"

Read s1 s2

The read command would read One into String Variable s1, and Dos (followed by two spaces), into Variable s2. The leading space before Dos would be discarded.

When the last variable has been read into, execution proceeds to the next command, even if unread data remains on the current line. If an end of line is encountered before the variables are exhausted, the remaining variables are made blank if they are of type String or zero if they are of type Date or Number, and execution proceeds to the next command.

Successive read commands pick up where the previous read command left off, until an end of line character is encountered. To read past an end of line character in a data file, you must use a readln command. When an end of line character is encountered, Predefined Indicator seqeol is set true. When an end of file character is encountered, Predefined Indicator seqeof is set true.

Assume the read command in the program above were followed by this command:

Read s3 s4 s5 s6

This command would read Trois into s3, Vier (followed by a space), into s4, and Cinqu into s5. The embedding characters (" and ') would be discarded. s6 would be blank, even if it had data in it previously, because an end of line character comes after Cinque. Any further read commands would read nothing until a readln command was executed.

The point in a file at which reading is done can also be changed by use of the set_channel_position command.

Read uses commas to divide sequential data into variables, and it discards leading spaces and tabs unless they are embedded in quotation marks. It ignores commas embedded between single or double quotation marks as field separators and instead treats them as part of the data. The comma is referred to as the "delimiter" character since it separates the variables on the input line. The quotation marks are referred as "embedding" characters. Embedding characters and delimiters are discarded from read data.

It is unnecessary ever to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program.

Read checks read data for the types of the destination variables, and truncates any items which exceed the declared length of String variables. Different types of variables may be intermixed in the same read command.

Assume the first read command above were replaced by a command which referred to the Numbers declared in the program:

Read n1 n2 n3

This command would generate three Visual DataFlex errors, since the data does not qualify for Type Number.

Notes

  • To delimit data which itself contains quotation marks, use single quotation marks, or apostrophes, (') to delimit the item. Use double quotation marks (") to embed single quotation marks.

'The Hungry "i"', "Johnny's Bar"

  • The quotation marks around "i" will be passed as data, not treated as embedding characters, since they are themselves embedded in single quotation marks ('). The apostrophe (') in Johnny's, will not be treated as an embedding character because it is enclosed in double quotation marks. Embedding characters may be intermixed in the same file and line in this manner.

  • To read data that uses a differenct data separator than a comma, a decimal point for example, set the DF_DECIMAL_SEPARATOR attribute to the alternate character, and reset it back to the original value when completed.

  • Unwanted items in a source file may be discarded by reading them to a "discard" variable, which must be established before the read command.

string sKeep1 sKeep2 sDiscard

read sDiscard sDiscard sDiscard sKeep1 sDiscard sKeep2

  • This command would move the first three data items to String Variable sDiscard, the fourth to Variable sKeep1, the fifth to sDiscard, and the sixth to sKeep2.

  • For data files which contain end of line characters, the readln command is required to discard the end of line characters and enable read commands to read beyond the first line. For such files, always follow read or a series of reads with a readln.

Repeat

Read sVariable

Send ProcessVariable sVariable

If (Seqeol) Readln

Until (Seqeof)

  • In this example, the read sVariable and processing statements are executed continuously until Predefined Indicator seqeof is true. When the end of a line is read, Predefined Indicator seqeol is set true, and the readln command is executed, discarding the end of line character and enabling the read loop to continue executing.

  • To create a data file from a database for transportation to another environment, use the direct_output, write, and writeln commands.

  • Read and readln cannot be used on global strings longer than 255 characters unbroken by delimiters (comma, and/or end of line characters). Such strings must be dealt with by the read_block Command or with local strings.


Read_Block

See Also: File I/O Commands, Direct_Input, Read, Readln, Set_Channel_Position, Seqeof, Seqeol, Write, Channel command component, Sequential File I/O, get_Argument_Size, set_Argument_Size

Purpose

To read a block of data of a specified size from a sequential file, device, or text field and move it to a variable.

Syntax

Read_Block [Channel {channel-num}] {variable} {length}

The value of length must be in the range from 1 to 255 for global variables and 64 KB for local variables (unless the local length is changed with the set_argument_size command as described below). Length is required, if omitted, it defaults to zero.

It is unnecessary to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program. If channel channelNum is omitted, the channel will be that specified in the last direct_input, read, read_block, or readln command in which channel was specified or implied.

What It Does

Read_block reads length characters into variable from the file or device named in the last previous direct_input command. Read_block makes no distinctions among characters in the file (delimiters, embedders, spaces, tabs, discards), except the end of file character, which it uses to set Predefined Indicator seqeof true.

Read_block is intended for use with non delimited data files. Files delimited with commas and/or end of line characters can be read in with the read and readln commands. Undelimited files may be text files, those produced by other data management programs, or data downloaded from main frames and mini computers.

You must set length and the pattern of read_block commands according to your prior knowledge of the structure of the data in the input file, since it cannot be inferred from delimiting characters. The maximum length is governed by the maximum number of characters that can be in variable.

Example

Read_Block sMainInfo 70

This reads a block of 70 characters into the variable called sMainInfo.

Notes

  • The point in a file at which reading is done can also be changed by use of the Set_Channel_Position command.

  • Read_block ignores all delimiters—commas, quotation marks, carriage returns (CR), line feeds (LF), —except end of file markers. It processes all characters the same. Specific characters can be detected and acted upon in files by direct programming.

String sFragment sEolval

Move (Character(10)) to sEolval

Repeat

Read_Block sFragment 80

Until (pos(sEolval,sFragment)>0)

  • In this example, a repeat loop causes successive blocks of 80 characters to be read into String Variable fragment. The if command tests the values of fragment for the presence of the end of line character (ASCII 10). If the end of line character is not present, the loop is repeated.

  • When reading into text or binary fields of database files through local String variables, a length greater than the default local variable length may be used. Before a length larger than this default value may be used, the set_argument_size command must be used to expand the amount of RAM available for processing the command argument.


Read_Hex

See Also: File I/O Commands, Direct_Input, Read, Readln, Read_Block, Write_Hex , Sequential File I/O

Purpose

To read binary data as two-byte hexadecimal numbers.

Syntax

Read_Hex [Channel {channel-num}] {variable} [{length}]

Argument Explanation

channel_num A value being, or containing, the input channel to use (0 ~ 9). This only needs to be used when input is coming from multiple sources.

variable The name of a variable to hold the data read.

length The number of hex values to read. If not used, all data in hex format will be read.

What It Does

Read_hex reads length hexadecimal characters into variable from the file or device named in the last direct_input command. Read_hex can be used in conjunction with write_hex to convert data between binary and text formats.

It will read the number of bytes specified (by the length parameter) or until non-hex data (which includes the end of line) is encountered. The byte encountered is not read and will remain on the input stream. Specifying 0 as the length reads until non-hex data is encountered.

This command works similarly to the Read_Block command. You can use Read_Hex when reading text formatted as hexadecimal digits, and Read_Block for normal text.

Example

String sTextData

Direct_Input "TestHex"

Read_Hex sTextData 13

Showln sTextData

In the example above, assume the file TESTHEX contains the following characters:

48656C6C6F2C20776F726C6421

Then the following would be displayed:

Hello, world!

Notes

  • If the optional length parameter is not used, the command will read as much data as it can; all data that is in hexadecimal format will be read.


Readln

See Also: File I/O Commands, Direct_Input, Readln, Read_Block, Set_Channel_Position, Seqeof, Seqeol, Write, Channel command component, Sequential File I/O

Purpose

To read a line of data from a sequential file, device, text field, or image, and move its "words" to one or more variables.

Syntax

Readln [Channel {channel-num}] {variable} […{variable}]

Variable is optional, may be of any type. Additional variables may be on the command line, separated by spaces, without limit.

If channel channelNum is omitted, the channel will be that specified in the last direct_input, read, read_block, or readln command in which channel was specified or implied.

What It Does

Readln reads data from the input file or device named in the last previous direct_input command. The first readln command in the program reads data from the first line of the input file or device until it finds an end of line character. Then it moves the data to variable. If there is more than one variable, readln will perform an internal read command on the portion of the read in data which precedes the first unembedded comma (,) in the data and move it to the first variable, and the remainder into the next, and so on until there are no more commas in the remaining data, or the variables are exhausted.

Readln sets Predefined Indicator seqeol false every time it is executed, and Predefined Indicator seqeof true when the end of the file is reached.

Example

For the following examples, assume File INFILE.TXT has two lines, as follows:

One, "Dos" , "Trois"

Four, "Cinco", "Six"

String sP1 sP2 sP3 sP4

Number n1 n2 n3

Direct_Input "infile.txt"

Readln sP1 sP2 sP3

The readln command would read One into String Variable sP1, Dos into Variable sP2, and "Troi into Variable sP3. The spaces around Dos would be discarded, since readln executed a read command on it, but the quotation mark which began the third value ("Trois") would not be stripped, because readln itself does not strip embedding or delimiting characters.

Readln reads all of the remainder of the input line into its last variable, regardless of delimiting characters which might be in that remainder, and it strips only the end of line character from the data, not delimiters or embedders. When the last variable has been read into, execution proceeds to the next command. See read command for a complete discussion of delimiting, embedding, and discard characters.

If a tab character (ASCII 9) is processed through the last variable of a readln command, it will be replaced with the number of spaces required to pad the string to a length which is a multiple of 8 (the standard tab function). Thus, if the input line were A, the command readln var would produce output of 8 spaces followed by an A. If the input line were B A, the output would be B followed by 7 spaces followed by an A. This replacement does not occur for variables preceding the last one, since they are processed by readln's internal read command.

If an end-of-line is encountered before the variables are exhausted, the remaining variables are made blank if they are of type String or zero if they are of type Date or Number, and execution proceeds to the next command. When the number of variables exceeds the number of delimited items on the line in this manner, delimiters and embedders are stripped from the contents of all variables, because they were all read in with readln's internal read command. The first variable after the last delimited item discards the end-of-line character in the input data. A dummy variable may be provided for this purpose.

If the Readln command above, for example, had been:

Readln sP1 sP2 sP3 sP4

String Variable sP1 would contain One, sP2 would contain Dos, sP3 would contain Trois, and sP4, having discarded the end of line character, would be blank.

Successive readln commands pick up where the previous readln command left off, that is, on the next line of data.

It is unnecessary ever to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program.

Readln checks read data for the types of the destination variables, and truncates any items which exceed the declared length of String variables. Different types of variables may be intermixed in the same readln command.

Assume the first readln command above were replaced by a command which referred to the numbers declared in the program:

Readln n1 n2 n3

This command would generate three DataFlex errors, since the data does not qualify for Type Number.

Notes

  • The point in a file at which reading is done can also be changed by use of the Set_Channel_Position command.

  • The contents of a text file may be displayed to the screen, provided the input lines are not too long to display on the screen.

String sLine

Repeat

Readln sLine

Showln sLine

Until (Seqeof)

  • This example will show an entire file to the screen.

  • If there is no data on the input line a blank or zero will be returned in variable, as appropriate.

  • Because readln executes internal read commands whenever it is executed with more than one argument, the command:

Readln s1 s2 s3

  • is exactly the same as the commands:

Read s1 s2

Readln s3

  • To create a data file from a DataFlex database for transportation to another environment, use the direct_output, write, and writeln commands.

  • Read and readln cannot be used on global strings longer than 255 characters unbroken by delimiters (comma, and/or end-of-line characters). Such strings must be dealt with by the read_block Command or with local string variables.

  • When the dir driver is used with a direct_input command to read the operating system directory, readln should be used to bring one line (file) of the directory into the program.


Real

See Also: Declaring Variables, Variable Declaration Commands, Struct, Integer, Number, Real Function

Purpose

Declares one or more floating-point numeric variables.

Syntax

To declare real variables

Real {identifier} […{identifier}]

Where

  • Where {identifier} is the name of a new Real variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Real

Real{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

Real defines in-memory variables which are to contain numeric type data in floating-point format. Real variables allow for 16 significant digits and an order of magnitude of ±306.

A Real variable can have any value in the range of ±9.99999999999999999 times 10 to the ±306th power.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTheMath

Real rAsymptote rGradient rAbscissa

End_Procedure

In this example, three Real variables, rAsymptote, rGradient, and rAbscissa, are declared.

Real[] rBattingAverages

This example declares 1 dynamic array variable, named rBattingAverages, containing an undefined number of elements of type real.

Real[5] rBattingAverages

This example declares 1 static array variable, named rBattingAverages, containing 5 of elements of type real.

Real[][3] rBattingAverages

This example creates a two-dimensional dynamic array variable named rBattingAverages, containing an undefined number of elements of type real. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • When a calculation exceeds the capacity of Real variables, error 59 is triggered.

  • The show and showln commands display values of absolute ten million or more, and one ten-millionth and less in scientific notation. For example, ten million is displayed as 1e+007. One ten-millionth is displayed as 1e 007.

  • The Real type is not supported in the database. If a Real variable is moved to a Number database element, its value is converted to the format of the Number data type. If the value of such a variable exceeds the range of Number, a value-range error is triggered. Data entry in Real format can be supported by addressing a Real variable through the entry_item command.

  • If you need to define a global Real variable, you should use the global_variable command to do so.


Register_Function

See Also: Function, Get, Register_Procedure

Purpose

To allow a function or a property to be referred to in expressions in parts of the program that precede the point at which the function is defined.

Syntax

Register_Function {message} [{type} {param} … …] Returns {type}

What It Does

Before any function can be referred to in an expression, the compiler must know the name and the number and types of parameters of the function. If you need to refer to a function in an expression before the point at which the function is defined, the register_function command allows you to predefine the function in order to do so.

{message} is the name of the function that is forward referenced. Since the point of register_function is to predefine functions, this command should never be used after the point at which the function actually is defined.

The data {type} should be given before the name of each parameter passed to the function. Acceptable data types are integer, number, date, real and string.

The name of the {param} may be anything that describes the use the value in the function. The name may not be a reserved word, and must follow the typical symbol rules.

Every function must be defined as returning a value. The type given after the returns keyword identifies the data type of the function. This is probably the most important piece of information to the system. With this data type, all uses of the function in expressions will return the proper data type and be converted to match the function's definition.

Register_Function DoTheJob Integer iType String sName Returns Integer

If the function has already been defined by the program (possibly in a package) and the parameters and types of the function do not match those given in register_function, a compile time error, "Illegal redefinition of function/message", is returned.

The register_function command can also be used to register properties so they can be accessed in expressions before they are defined.

Register_Function piHitCount Returns Integer


Register_Object

See Also: Get, Object

Purpose

To allow references to an object in expressions at points in the program prior to the point at which the object is defined.

Syntax

Register_Object {object-name}

What It Does

Objects can be referred to in programs by their "access methods". Before any object can be referred to, the compiler must know the name of the object. If you wish to refer to an object before it has been defined, the register_object command allows you to predefine the object.

The register_object command defines the symbol get_objectname . This is actually a function that is translated by the system for each object that is created. The function returns the absolute object_id of the named object.

Register_Object oName

You may not assign an object the same name as a function or a property. If you attempt to do so, an error will be declared. For this reason, developers often preface object names with the letter "o". This insures that the object will not share the same name as a function. It also makes it easier to identify object names within your code.

Code generated with theStudioautomatically registers all objects at the top of a component.

The register_object command is typically used with objects referenced in on_item, on_key or entry_item commands. It is a misuse of the command to register an object for use as another object's property (e.g.,, action_bar_id property) at points prior to the referenced object's (the menubar's, in this case) creation. When this is done, various properties of the undefined object (such as action_bar_keys_msg) are not available for access by the using object, and the assignment will fail.


Register_Procedure

See Also: Procedure, Register_Function, Send

Purpose

To allow a procedure to be referred to in a part of the program that precedes the point at which the procedure is defined.

Syntax

Register_Procedure {message} [{type} {param} … …]

Register_Procedure Set {message} [{type} {param} … …]

What It Does

The message is the name of the message that is forward referenced. Since the point of the register_procedure command is to predefine messages, message should not already be defined when this command is used.

{type} is used with each parameter passed to the procedure to define its data type. Valid data types are integer, number, date, real and string.

The name of the parameter may be anything that describes the use the value in the procedure. {param} may not be a reserved word, and must follow the typical symbol rules.

Register_Procedure AddName String sName String sAddress String sPhone

Properties have two access methods, a get property-name and set property-name message. The set property-name can be registered using the register_procedure command. The get property-name can be registered using the register_function command

Register_Procedure Set piHitCount integer iCount

Register_Function piHitCount returns integer

Use of this command is optional - Procedure and Procedure Set messages do not need to be registered before they are used in a program. This is not the case of functions which must be registered (or defined) before they can be used in an expression.

Global methods (procedures, procedure sets and function) may not be registered.


Registration Command

Registration

Purpose

To place the registered name and serial number of a Visual DataFlex license into variables.

Syntax

Registration StringVariable {IntegerVariable)

What It Does

Registration retrieves the name and serial number of the Visual DataFlex license in use, and moved the registration name to StringVariable and the serial number to IntegerVariable.

string sRegistrationName

integer iSerialNumber

Registration sRegistrationName iSerialNumber

In this example, the registration name of the license under which the current program is being run is moved to string variable sRegistrationName and the serial number is moved to integer variable iSerialNumber.

Notes

  • The registration information retrieved is stored in file termlist.cfg.


Relate

See Also: Attach, Find, Set_Relate, Relationships, Table Relationships

Purpose

To find parent records matching the data in a child table's record buffer. This command is usually not used when working with Data Dictionaries.

Syntax

Relate {child-table} […{child-table}]

What It Does

Relate moves field data on which relationships to parent (related to) database tables are based from the record of child-table which is in its buffer into the buffer of each parent table which is open. Then it attempts a find in each parent table for a record with matching field data. A child table is one whose Database Builder specifies relationship of one or more of its fields to one or more of the fields of the parent table.

If any of the parent tables has parent tables of its own, a relate is done on each such table to find its parents, and so on until all ultimate parents have been related to. If more than one child-table is named in the command, this process is repeated for all such child-table, none of which needs to bear any relation to any other child-table.

Relate is used with the find process to find all related to records in a database.

Example

Find Ge Pay_Tran.Posting

Relate Pay_Tran

In this example, a record in database table pay_tran is found according to data in Field posting. Then records in all parent tables with field data matching that of the pay_tran record in the buffer are found, and data from pay_tran is moved to the related to fields in their buffers. This process is repeated for any parent tables related to by the parent tables of pay_tran.

If pay_tran had a single parent, employee, and the relation was from Field emp_num in pay_tran to recnum in employee, then the following commands would have the same effect as the relate pay_tran statement above, so long as employee itself had no parent of its own:

Clear Employee

Move Pay_Tran.Emp_Num To Employee.Recnum

Find eq Employee.Recnum

The only performance differences between the two methods are: (a) if the required record from employee is already in its buffer, relate does not find it again; (b) if the record in employee is not found, relate will not declare an error; and (c) relate requires the relationship to be defined in the Database Builder of pay_tran.

If a relate finds no matching record in a parent table, a subsequent save command will relate the child-table record to Record Number 0 in such parent table (null relationship).

Notes

  • Relate works only when the record buffer for child-table is active, that is, when it contains a record previously retrieved from the database.

  • If a parent table is not open, it is not related to, and no error is reported. Likewise, any parent tables of such a parent table are unaffected by the relate command.

  • Relate functions only on the basis of relationships among and between tables defined in the DataFlex Database Builder, or in preceding set_relate commands executed in the program running.

  • The attach command works in the opposite direction from that of relate. While relate moves data to, and finds records in parent tables, attach moves data from parent tables to child tables.

  • The command:

Relate a_table b_table

//is exactly the same as:

Relate a_table

Relate b_table

  • Relate is useful for writing programs or macros which can operate independently of the particular field names of the tables in use.

  • When child-table relates to a particular parent table through more than one field, the lowest numbered field in child-table is used for the find in the parent table. If this find fails, no further finding will occur.

  • You can pass either the child-table's logical name or its table number (in the filelist) to the relate command.


Remove_Directory

See Also: File_Exist, Get_Directory, Make_Directory, Make_Temp_File, Valid_Drive

Purpose

To remove a directory.

Syntax

Remove_Directory {directory-path}

What It Does

The Remove_Directory command removes the directory specified in the directory argument.

Example

Remove_Directory "k:\accounting\data"

In this example, the Directory data will be removed from the directory k:\accounting.

Notes

  • If the directory cannot be removed for any reason, e.g., there are files in the directory, or the directory attributes are set to read-only, the DFERR_RAWFILE_ERROR error will be reported.

  • Remove_Directory will fail if the current directory is the same as the directory you want to remove.

  • Remove_Directory will fail when the directory is in use by another application.


RenameFile

See Also: CopyFile, Direct_Input, EraseFile

Purpose

To change the name of a disk file.

Syntax

RenameFile {old-filename} To {new-filename}

old_filename may contain a directory path

new_filename may not contain a directory path

Example

renamefile "vendor.txt" to "seller.txt"

old_filename may contain a directory path. New_filename will appear in the same directory that old_filename was in. If new_filename contains a path, or already exists, or if the directory named in old_filename does not exist, or old_filename does not exist, no rename is done, and no error is reported.

Notes

  • Renamefile treats all directory files, including DataFlex database files, the same. You do not need to open a database file in order to execute a renamefile on it. In fact, a database file must not be open when it is renamed.

  • You may use "wild-card" (ambiguous) filenames with renamefile provided your operating system supports such usage in its rename function.

  • If renamefile is executed on a nonexistent old_filename, no error will be triggered, and no file will be affected in any way.

  • Use extreme caution when invoking this command. If new_filename already exists, no error will be triggered, and no file will be affected in any way.

  • When a DFPATH is in effect: If old_filename contains no directory name, only the first path in DFPATH will be used. Renamefile will not search the second and following paths as the open command does.

  • The effect of this command is the same as using the operating system's RENAME command, except that it does not report errors.


Repeat

See Also: Boolean Expressions, Execution Control Commands, For, Loop, Until, While, Break, Boolean

Purpose

Executes a repeating block of code.

Syntax

Repeat

Until {Boolean-expression}

What It Does

Until sends execution back to the last previous Repeat command until the {Boolean-expression} becomes true. When {Boolean-expression} becomes true, execution proceeds to the command next following the Until command.

A Repeat ... Until block will still execute once even if {Boolean-expression} is True, unless you program the Repeat command with conditionals to make it, also, subject to {Boolean-expression}.

Example

Integer iCount

String sName

Move 0 to iCount

Repeat

Clear people

Readln sName

Send SaveName sName

Increment iCount

Until (iCount >= 100)

Send ShowDetails

In this example, the loop keeps executing until Variable iCount becomes greater than or equal to 100. Execution then moves to the next command line (Send ShowDetails).

Boolean bFinished

Repeat

Get InventoryCheck To bFinished

Until bFinished

The function method InventoryCheck executes repeatedly until the Boolean variable bFinished is true. Execution then continues on to the next command.

integer iPlayers

Repeat

increment iPlayers

Until (iPlayers >= 10)

In this example, 1 is added to the variable iPlayers repeatedly, until it is greater or equal to 10. Keep in mind that iPlayers starts out at 0, since it is not specifically initialized to a value.

Notes

  • Repeat loops may also be terminated with loop (although this technique is unusual).

  • You may place Repeat ... Until blocks inside other looping blocks, up to a limit of 40. And you may freely intermingle the various types of loops. But you may not overlap them—you must end the innermost block first, then the next innermost, and so on.

  • You may exit from the middle of a loop by using break. If your loop is within a function or procedure (which it typically is), it may be terminated with function_return or procedure_return, which also terminate the function or procedure.

  • Statements inside blocks are usually indented to make the blocks more readable.

  • Repeat is an unconditional initiator. For a conditional initiator, use while.


Reread

See Also: Transactions and DDOs, Lock, Unlock

Purpose

To maintain data integrity in multi user systems by updating record buffer data for any changes made by other users since the data was first brought into the buffers, and to prevent further changes by other users until an unlock command has been executed. This command is usually not used when working with Data Dictionaries.

Syntax

Reread [{df-file} … {df-file}]

df_file is the logical name, or filelist number, used to identify the file.

What It Does

When a reread command is executed, an internal lock command is executed, preventing changes to all files opened by the program. Then reread updates all active records in the buffers for any changes which may have been made to the database (by other users) since the data was first brought into the buffers by the user of the program, unless df_files have been named in the command. If df_files have been named, then only the buffers for the named database files are updated (whether their buffers are active or not).

All database files opened by the program are locked, and remain so until a following unlock command. The records in the buffers for Database Files vendor and customer are updated for any changes since the disk was last read.

Caution

In a database file for which LOCKING TYPE is set to NONE in Database Builder, Reread does not refresh the buffer unless Reread is used with an argument naming the file.

Whether you specify df_files or not, reread will lock all files opened by the program except for those opened read_only or alias. The lock remains in effect until an unlock command is executed.

Example

Reread

In this example, all database files opened by the program are locked, and all active record buffers are updated.

This command:

Reread animals

is the same as:

Lock

Find eq animals By Recnum

The following program fragment updates a counter (animals.confirmed) in a file in a manner which will not be corrupted by concurrent activities of other users.

Get AnimalName to animals.name

Find ge animals.name

If (Found) Begin

Reread animals

Increment animals.confirmed

Save animals

Unlock

End

The Reread command is required to make sure that the value of animals.confirmed that is incremented is in fact the current value of that field. If the starting value pulled into the buffer had been 102 and other users had raised it to 110, incrementing without a reread would put it back to 103, since it would have started out from 102 (the original value in the buffer).

The interval between reread and unlock is critical. In the example above, there are commands (increment and save) in that interval. Both of these commands must be in that interval, but neither requires keyboard input. It is essential that no command requiring keyboard input be placed in this interval, because all database files opened by the program are locked, and any delay, or potential for delay, could deprive all other users of use of the affected file(s). As shown above, the lock interval would be a fraction of a second, imperceptible even to other users actively saving to the same database.

The following program fragment will get the next available invoice number from a system file in a manner which cannot be corrupted by concurrent activities of other users who also are getting invoice numbers from the same system file:

Reread sysfile

Move (sysfile.invnum +1) To sysfile.invnum

Saverecord sysfile

Unlock

The invoice number generated from sysfile.invnum is "assigned" to the user who "drew" it. Another user will never get the same number. For this reason, where continuous accountability of invoice numbers is required, the number either should be drawn at the moment the invoice is actually issued, or if drawn prior to that point, must be assigned to a voided invoice in the event the invoice is not issued, rather than simply discarded.

Notes

  • An Unlock command must follow each reread command with as few intervening commands as possible, and no intervening commands which require keyboard input (entry_item, inkey, or input).

  • Records that have been re-read may be updated without fear of disrupting other users because the file is locked after the reread.

  • Always reread before you put any changes to the record buffer. If you reread after making a change to a field, the field value on disk will overwrite the changed value, unless the field is an indexed one, in which case an Error Status 82 (Edited record not saved) will be triggered, the buffer will be cleared, and Error Status 25 (Record not found) will be triggered.

  • If the buffer of an explicitly named df_file (reread df_file) is inactive (clear, or recnum set equal to zero), an Error Status 25 (Record not found) will be triggered.

  • Rereads or locks are not required when you are only creating new records. Other users cannot make changes to records which you have not yet created.

  • Where two or more locks or rereads are in effect at the same time, the same number of unlocks will be required to unlock the database.

  • Files are locked in the order of their numbers in the file list, and unlocked in the reverse of that order.

  • You can pass either the file's logical name or file number (in the file list) to the reread command.


RowId

See Also: Declaring Variables, Variable Declaration Commands, Struct

Purpose

Declares one or more RowId variables.

Syntax

To declare RowId variables

RowId {identifier} [{identifier}]

Where

  • Where {identifier} is the name of a new Real variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type RowId

RowId{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

RowId defines variables in memory to contain data about a table's RowId. A RowId contains the information needed to uniquely identify a row (aka record) within a table. Typically these variables are used to store a Table's row identifier so that it can be used later to refind that row.

A RowId variable is assigned by either moving the RowId data from one RowId typed variable to another, or, by using one of the RowId global functions provided to work with RowId. Those functions are: GetRowID, FindByRowID, NullRowID, IsNullRowID, IsSameRowID, SerializeRowID and DeserializeRowID.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

It is important to note that RowId variables are strictly typed. You cannot cast RowId variables in to or out of other variable types.

Procedure RunTest RowId riOrder

// create some local RowId variables

RowId riCustomer riSalesPerson riOrder riOldOrder

RowId[] riDetails

:

Move riOrder to riOldOrder

:

End_Procedure // RunTest

In the above example, local RowId variables riCustomer, riSalesPerson, riOldOrder and riDetails are created inside Procedure RunTest. The riDetails variable is defined as an array of RowIDs. The procedure is passed a RowId parameter named riOrder. This value is later assigned to riOldOrder using the move command. Because the source and destination data type of the move is RowId, this is allowed.

Procedure LoadOrder RowId riOrder

// create some local RowId variables

RowId riCustomer riSalesPerson

RowId[] riDetails

Integer iDetail

Boolean bFound

Move (FindByRowID(OrderHea.File_number, riOrder)) to bFound

If bFound Begin

// find parents Customer and Salesperson

Relate OrderHea

Move (GetRowID(Customer.File_Number)) to riCustomer

Move (GetRowID(SalesP.File_Number)) to riSalesPerson

// find all detail records

Clear OrderDtl

Attach OrderDtl

Find Gt OrderDtl by 1

While ((found) and OrderDtl.Order_number = OrderHea.Order_number)

Move (GetRowID(OrderDtl.File_number)) to riDetails[iDtl]

Increment iDetail

Loop

End

Else Begin

Move (NullRowID()) to riOrder

end

Set priOrder to riOrder

Set priCustomer to riCustomer

Set priSalesPerson to riSalesPerson

Set priDetails to riDetails

End_Procedure // RunTest

In the above example, the procedure is passed a RowId for an order. The order is found using the RowId. If an order is found, Customer and Salesperson records are found and stored in the appropriate RowId variables. All detail records are found and each record's RowId is stored in a RowId array. Finally, all of this data is stored in this object's properties.

RowId[] riCustomers

This example declares 1 dynamic array variable, named riCustomers, containing an undefined number of elements of type RowId.

RowId[5] riCustomers

This example declares 1 static array variable, named riCustomers, containing 5 of elements of type RowId.

RowId[][3] riCustomers

This example creates a two-dimensional dynamic array variable named riCustomers, containing an undefined number of elements of type RowId. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global RowId variable, you should use the global_variable command to do so.

  • The RowId style of programming can be used with all types of tables. Even if your underlying table uses Recnum (e.g. the embedded database), you may still use the RowId programming style. The use of RowId and the RowId functions completely replaces the need to use Recnum programming techniques. Using the RowId programming style will create a more portable application.


Runprogram

See Also: Chain, Memory

Purpose

Executes a call to another operating-system program, optionally returning when the called program has finished execution, to the statement in the calling program that follows the runprogram statement.

Syntax

Runprogram [Wait] [Background] {program-name} [{program-arguments}]

What It Does

Runprogram runs the operating-system program first named in the contents of program_name. Program_name may contain literal arguments for use by the named program, and/or such arguments may be placed in program_arguments.

If the wait option is included, execution will return to the running Visual DataFlex program at the line following the runprogram command, upon termination of the program first named in program_name.

If the background option is included, execution will return to the running Visual DataFlex program at the line following the runprogram command, immediately after launching of the program first named in program_name

Example

Runprogram wait "TotalHoursForEmployee.exe" "EmployeeId=58"

In this example, runprogram executes the program TotalHoursForEmployee.exe, which might be another Visual DataFlex program, with argument EmployeeId=58. After TotalHoursForEmployee.exe has completed, execution will return to the calling Visual DataFlex program after the runprogram line.

string sDocument sWordProc

move "Word.exe" to sWordProc

get Value of oCustomer_Document to sDocument

Runprogram wait sWordProc sDocument

In this example, the program Word.exe is executed with an argument of sDocument (the value of a dbForm object named oCustomer_Document). When the program named in sWordProc has terminated, execution returns to the calling Visual DataFlex program at the command line following the runprogram command.

string sDocument sWordProc

move "notepad.exe" to sWordProc

move "MyNotes.txt" to sDocument

Runprogram background sWordProc sDocument

In this example, the Windows Notepad program is launched and opens the file MyNotes.txt. Execution in the calling Visual DataFlex program continues immediately at the command line following the runprogram command.

Notes

  • Runprogram can be used to execute calls to any program, including other Visual DataFlex programs.

  • As an alternative to the runprogram command, you can use the ShellExecute Windows API call. This API call, when used with "open" as the "operation" parameter, will open a document in Windows using the application associated with it in the Windows Registry.

// Since ShellExecute is already used in some predefined Visual DataFlex packages,

// this #IFDEF statement will stop interference of this declaration with those

// inthe Visual DataFlex packages.

#IFDEF GET_SHELLEXECUTE

#ELSE

// external function call used in Procedure DoStartDocument

External_Function ShellExecute "ShellExecuteA" shell32.dll ;

Handle hWnd ;

String lpOperation ;

String lpFile ;

String lpParameters ;

String lpDirectory ;

Dword iShowCmd Returns Handle

#ENDIF

// this will perform an operation on a file (e.g. open) with the application

// registered in the Windows Registry to open that type of file (via its extension)

// sOperation would be "open" (it could also be "print" etc).

Procedure DoStartDocument GLOBAL String sOperation String sDocument

handle hInstance hWnd

Get Window_Handle To hWnd

Move (ShellExecute (hWnd, sOperation, (Trim (sDocument)), '', '', 1)) To hInstance

End_Procedure // DoStartDocument

  • If runprogram wait is executed with only "" as argument, a command prompt window will appear, awaiting input. If such input includes redirection of the output of a DOS program (the > operator), such a command must be a call to the command prompt program (command.com on Windows 98 and ME, cmd.exe on Windows NT, 2000, XP and 2003), or the redirect operator will be interpreted as a parameter of the command.

  • When runprogram is executed, any uppercase letters in program_name are converted to lower case automatically. The contents of program_arguments are passed unchanged.

  • If the running Visual DataFlex program was called from another Visual DataFlex program by a chain wait command, runprogram is executed as though written with wait, and execution returns to the calling Visual DataFlex program. Chain was used frequently in character-mode versions of DataFlex. The use of chain is discouraged in favor of runprogram in Visual DataFlex.


Save

See Also: Understanding File Buffers and DDO Field Buffers, Attach, Lock, Reread, SaveRecord

Purpose

To save changes made to a record buffer, including data from parent tables, to the database on disk. This command is usually not used when working with Data Dictionaries.

Syntax

Save {child-table} […{child-table}]

Child-table is the logical name or filelist number of the table being saved.

What It Does

Save first executes an internal Attach command (moving data for fields on which a relation is based from all parent tables into child-table) and then writes record buffer data to disk and updates all on line indexes for child-table. If the record buffer was active (contained an existing record) prior to the save, only data for fields whose data changed is written, and it is written back to the original record (recnum). If the record buffer was inactive, a new record is created.

Example

find ge boxcars by index.2

If (Found) Begin

Reread Boxcars

Move sNewOwner to boxcars.owner

Save boxcars

Unlock

End

In this example, a record in the database table boxcars is found, the value of Variable sNewOwner is moved to Field owner, and the record is saved back to the table. The record will retain the same record number and all other fields will remain unchanged.

Clear boxcars

Move sId To boxcars.id

Move sLocation To boxcars.location

Save boxcars

In this example, which starts with a clear record buffer, Data for two fields is moved to the record buffer for Database File boxcars, and a save to the boxcars database table is done. This will create a new record in the boxcars table, updating its indexes that use the two fields.

In the following example, boxcars is related to parent Database File locations. The relationship is established through Field zipcode in both tables, locations.zipcode and boxcar.zipcode (relating fields do not have to have the same name in their tables, but they may).

Clear boxcars locations

Move sId to boxcars.id

Move sZip to locations.zipcode

Find Eq locations.zipcode

Save boxcars

Here, the buffers for both tables are cleared. Then data is moved to base a boxcars record on. Then data is moved to the location, but it is not accepted to boxcars.zipcode. It is accepted to locations.zipcode to enable the next statement (find eq locations.zipcode) to bring a locations record into its buffer (the locations record might contain a city name, a state name, a counter of the number of boxcars located there, etc.). Then the last statement, save boxcars, performs an attach, which moves the value of locations.zipcode to boxcars.zipcode, and the relationship between the two records is established in the data that is saved to disk. Hereafter, when the boxcars record is found and a relate done, the same location record will be found also.

Where child-table relates to one or more parent tables, and data in the field(s) on which such relationship(s) is (are) based may be changed, you must use save rather than saverecord, unless you include an attach with the saverecord.

Notes

  • Once you move data to an active record buffer, you must either save that record or deactivate it. Doing otherwise will trigger DataFlex Error 82 (Edited record not saved).

  • If you save a record on which there has been no change made to the contents of the record buffer, no save will take place.

  • In multi-user operations, be sure to issue a reread command immediately before the save, and unlock as soon thereafter as possible.

  • Save updates all on-line indexes, adding or modifying key entries for the saved record.

  • When you do not wish an attach done, or when child-table has no parent tables, use of the saverecord command saves a very small amount of time per execution.

  • The capability to name multiple child-tables in one command is provided as a convenience. The command:

Save this_table that_table

//is exactly the same as:

Save this_table

Save that_table

  • You can pass either the table's logical name or its filelist number to the save command.


SaveRecord

See Also: Understanding File Buffers and DDO Field Buffers, Attach, Lock, Reread, Save

Purpose

To save changes made to a record buffer to the database on disk without updating fields that relate to other tables with data from those tables. This command is usually not used when working with Data Dictionaries.

Syntax

SaveRecord table [...table]

table is the logical name or filelist number used to identify the table.

What It Does

Saverecord saves data in the buffer for table to the disk and updates all indexes. If the record buffer was active (contained an existing record) prior to the saverecord, that record is edited. If the record buffer was inactive, a new record is created.

Saverecord transfers all data in the record buffer to the disk. It does not do an automatic attach.

find ge boxcars by index.2

If (found) begin

reread boxcars

move sNew_owner to boxcars.owner

saverecord boxcars

unlock

end

In this example, a record in Database File boxcars is found, and the value of a field is changed. Then a saverecord writes the changed data back to the table. The record will retain the same record number and all other fields will remain unchanged.

clear boxcars

Move sId to item boxcars.id

Move sLocation to boxcars.location

saverecord boxcars

This example starts with a clear (new-record) buffer, fills it with data, and does a saverecord. This will create a new record in Database File boxcars, and update all on line indexes.

Where table relates to one or more parent tables, and data in the field(s) on which such relationship(s) is (are) based may be changed, you must use save rather than saverecord, unless you include an attach with the saverecord.

Notes

  • Once you move data to an active record buffer, you must either save that record or deactivate it. Doing otherwise will trigger DataFlex Error 82 (Edited record not saved).

  • If you saverecord where no change has been made to the contents of the record buffer, no saverecord will take place.

  • In multi user operations, be sure to issue a reread command immediately before moving data to the record buffer and executing the saverecord, and unlock as soon thereafter as possible.

  • Saverecord updates all on line indexes, adding or modifying key entries for the saved record.

  • When table has parent tables and you wish an attach done, use the save command.

  • The capability to name multiple tables in one command is provided as a convenience. The command:

saverecord thisTable thatTable

//is exactly the same as:

saverecord thisTable

saverecord thatTable

  • You can pass either the table's logical name or its filelist number to the saverecord command.


Send

See Also: Method Overloading, Get, Procedure, Set

Purpose

To send a message to an object.

Syntax

send message [of object] arguments

What It Does

The send command is used to tell an object to perform the operation of the passed message. Message may be a message defined in a class or in the program. The makeup of arguments depends on the syntax of the message being sent.

The optional to object clause permits identification by name or access method of an object to receive the message. If the clause is not used, message is sent to the current object (self, i.e. the object that sent the message).

The following two samples are the same. In both cases the message Request_save is sent to the object customer_DD.

Send Request_Save of Customer_DD

Handle hCustomer_DD

Move Customer_DD to hCustomer_DD

Send request_Save of hCustomer_DD

The following two samples are the same. In both cases the message AddNewName is sent to itself passing three string parameters.

Send AddNewName sFirstName sLastName sPhone

Send AddNewName of self sFirstName sLastName sPhone

Internally, the message created by the send command is of the form msg_message. Send commands do not return a value to the sending object, as the get and set commands do.

If no definition of message can be found, the send command will generate an error at the end of compilation. If message is defined in the program but the receiving object does not understand the message, then an error will be generated at runtime.

Notes

  • Previous of versions of DataFlex used the To keyword instead of the Of keyword to specify the object that receives the message. This created confusion because the Get and Set commands used the To keyword for an entirely different purpose. The To syntax is still supported and you will see it used in legacy DataFlex code.


Set

See Also: Get, Property

Purpose

To set the value of an object property.

Syntax

set property [of object] to value

set property [of object] [item_number] to value

What It Does

The set command is designed to set values of the properties of objects. Objects of every class are composed of storage locations for information pertaining to the operation of the object. The set command places (value) into one of these storage locations (property).

For most of the object properties in classes predefined in DataFlex, a pair of messages, one get and the other set, is provided. Consult the property list in each class to determine which commands are provided for the property in question, and the exact name of the message for each.

Procedure IncrementCount

Integer iCount

Get piHitCount to iCount

Increment iCount

Set piHitCount to iCount

End_procedure

The object that receives the message may be either explicitly specified (to object) or omitted, in which case the object identified is the current-object (self, i.e., the object that sends the message also receives the message).

The following two samples are the same. In both cases the property from object Customer_DD is being queried from some other object.

Set Changed_State of Customer_DD to True

Handle hCustomer_DD

Move Customer_DD to hCustomer_DD

Set Changed_State of hCustomer_DD to True

The following two samples are also the same. In both cases, the property is being queried from the object that is sending the message.

Set Changed_State to True

Set Changed_State of Self to True // "of Self" is not required

Some properties are associated with object items, rather than the object overall. For those properties, a item index number should be specified (item_number). Some item based properties allow you to omit the item index in which case the value 0 or the value of current_item of the object is used.

Struct Properties

Special consideration needs to be given for accessing data that is stored in class properties that are of struct type. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire struct. This works just like a struct variable assignment.

To read or write individual members of a struct property, it is necessary to get the property to a local struct variable of the same type. You would then manipulate the data of this local struct and write back the changes by setting the struct property once again.

Example…

struct tNameAndAddress

string sName

string sAddress

end_struct

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare a struct property

Property tNameAndAddress pContact

End_Procedure

Procedure StoreName String sName

tNameAndAddress contact // create a local struct variable

// get the struct property to the variable.

Get pContact to contact

// show the current name.

Send Info_Box ("The current name is: " + contact.sName)

// change the name.

Move sName to contact.sName

// Save the change back to the struct property.

Set pContact to contact

End_Procedure

End_Class

Array Properties

Special consideration needs to be given for accessing data that is stored in array properties. The Get and Set commands that are used for accessing a property's data can only be used to get and set the entire array. This works just like an array variable assignment.

To read or write individual array property elements, it is necessary to get the property to a local array variable of the same type. You would then manipulate the data of this local array and write back the changes by setting the array property once again.

Example…

Class cMyButton is a Button

Procedure Construct_Object

Forward Send Construct_Object

// Declare an array property

Property string[] psNames

End_Procedure

Procedure StoreName String sNewName

string[] sNames // create a local array variable

integer iElementCount

// get the array property to the variable.

Get psNames to sNames

// Add the new name.

Move (SizeOfArray(sNames)) to iElementCount

Move sNewName to sNames[iElementCount]

// Save the change back to the array property.

Set psNames to sNames

End_Procedure

End_Class

Item-Based Properties

The compiler must explicitly recognize that a message requires an index parameter. Special compiler commands are created to identify these messages. The indexed messages identified as current-item based, which means that current_item is used if the index parameter is omitted, are:

Value | Message | Aux_Value
Shadow_State | Select_State | Checkbox_Item_State
Autoclear_State | Center_State | Entry_State
Item_Changed_State | Item_Entry_Msg | Item_Exit_Msg
Item_Validate_Msg | Data_File | Data_Field
Data_Window | Item_Options | Item_Option
Prompt_Object | Zoom_Object |

The indexed messages identified as Form based, which means that zero is used if the index parameter is omitted, are:

Form_Width | Form_Color | Form_Datatype
Form_Options | Form_Font | Form_Row
Form_Column | Form_Typeface | Form_Fontheight
Form_Fontweight | Form_Fontitalics | Form_Fontunderline
Button_Aspect | Form_Height | Form_Guiwidth
Form_Guiheight | Form_Guirow | Form_Guicolumn
Form_Margin | Form_Option | Form_Style
Form_Extended_Style | Form_Border | Password_State
Form_Mask | Form_Button | Form_Button_Value
Form_Window_Handle |  |

The difference between current-item based and form based messages are historical. Since we only recommend that you omit the index parameter on single item objects the current-item should always be zero. This means that both types of messages should be treated the same.

We advise that you always omit the item index parameters for objects that are single item objects (in which case current_item should be zero anyway). Examples of single item objects are dbForms, Forms, and ComboForms. For example, when in a dbForm the Value property should be accessed as follows:

Set Value of oMyDbForm to "form test value"

We advise that you always include the item index parameter in multi-item objects. Examples of multi item objects are Arrays, Grids, dbGrids and dbLists. For example, when in an array the Value property should be accessed as follows:

For iCount from 1 to 10

Set Value iCount to "Array test value"

Loop

Every property has a known data type. If value is a variable of other than the type specified in the property, its value will be converted automatically to the required type.

Notes

  • In older programs you will see the keyword item before the index value (e.g., set Value item 0 to "x"). The item keyword is optional. Its usage is no longer recommended.


Set_Argument_Size

See Also: Append_Output, Direct_Input, Direct_Output, Get_Argument_Size

Purpose

To set the current argument size setting. Argument size is the largest size permitted for string variables.

Syntax

set_argument_size bytes

What It Does

The default maximum argument size can be found under Argument Size in the VDF Specifications book. Where arguments of greater size than the default may need to be handled in a program, a larger allocation of memory can be specified by the set_argument_size command.

set_argument_size 256000

In this example, the maximum argument size for a program is set to 256000 bytes.

Argument size can be reset any number of times desired in a program. This is important because large argument sizes consume more memory. Argument work space is twice the amount of memory indicated by the maximum size in effect, and the string expression stack consumes additional memory beyond that when a large argument size is set.

Notes

  • When one program chains to another, the argument size in the first program automatically governs the argument size in all succeeding programs unless it is reset in a succeeding program. If it is reset in a succeeding program and execution returns to an earlier program, the most recent setting (in the chained-to program) continues to govern until the argument size is again explicitly reset.

  • The Get_Argument_Size command returns the current argument size to a variable.

  • If the length of the value moved to any argument exceeds the maximum argument size, the value will be truncated in the argument with no error report.


Set_Attribute

See Also: Execute Structure_Start, Get_Attribute, Structure_Start, Structure_End

Purpose

To set a global, file, field, or index attribute.

Syntax

set_attribute attribute [of fileNum [fieldNum | indexNum [segmentNum]]] to value

Argument | Explanation
attribute | Attribute ID to be set.
fileNum | Optional handle for either a file or a structure.
fieldNum | Optional field to be modified.
indexNum | Optional index to be modified.
segmentNum | Number of the segment in indexNum to be modified
value | The value to use for setting the attribute. This can be a constant or a variable.

What It Does

This command is used to set or modify any attribute. All low-level file modifications can be done through the use of the set_attribute command.

Example – Runtime Attribute

integer iFreq

move 1000 to iFreq

set_attribute DF_RUNTIME_PROGRESS_FREQUENCY to iFreq

This example sets the interval between runtime progress updates to 1000 milliseconds (1 second).

Example – Global Attribute

string sFileListName

move "filelist2.cfg" to sFileListName

set_attribute DF_FILELIST_NAME to sFileListName

This example changes the current filelist in use to filelist2.cfg.

Example – File Attribute

handle hFile

move 20 to hFile // new number

set_attribute DF_FILE_LOGICAL_NAME of hFile to "OrderHea"

set_attribute DF_FILE_ROOT_NAME of hFile to "OrderHea"

set_attribute DF_FILE_DISPLAY_NAME of hFile to "Order Header Table"

This example adds the OrderHea table to the current filelist as file number 20.

Example – Field Attribute

integer iField iIndex

handle hFile

open Customer

move Customer.File_Number to hFile

move 1 to iField

move 2 to iIndex

Structure_Start hFile "DATAFLEX"

set_attribute DF_FIELD_INDEX of hFile iField to iIndex

Structure_End hFile DF_STRUCTEND_OPT_NONE

This example sets the main index for field 1 in the Customer table to index 2.

Example – Index Attribute

integer iIndex iSegment iField iNumSegments

handle hFile

open Customer

move Customer.File_Number to hFile

get_attribute DF_FILE_LAST_INDEX_NUMBER of hFile to iIndex // get last index

increment iIndex // add 1 to last index number

move 2 to iNumSegments

move 1 to iSegment

Structure_Start hFile "DATAFLEX"

create_index hFile at iIndex

set_Attribute DF_INDEX_NUMBER_SEGMENTS of hFile iIndex to iNumSegments

field_map hFile "STATE" to iField // get field number of STATE field

set_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex iSegment to iField

increment iSegment // next segment

field_map hFile "NAME" to iField // get field number of NAME field

set_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex iSegment to iField

Structure_End hFile DF_STRUCTEND_OPT_NONE

This example adds an index after the last index to the Customer table. The index has 2 segments: the STATE field and the NAME field.

Example – Index-Segment Attribute

integer iIndex iSegment iField iNumSegments

handle hFile

open Customer

move Customer.File_Number to hFile

get_attribute DF_FILE_LAST_INDEX_NUMBER of hFile to iIndex // get last index

increment iIndex // add 1 to last index number

move 2 to iNumSegments

move 1 to iSegment

Structure_Start hFile "DATAFLEX"

create_index hFile at iIndex

set_Attribute DF_INDEX_NUMBER_SEGMENTS of hFile iIndex to iNumSegments

field_map hFile "NAME" to iField // get field number of NAME field

set_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex iSegment to iField

increment iSegment // next segment

// get field number of CUSTOMER_NUMBER field

field_map hFile "CUSTOMER_NUMBER" to iField

set_Attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex iSegment to iField

Structure_End hFile DF_STRUCTEND_OPT_NONE

This example adds an index after the last index to the Customer table. The index has 2 segments: the NAME field and the CUSTOMER_NUMBER field.

Runtime Attributes

DF_RUNTIME_PROGRESS_FREQUENCY

Global Attributes

DF_ALL_FILES_TOUCHED*

DF_DATE_FORMAT

DF_DATE_SEPARATOR

DF_DRIVER_NAME*

DF_DRIVER_NUMBER_SERVERS*

DF_DRIVER_SERVER_NAME*

DF_DECIMAL_SEPARATOR

DF_FILELIST_NAME

DF_HIGH_DATA_INTEGRITY

DF_LOCK_DELAY

DF_LOCK_TIMEOUT

DF_NUMBER_DRIVERS*

DF_OPEN_PATH

DF_REPORT_UNSUPPORTED_ATTRIBUTES

DF_REREAD_REQUIRED

DF_STRICT_ATTRIBUTE

DF_TRANSACTION_ABORT

DF_TRAN_COUNT

File Attributes

DF_FILE_ALIAS

DF_FILE_CHANGED*

DF_FILE_COMMITTED*

DF_FILE_COMPRESSION+

DF_FILE_DISPLAY_NAME+

DF_FILE_DRIVER+*

DF_FILE_HANDLE_TYPE*

DF_FILE_INTEGRITY_CHECK+

DF_FILE_IS_SYSTEM_FILE

DF_FILE_LOCK_TYPE+

DF_FILE_LOGICAL_NAME+

DF_FILE_LOGIN

DF_FILE_MAX_RECORDS+

DF_FILE_MODE

DF_FILE_MULTIUSER+

DF_FILE_NEXT_EMPTY+

DF_FILE_NEXT_OPENED*

DF_FILE_NEXT_USED+*

DF_FILE_NUMBER*

DF_FILE_NUMBER_FIELDS+*

DF_FILE_LAST_INDEX_NUMBER+*

DF_FILE_OPEN_MODE*

DF_FILE_OPENED*

DF_FILE_OWNER+

DF_FILE_PHYSICAL_NAME+

DF_FILE_RECORD_IDENTITY+

DF_FILE_RECORD_LENGTH+

DF_FILE_RECORD_LENGTH_USED+*

DF_FILE_RECORDS_USED+*

DF_FILE_RESTRUCTURE*

DF_FILE_REUSE_DELETED+

DF_FILE_ROOT_NAME+

DF_FILE_STATUS

DF_FILE_TOUCHED*

DF_FILE_TRANSACTION+

DF_FILE_TYPE+*

Field Attributes

DF_FIELD_INDEX+

DF_FIELD_LENGTH+

DF_FIELD_NAME+

DF_FIELD_NATIVE_LENGTH+*

DF_FIELD_NUMBER+*

DF_FIELD_OFFSET+

DF_FIELD_OLD_NUMBER

DF_FIELD_OVERLAP+*

DF_FIELD_PRECISION+

DF_FIELD_RELATED_FIELD+

DF_FIELD_RELATED_FILE+

DF_FIELD_TYPE+

Index Attributes

DF_INDEX_KEY_LENGTH+*

DF_INDEX_LEVELS+*

DF_INDEX_NUMBER_BUFFERS

DF_INDEX_NUMBER_SEGMENTS+

DF_INDEX_TYPE+

Index-Segment Attributes

DF_INDEX_SEGMENT_CASE+

DF_INDEX_SEGMENT_DIRECTION+

DF_INDEX_SEGMENT_FIELD+

* Read-only attribute.

+ Permanent attribute.

Notes

  • Set_attribute may be done only after a structure_start, except for global attributes. See structure_start for more information.


Set_Channel_Position

See Also: File I/O Commands, Append_Output, Direct_Input, Direct_Output, Get_Channel_Position, Sequential File I/O

Purpose

To set the input/output channel position pointer to a position.

Syntax

set_channel_position channelNum to value

ChannelNum is the channel number, 0 through 9.

What It Does

The position pointer for each input/output channel is maintained at the end of the last output, write, or writeln to a file opened by append_output or direct_output, or the end of the last read, read_block, or readln from a file opened by direct_input. Position 0 is before the first byte in the file, while Position 1 is after the last byte, with intermediate positions being the ordinal number of the byte in question. Set_channel_position moves the position pointer for the specified input/output channel to value.

set_channel_position 9 to iCh9Position

In this example, the pointer in input/output Channel 9 is moved to the value of Variable iCh9Position.

If set_channel_position is used to place the append within the existing contents, the existing contents will be overwritten by the written material, byte for byte.

To query the position of the pointer for an input/output channel, use the get_channel_position command.

If value is greater than the size of the file, the file will be extended to the indicated size at the time of the next write.

Notes

  • When a file, field, or image has been opened by the direct_input command, its channel position is 0 (the beginning of the file). After an append_output command, it is at the end of the file. A get_channel_position command immediately after an append_output or set_channel_position to -1 statement returns the size of the file.

  • Caution: Unexpected behavior can result from mixing sequential I/O code that uses channels with code that does not, since seq. I/O code that does not use explicit channel numbers will use the default channel or the last channel explicitly specified. We recommend always explicitly using channel numbers.


Set_Directory

See Also: File_Exist, Make_Directory, Make_Temp_File, Remove_Directory, Valid_Drive

Purpose

To obtain the current working directory for a given drive letter.

Syntax

Set_Directory {sVariable}

What It Does

Set_Directory sets the current working directory in variable sVariable.

The following example shows how to set current directories to the root of the C drive.

Example

Procedure ChangeDirectory

String sDir

// Retrieve the current directory.

Get_Current_Directory To sDir

send Info_Box sDir "Current Directory"

// Set to the root directory of drive C

Set_Directory "C:\"

// Now, get the new current directory.

Get_Current_Directory To sDir

send Info_Box sDir "Current Directory"

End_Procedure // ChangeDirectory


Set_Date_Attribute

See Also: Get_Date_Attribute, SysDate

Purpose

To control the behavior of the date system with regard to the century change at the Year 2000 (Y2K).

Syntax

set_date_attribute attribute to value

Argument Explanation

attribute:

  • SysDate4_State controls whether the sysdate command returns dates with the year in 2 or 4 digits.

  • Date4_State controls whether entries of dates with two-digit years are converted to and from dates with four-digit years on saving to and retrieving from disk respectively.

  • Epoch_Value sets the two-digit year value below which dates are considered to be in the 2000s. All other dates are considered to be in the 1900s.

value:

  • True or False for SysDate4_State and Date4_State

  • 0 through 99 for Epoch_Value

What It Does

Set_date_attribute manages the running program's behavior in entry of dates with two-digit years with regard to the change of century at the Year 2000. With it, you can have your existing applications continue to accept entries of dates with two-digit years while maintaining the internal date values with full four-digit-year precision to support finding, sorting, and other such functions.

set_date_attribute SysDate4_State to True

In this example, sysdate commands in the program will return dates with four-digit years instead of two-digit years.

set_date_attribute Date4_State to True

In this example, all entries of two-digit-year dates will be saved to the disk with four-digit years.

set_date_attribute Epoch_Value to 30

In this example, date entries with two-digit years below 30 will be interpreted internally as dates in the Twenty-first Century. Date entries with two-digit years above 30 will be interpreted as being in the Twentieth Century.

Notes

  • Settings of Epoch_Value have no effect if Date4_State has not been set to True.

  • A set_date_attribute Date4_State statement overrides the value of the UseEpoch registry key and a set_date_attribute Epoch_Value statement overrides the value of the Epoch registry key, but does not change the values of the keys. This command affects only the program that contains it, unlike the registry keys.


Set_Field_Value

See Also: Get_Field_Value, Move

Purpose

To set the value of a field for the current record of a database file.

Syntax

Set_field_value file_num field_num to new_value;

[length data_length [offset data_offset [no_clear_eol]]]

Argument Explanation

file_num The number used to open the file.

field_num The number of the field.

new_value The value to be put into the field.

data_length The length of the data to be used. By default, all data (or as much as can be) is written into the field. A value of 0 causes all data to be written.

data_offset The first byte in the field where data will be written, starting from 0. Default is that data will be written into the field starting at Byte 0.

no_clear_eol Whether the field is cleared before new_value is set. The value can be True, which does not clear the field, or False, which clears. The default value is False.

What It Does

Database files from DBMSes other than DataFlex do not in all cases support the filename.field construct by which DataFlex database files are customarily addressed. This command is capable of addressing such files by their file and field numbers. It can be used in the same manner on DataFlex files as well.

Set_field_value sets the value of a field to new_value, doing any type conversion necessary. The data will be put into the record buffer for the specified file and field, replacing the current record's data, if any.

You can also specify how much of new_value will be put into the field with the data_length parameter, and where to put it (how many bytes from the beginning of the field) with the data_offset parameter.

set_field_value 3 5 to "abcdefgh" length 3 offset 4 True

In the above example, only the first 3 bytes of the string abcdefgh will be put into the fifth field. They will be put in the 5th - 7th positions of the field (remember that the numbering starts at 0). If the field previously contained the string 305.238.0012, it will now contain 305.abc.0012.

set_field_value 3 5 to "abcdefgh" length 3 offset 4

This example behaves just as the previous one, except that no_clear_eol is set to False by default. If the field previously contained 305.238.0012, it will now contain 305.abc.

Notes

  • This command is useful when dealing with text and binary fields. Data can be inserted anywhere within the variable, by using the data_offset parameter.

  • All type conversion is done automatically. For example, if you are setting the value of a Date field, you can use string manipulation:

set_field_value 3 3 to "1/12/1996"

//This example sets the current record of File Number 3,

//Field Number 3 (assumed to be a Date field) to 1/12/1996.

  • When you use the data_offset parameter with a non ASCII type field (e.g., Number or Date), the contents of the field are converted to a string, the data is inserted, and then the final string is converted back to the original type, and put back into the record buffer.

set_field_value 3 3 to "11" length 0 offset 3 True

//If the field currently contains the date 11/12/1996,

//this statement will reset it to 11/11/96.


Set_File_Mod_Time

See Also: Get_File_Mod_Time

Purpose

To set the time/date stamp for a file.

Syntax

Set_File_Mod_Time {file-name} To {date-var} [{hour-var} [{minute-var} [{second-var}]]]

What It Does

Set_file_mod_time sets {file-name}'s date stamp, and as many parts of the time stamp as there are arguments provided after {date-var} in the statement.

Date dFileDate

Integer iFileHour iFileMinute iFileSecond

// set the values of the date and integer variables to the current date and time

sysdate dFileDate iFileHour iFileMinute iFileSecond

Set_File_Mod_Time "Hello.Txt" to dFileDate iFileHour iFileMinute iFileSecond

In this example, the file-modified date and time for Hello.Txt are set to the values in dFileDate, iFileHour, iFileMinute and iFileSecond.

Notes

  • If the file is not found, error 4358 "Rawfile Command Error" is reported.


Set_Relate

See Also: Attach, Open, Relate, Relationships, Table Relationships

Purpose

To establish a temporary runtime relationship between a field in a database table and another field in a database table.

Syntax

set_relate childTable.fieldName to parentTable.fieldName

What It Does

Set_relate changes the parent field to which childTable.fieldName relates.

set_relate OrderHea.Shipto to Ship.ShipTo

In this example, field Shipto in table OrderHea is set to relate to field ShipTo in table Ship.

If the table definition of childTable specifies a relationship of childTable.fieldName to some other parentTable.fieldName, that relationship is replaced by the new one. Set_relate affects a relationship only while a program is running. It does not change the relationship in the table definition on disk. Set_relate relationships do, however, affect finding of records in parentTable on relates, and they affect data brought into childTable on attaches, including the one within the save command.

If a permanent relationship is required to be restored for childTable.fieldName for use after a set_relate command has changed it, an additional set_relate specifying the original relationship is required before the original relationship can be used.

There is no limit to the number of set_relates that may be executed in a single program, nor on the number of set_relates that can be executed on a particular field.

The set_relate command can also be used to clear a relationship by setting the relates-to parent field value to |FN0,0.

set_relate OrderHea.Shipto to |FN0,0 // this will clear the relate

In this example, the relationship between OrderHea and its parent Ship-to table is cleared.

Notes

  • The proper way to establish a relationship between one table.field and another is to specify it in the DataFlex Database Builder. If done in this manner, the relationship is recorded on the disk and remains in force from one session to the next.

  • The zerofile command writes the table definition as it stands in memory to the disk, overwriting the definition originally there. Thus, you should not use zerofile on a table after changing its definition with set_relate unless you actually intend the change to become permanent. Any saves of childTable or saverecords after an attach that are affected by a set_relate will produce permanent changes in the data of childTable.

  • If childTable is not open at the time set_relate is executed, an error will be declared. If either no df_filename is in the filelist matching childTable or none matches parentTable, an error will be declared. If parentTable is not open, no error will be declared.


Set_Transaction_Retry

See Also: Get_Transaction_Retry

Purpose

This command's argument specifies the number of automatic lock retries that will occur when a deadlock is detected. A deadlock is when two or more tasks or users are trying to lock records from one another. Note: The default value is 15.

Syntax

Set_transaction_retry to variable

Argument Explanation

variable The number of automatic retries.


Short

See Also: Declaring Variables, Variable Declaration Commands, Struct, UShort

Purpose

Declares one or more two byte signed integer variables.

Syntax

To declare Short variables

Short {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Short variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Short

Short{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Short command declares integer variables of two bytes in the range -32768 to 32767.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

Short siMyVar

Move 1 To siMyVar

End_Procedure

This example declares a Short variable named siMyVar and initializes it.

Short[] siSeats

This example declares 1 dynamic array variable, named siSeats, containing an undefined number of elements of type Short.

Short[5] siSeats

This example declares 1 static array variable, named siSeats, containing 5 of elements of type Short.

Short[][3] siSeats

This example creates a two-dimensional dynamic array variable named siSeats, containing an undefined number of elements of type Short. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Short variable, you should use the global_variable command to do so.


Show

See Also: Showln, Write, Writeln, Fundamental Data Types, Expression Syntax

Purpose

To display a string of characters to the screen in a special "character-mode" display box that deactivates it when its Close button is pressed. This command is intended for development purposes only; it should not be used in finished applications.

Syntax

show value [... value]

Argument Explanation

value may be of any primitive data type or an expression.

What It Does

Show outputs the value(s) to a special-purpose object displayed at the top left of the screen when the first show or showln command is executed. If the data exceeds the width of the object, the display will wrap onto the object's next physical line. The object remains displayed, and displays successive show and showln commands, until its Close button is pressed.

This command is intended for development purposes only; it should not be used in finished applications.

To show literal information, place it inside single or double quotation marks. To show the contents of a variable, name the variable without quotation marks.

show "Report in Progress"

In this example, the message Report in Progress is displayed.

string sStockNumber

move "128 0045" to sStockNumber

show sStockNumber

In this example, the value of Variable sStockNumber (128 0045) is displayed.

Different data types can be intermingled on a single show command line.

show "The date in one week will be " (dToday +7)

In this example, the legend The date in one week will be will be displayed to the screen, followed by the date seven days after the value of Variable dToday.

Notes

  • Show outputs only to the screen. For output to the printer or a file, use the write and writeln commands.

  • If you want the cursor moved to the beginning of the next line after displaying data on the screen, use the showln command.

  • The show and showln commands display only seven significant digits of values, along with the sign and, for Real values of absolute value greater than 9,999,999 or less than 0.0001, the exponent. Show and showln display Numbers of absolute value up to 99,999,999,999,999, and truncate on the left without reporting an error above that point. To the right of the decimal point, show and showln truncate displays of Numbers to the right of the seventh digit after the decimal point, and for Reals, they round the seventh digit.


Showln

See Also: Show, Write, Writeln, Fundamental Data Types, Expression Syntax

Purpose

To display a line of characters to the screen in a special "character-mode" display box that deactivates when its Close button is pressed. This command is intended for development purposes only; it should not be used in finished applications.

Syntax

showln [value... value]

Argument Explanation

value may be of any primitive data type or an expression.

What It Does

Showln outputs the value of value (if used) to a special-purpose object displayed in a dialog when the first show or showln command is executed. If the total length of data output exceeds the width of the object, the display will wrap, and the cursor will be placed at the next line following the last line on which data is displayed. The dialog remains displayed, and displays successive show and showln commands, until its Close button is pressed.

This command is intended for development purposes only; it should not be used in finished applications.

To showln literal information, place it inside single or double quotation marks. To showln the contents of a variable, name the variable, without quotation marks.

showln "The process has completed."

In this example, the prompt Please Enter Another Customer is displayed.

string sDescription

move "Tank, medium" to sDescription

showln sDescription

In this example, the value of Variable sDescription (Tank, medium) is displayed.

Different data types can be intermingled on a single showln command line.

showln "Total Amount: $ " nTotal

In this example, the legend Total Amount: $ is displayed, followed by the value of Variable nTotal, and the cursor is placed at the beginning of the next line.

Notes

  • Showln outputs only to the screen. For output to the printer or a file, use the writeln command.

  • The show and showln commands display only seven significant digits of values, along with the sign and, for Real values of absolute value greater than 9,999,999 or less than 0.0001, the exponent. Show and showln display Numbers of absolute value up to 99,999,999,999,999, and truncate on the left without reporting an error above that point. To the right of the decimal point, show and showln truncate displays of Numbers to the right of the seventh digit after the decimal point, and for Reals, they round the seventh digit.


Sleep

Purpose

To pause execution of the Visual DataFlex program for a specified time interval.

Syntax

sleep seconds

Argument Explanation

seconds May be of any class, and any type except String.

What It Does

Sleep pauses all activity in the program for the number of seconds specified by the value of seconds.

send bell

move 3 to iDuration

sleep iDuration

In this example, the computer's bell is rung, and 3 is moved to Integer Variable iDuration. The subsequent sleep command pauses program execution for 3 seconds.

Sleep is particularly useful to keep messages and warnings visible on the screen long enough for users to read them. It reads the system clock, and thus is not affected by the speed of the computer the program is being run on.

Notes

  • Sleep cannot be interrupted by user input.

  • Sleep does not offer timing to fractions of a second. If seconds contains a decimal portion, that portion of the value will be truncated when the command is executed.


Sort

See Also: Implementing Callback Functions, Using Database Builder to sort indexes, DF_RUNTIME_PROGRESS_FREQUENCY API Attribute, Call_Driver, Open

Related Topics

Purpose

The Sort command is used to sort or re-build one or more indexes of a data file.

Syntax

sort {file-handle} [{index-list} [{options} [{callback-object}]]]

Argument Explanation

file-handle Is a handle to the data file that you wish to sort. The file must have been opened.

index-list Is a string of numeric characters listing each index that you wish to sort. The index numbers are delimeted in the string using space characters. Each index number must be within the minimum and maximum range of index numbers for the file. If you omit the index-list parameter then every index of the file will be sorted.

options Are the options to use for the sort. Available options are listed below.

callback-object Is a handle to an object that will receive the Callback message during the sort operation. Refer to Implementing Callback Functions for more information.

What it Does

Below are some examples of using the Sort command:

Handle hfOrder

Open "Order" as hfOrder mode DF_EXCLUSIVE

Sort hfOrder

In the above example an order file is opened and a handle to the file placed in the variable hfOrder. The Sort command is invoked to sort every index of this file.

Handle hfEmployee

Open "Employee" as hfEmployee mode DF_EXCLUSIVE

Sort hfEmployee "1 6 12"

In the above example an order file is opened and a handle to the file placed in the variable hfOrder. The Sort command is invoked to sort index numbers 1, 6, and 12 of this file.

Sort Options

The options listed below may have different effects on the sort operation depending upon the database driver in use. The effects listed here are for the DataFlex driver. The {option} parameter of the Sort command can be any one of the following:

DF_SORT_OPTION_NO_DATA_CHECK - the sort operation will not check for bad data in the records. However, duplicate records will always be checked for.

Bad data is defined to be data in a record that does not match the data's field type.

DF_SORT_OPTION_BAD_DATA_FIXUP – the sort operation will fix bad data by replacing bad characters with blanks or zeros as appropriate.

DF_SORT_OPTION_BAD_DATA_FILE – the sort operation will not fix bad data in the database, but logs the bad record(s) in a .BAD file.

DF_SORT_OPTION_BAD_DATA_ABORT - if bad data is encountered, the sort operation is aborted with an error.

DF_SORT_OPTION_DUP_DATA_FILE – the sort operation will leave any duplicate records in the database and also log them to a .BAD file. Note that this will result in corrupted indexes.

Duplicate records are defined to be two or more records with matching key fields in an index.

DF_SORT_OPTION_DUP_DATA_ABORT - if duplicate data is encountered, the sort operation is aborted with an error.

If you want to use more than one of these options, you can ior them in a bitwise expression. Note that some of these options are mutually exclusive.

The default options for sort is to not check for bad data, and to write errors to a .BAD file (DF_SORT_OPTION_NO_DATA_CHECK ior DF_SORT_OPTION_DUP_DATA_FILE).

Below is an example of using the Sort command with options:

Handle hfCustomer

Open "Customer" as hfCustomer mode DF_EXCLUSIVE

Sort hfCustomer "1 3 4" (DF_SORT_OPTION_BAD_DATA_FIXUP ior ;

DF_SORT_OPTION_DUP_DATA_ABORT)

In the above example a customer file is opened and a handle to the file placed in the variable hfCustomer. The Sort command is invoked to sort index numbers 1, 2 & 3. The Sort operation is instructed to fix any bad data that it finds and abort if duplicate records are detected.

Notes

  • Normally the indexes of a data file are maintained on-line and do not need sorting. You would need to sort a file's indexes for one of the following reasons: The indexes have become corrupted, you have modified the structure of an index, you have created a new index, the file has Batch indexes.

  • To use the sort command on a file in a multi-user environment, the file must be opened in exclusive mode (DF_EXCLUSIVE).

  • You do not need to write a DataFlex program to sort data files. The Database Builder tool can be used to sort your data files.

  • A callback function can be implemented to display the progress of long sort operations. Refer to Implementing Callback Functions for further information.

  • The speed of sorting may be improved by increasing the amount of memory allocated to the sort buffer (default: 8Mb). On machines having more than the default amount of memory available, the FLEX_SET_MAX_SORT_BUFFER function of the DataFlex database driver may be used by the Call_Driver command to increase it.


Start_UI

See Also: Object

Purpose

To begin a new user-interface level.

Syntax

start_ui [object]

Argument Explanation

object The name of an existing user-interface object.

What It Does

The start_ui command is the beginning of the non-procedural execution of a DataFlex program. The start_ui command is a loop that waits for keyboard, mouse and timer events, and sends messages based upon the event. The events are always represented as messages, such as key, mouse_down and switch. Each user event is translated into a message.

The start_ui command is typically used once in a program, after all of the program's objects are created.

Each message returns a value, and execution remains in the non-procedural mode until the return value of any of the messages is non-zero. The return value may be generated by the commands function_return, procedure_return or as the result of a built-in message. After the termination of the start_ui command, execution continues with the next command line in the program. Typically this UI loop will not be stopped until the program is terminated.

Object is an optional parameter in which an object to activate prior to the beginning of the start_ui may be named. The command will send activate to the named object, causing it to become the focus. It is suggested that you not use this technique. If you wish to activate an object, explicitly send the activate message.

Send Activate to oMyPanel

Start_Ui

The start_ui command will not allow the desktop to be the focus. If the focus is the desktop prior or at any time during the execution of the start_ui, the loop will terminate.

Execution of the program while in the non-procedural mode is typically under the end user's control. Users will navigate the system by sending keyboard or mouse events to objects through the start_ui event handler.

The start_ui command gets input from the object that is the focus. The input will be either the single-key type or a whole string of information. In either case, the terminating key is sent to the key translation routine to test for any accelerator-key definitions. If a key is defined, then the message on the on_key command line for that key is sent; otherwise the key message is sent to the focus.


String

See Also: Declaring Variables, Variable Declaration Commands, Struct, String Function, String Functions

Purpose

Declares one or more String variables.

Syntax

To declare string variables

string {identifier} [{identifier}]

Where

  • Where {identifier} is the name of a new String variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type String

String{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

The default maximum length of local strings is determined by the default argument size. This maximum length can be changed with the Set_Argument_Size command and queried with the Get_Argument_Size command.

Global strings have a default maximum length of 80 characters. If a different maximum length is desired, ### may be specified literally in the range of 1 to 255, separated from string by a space.

What It Does

String defines variables in memory to contain data other than dates and quantities. String data encompasses any and all printable characters in any order desired.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure RunTest

string sSong sKey sTempo sLyrics

End_Procedure // RunTest

In this example, local string variables sSong, sKey, sTempo and sLyrics are created inside Procedure RunTest.

Literal material which is to be moved to a string variable should be enclosed in quotation marks.

string sEquation

move "(m *(c ^2))" to sEquation

In this example, (m *(c ^2)) is moved to string variable sEquation.

If a statement moves numbers, dates or expressions not enclosed in quotation marks to a String, the value of the variable or expression will be converted to a string and moved to the String variable.

string sEquation

number m c

move 8 to m

move 4 to c

move (m *(c ^2)) to sEquation

In this example, the value of m *(c ^2) (128) is moved to string variable sEquation.

String[] sStudents

This example declares 1 dynamic array variable, named sStudents, containing an undefined number of elements of type string.

String[5] sStudents

This example declares 1 static array variable, named sStudents, containing 5 of elements of type string.

String[][3] sStudents

This example creates a two-dimensional dynamic array variable named sStudents, containing an undefined number of elements of type string. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global string variable, you should use the global_variable command to do so.

  • If you move or append data to a global string variable which exceeds its declared length, the characters in excess of ### will be truncated from the value of the variable. No error will be declared.

string gsShort 5

move "1234567890" to gsShort

After these commands, Variable gsShort will have contents of 12345, having truncated all characters moved to it in excess of its declared length.


Struct

See Also: Declaring Variables: Array Declarations, Struct Type, Struct Variables, Struct Declaration, Struct Variable Assignments, Struct Properties, SizeOfType

Purpose

Declares a new struct data type.

Syntax

Struct {type-name}

{data-type} {member-name}

[{data-type} {member-name}]

[…]

End_Struct

Where:

  • {type-name} is the name of the new struct type. Struct type names must be unique symbols. Visual DataFlex naming convention suggests prefixing struct type names with a lowercase 't'.

  • {data-type} is the data type of individual struct members. This can be any Visual DataFlex simple type (Integer, Number, Real, Boolean, Date, String, Pointer, Handle), an array type, or another struct type.

  • {member-name} is the name assigned to each struct member. Struct member names must be unique within the declared struct. i.e. a struct cannot declare two members with the same name. Member names do not have to be unique outside the struct declaration. You may not use a Visual DataFlex reserved word as a member name.

What It Does

A struct represents a set of elements where each element is called a member. A struct type declaration defines a particular set of elements and associates it with a new type identifier.

Once a struct type is declared it can be used just like any other Visual DataFlex data type. i.e. you may declare and use variables and properties, and you may declare procedure or function parameters and return types of a struct type. For example…

Struct tCreditCard // declares a new struct type

Integer iType

String sName

Integer iNumber

Date dExpires

End_Struct

tCreditCard MyCreditCard // declares a new variable of tCreditCard type

Members of a struct variable are accessed using the member access operator (the dot operator). For example…

Move 0 to MyCreditCard.iType

Move "Joe Bloggs" to MyCreditCard.sName

Move 1234123412341234 to MyCreditCard.iNumber

Date dToday

Sysdate dToday

If (MyCreditCard.dExpires >= dToday) Showln "Expired!"

For each struct type defined, the compiler automatically defines the symbol _struct_{name} where {name} is replaced with the name of the struct type. This can be used at compile time to determine whether a particular struct type has been defined. For example:

#IFDEF _struct_tCreditCard

// Do something special if the tCreditCard struct type has been defined

...

#ENDIF

For more information refer to struct types in the Language Guide.

Examples

The following example demonstrates a nested struct declaration. i.e. a struct type with a member that is also a struct type.

Struct tAddress

String Street

String City

String State

Integer Zip

End_Struct

Struct tCompany

String Name

tAddress PostalAddress

tAddress Location

Integer Phone

End_Struct

The following example declares a struct variable named tStudent, then creates a dynamic array of type tStudent named myStudents. Next, a loop is created that finds Student records and fills the array with the information from the database.

// declare data type tStudent

Struct tStudent

String FirstName

String LastName

String ClassName

Integer LastTestScore

End_Struct

tStudent[] myStudents // dynamic array of tStudent

open Student // open Student table

integer i

for i from 0 to iNumberOfStudents

clear Student

move i to Student.Id

find eq Student by 1 // Id

if (Found) begin

move Student.First to myStudents[i].FirstName

move Student.Last to myStudents[i].LastName

move Student.Class to myStudents[i].ClassName

move Student.TestScore to myStudents[i].LastTestScore

end

loop

Notes

  • You may not declare a member whose type is the same as the struct type being declared (i.e. recursive struct declarations are not allowed).

  • When declaring a static array struct member, the array dimension must be a constant value computed at compile time. For example the declaration below is correct.

Struct tContact

String Company

String[5] ContactNames

Integer Fax

End_Struct

However the following declaration will produce a compile-time error.

Integer icNames

Move 5 to icNames

Struct tContact

String Company

String[icNames] ContactNames

Integer Fax

End_Struct

This restriction does not apply to dynamic or jagged array struct members.

  • To see how to declare arrays of structs, see Declaring Variables: Array Declarations.


Structure_Abort

See Also: Structure_End, Structure_Start

Purpose

To terminate a file structure operation without completing it.

Syntax

Structure_abort fileNum

Argument Explanation

fileNum The variable containing the handle from the corresponding structure_start.

What It Does

This command can be used when constructing error handling routines. The structure_abort command will undo any structure operations that have been done since the last structure_start.

structure_start hFile

// Create an index, and set its attributes. Also process any errors.

create_index hFile at iIndex

on error gosub bad_structure

set_attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex 1 to 2

set_attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex 2 to 4

set_attribute DF_INDEX_SEGMENT_FIELD of hFile iIndex 3 to 0

structure_end hFile

bad_structure:

showln "An error has occurred while creating the index. Program will abort."

structure_abort hFile

abort

return

This example will call the error-handling procedure bad_structure, if any errors occur during the creation of the index.

Notes

  • After a restructure, fileNum contains a file handle rather than the file number it was passed before the restructure. Therefore, an open fileNum statement after a restructure will return an error. It is good practice either to create a separate variable to pass to structure_start for fileNum or to perform restructures in procedures that use a local variable for the parameter.


Structure_Copy

Purpose

Copies the structure of one file to another.

Syntax

Structure_copy from_file_num to to_file_num

Argument Explanation

from_file_num Number of the file which will have its structure copied (the source file).

to_file_num Number of the file to which the structure is to be copied (destination file).

What It Does

This command is similar to load_def. They both copy an existing file structure onto a new one. Structure_copy uses an open database file as the source, while load_def uses a definition (.DEF) file as the source.

Notes

  • If the destination file is an existing file, any existing fields or indexes in the destination file will be deleted before the copy takes place.

  • This command must be used once after every structure_start. Note that it is the destination file that will be the argument to the structure_start command.

  • This command only copies the structure, not existing records.


Structure_End

See Also: Implementing Callback Functions, Structure_Abort, Structure_Start

Purpose

To commit a structure operation, performing restructure on the file data if necessary.

Syntax

Structure_end fileNum [restructureOptions [tempDir [callBackObject]]]

Argument Explanation

fileNum The variable containing the number of the file (or handle returned by structure_start, for a new file) on which a structure_start command has been done.

restructureOptions Options (listed below) which determine how the command behaves.

tempDir A temporary directory to be used when not restructuring in-place. This defaults to the directory where the file being restructured resides.

callBackObject The ID of the object to receive callback during the restructure operation. The first parameter of callback should be a string containing progress information.

What It Does

This command completes a structure block begun with structure_start.

structure_end hFile DF_STRUCTEND_OPT_NONE

This example ends the structure on the File with number hFile, setting no options.

The restructureOptions listed below are peculiar to the DataFlex database driver. The available restructureOptions are as follows:

DF_STRUCTEND_OPT_NONE - sets no options

DF_STRUCTEND_OPT_FORCE - will force a restructure even if one is not needed.

DF_STRUCTEND_OPT_RECOMPRESS - force the rebuilding of the custom compression grid and recompression of data in a file that uses custom compression.

DF_STRUCTEND_OPT_IN_PLACE - this option will perform the restructure in place. The tempDir parameter will be ignored. Note that this option is only a suggestion—if it can be done in place, it will be.

These options can be combined by using the ior operator.

Notes

  • After a restructure, fileNum contains a file handle rather than the file number it was passed before the restructure. Therefore, an open fileNum statement after a restructure will return an error (or open the wrong file). It is good practice either to create a separate variable to pass to structure_start for fileNum or to perform restructures in procedures that use a local variable for the parameter.


Structure_Start

See Also: DF_FILE_REVISION Attribute, Structure_Abort Command, Structure_End Command

Purpose

This command begins creation of a new file or modification of an existing one.

Syntax

structure_start fileNum [driverName]

Argument Explanation

fileNum Must be a variable. It must have a value of 0 if starting a new file, or of the number of a file being modified. In either case, a handle to the structure is written back into fileNum so that attributes of the new structure can be queried.

driverName Name of the driver to use when creating the new file. If this parameter is not supplied, it defaults to the embedded database driver. The names of drivers available from Data Access Worldwide are:

  • DATAFLEX for the embedded database

  • DB2_DRV for the DB2 Connectivity Kit

  • DFBTRDRV for the Pervasive.SQL Connectivity Kit

  • MSSQLDRV for the Microsoft SQL Connectivity Kit

  • ODBC_DRV for the ODBC Connectivity Kit

If you are using drivers provided by other vendors, check the driver documentation for the driver name.

What It Does

This command is used to change a file's physical structure, such as adding, deleting or modifying indexes.

Integer hFile

move 0 to hFile

structure_start hFile "DATAFLEX"

:

// do the file creation/modification

:

structure_end hFile

The above example shows the structure_start/_end block you could use to create a new DataFlex database file.

Notes

  • FileNum must be a variable. After a restructure, fileNum contains a file handle rather than the file number it was passed before the restructure. Therefore, an open fileNum statement after a restructure will return an error. It is good practice either to create a separate variable to pass to structure_start for fileNum or to perform restructures in procedures that use a local variable for the parameter.

  • In order to perform any type of restructuring operation, the header file (.HDR) must be located in the same directory as the .DAT file.

  • DriverName defaults to DATAFLEX when starting a new structure.

  • After restructuring, the file's DF_FILE_REVISION attribute will be that of the revision of DataFlex used when the file was restructured.

  • This command is only for attributes that actually change the structure of the file, such as creating or deleting a field or index. If you are setting an attribute which does not modify the file structure, you should do it outside any structure_start/structure_end block.

  • For example, setting DF_FILE_DISPLAY_NAME does not change the structure of the file. The following sequence will cause an error (Bad file number):

integer hFile

open Test1

move Test1.File_Number to hFile

structure_start hFile

set_attribute DF_FILE_DISPLAY_NAME of hFile to "Employee Data"

structure_end hFile DF_STRUCTEND_OPT_NONE

//This code would work as intended without the structure_start

//and structure_end commands.

integer iFile

open Test1

move Test1.File_Number to iFile

set_attribute DF_FILE_DISPLAY_NAME of iFile to "Employee Data"


Subtotal

See Also: BasicReport class, Print, Output

Purpose

To print the amount currently in the subtotal accumulator of an output window in a report image, and to zero the accumulator. This command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Syntax

subtotal source [to destination] [{option [, ..., option]}]

Argument Explanation

source Must be a window in a DataFlex image.

destination Must be a window in a DataFlex image.

option Must be a print option.

What It Does

Subtotal puts the value of the subtotal accumulator for source to destination and then sets the accumulator to zero.

DataFlex maintains a subtotal accumulator on every numeric window addressed by a print command. Whenever you print to a numeric type window, the value printed is added to the accumulator (in the precision of the window, not of the source value). Subtotal, typically in a section subtotal#, zeroes the accumulator and, optionally, puts the value of the accumulator to a window, again typically in Image subtotal# of a report program.

procedure_section subtotal2

subtotal subtotal3.4

In this example, the value of the accumulator for the fourth window in Image subtotal3 is printed to the first window in Image subtotal2 (if there is an Image subtotal2), relying on the autopage command in the procedure_section subtotal2 statement, and the accumulator is zeroed.

You may address windows with the subtotal command which are themselves filled by subtotal commands. This is the way to get subtotals for subtotal levels above the first one, and it is the way to get a grand total for a report.

You may access the value of any subtotal accumulator by appending a percent sign (%) to the window name of source. So long as you do not move or calc to the accumulator, this does not zero or otherwise affect the value of the accumulator.

move body.8% to cume

In this example, the subtotal accumulator for the eighth window in Image body is moved to Variable cume.

Notes

  • Subtotal moves zero to source% to initialize it for the next subtotal.

  • You cannot address subtotal accumulators through windowindex.

  • Address windows which were themselves subtotalled to, with subtotal commands to get a subtotal for the next-higher subtotal-break level or a grand total.

  • If you print to a subtotalled window with any option on it other than those for the print command (capslock, fill=, float$, signrt, suppress), source% may contain an incorrect value.

  • Use of the subtotal command and subtotal accumulators is not limited to the BasicReport class, but it is limited to sources filled by the print command. It does not work with report classes not derived from BasicReport, such as WinReport and CrystalReport.


Subtract

See Also: Add, Decrement, Increment, Move

Purpose

To perform subtraction.

Syntax

subtract value from variable

What It Does

The subtract command subtracts value from variable. Value can be a constant, a number, or an expression.

The following two lines of code are the same:

move (invoice.amount vendor.total_due) to vendor.total_due

subtract invoice.amount from vendor.total_due

The subtract and add commands are often used in the data-dictionary procedures Update and Backout as follows:

procedure Update

forward send Update

Add invoice.amount to vendor.total_due

end_procedure

procedure Backout

forward send Backout

subtract invoice.amount from vendor.total_due

end_procedure


SysDate

See Also: Time and Date Functions, Sleep

Purpose

To return the current system date, hour, minute, and second.

Syntax

sysdate {dDate} [{iHour} [{iMinute} [{iSecond}]]]

{minute} is allowed only if {hour} is used.

{second} is allowed only if {minute} is used.

What It Does

Sysdate retrieves the date and time from the operating system and moves the date to dDate. If an additional variable is provided, the hour is moved to that variable (iHour). If two additional variables are provided, the minute is moved to the second additional variable (iMinute). If three additional variables are provided, the second is moved to the third additional variable (iSecond).

Sysdate moves the date to date as a Julian number, which can be interpreted correctly by date variables. The hour is moved to the hours in 24-hour format.

Example

date dToday

integer iHr iMin iSec

sysdate dToday iHr iMin iSec

In this example, if it is 1:36:18 PM on January 1, 2004, Visual DataFlex moves 01/01/2004 to dToday 13 to iHr, 36 to iMin, and 18 to iSec.

Notes

  • This command returns the system date with the year in two digits if the date attributes SysDate4_State and Date4_State are both set to False.

  • The SysDate4_State and Date4_State date attributes are defaulted to True in Visual DataFlex applications. You can change the value of these attributes using the Set_Date_Attribute command.

  • The predefined variable Strlen is set to the value of hour and the predefined variable strmark is set to the value of minute.


Time

See Also: Declaring Variables, Variable Declaration Commands, Time and Date Functions, Struct

Purpose

Declares one or more Time variables.

Syntax

To declare Time variables

Time {identifier} […{identifier}]

Where

  • Where {identifier} is a variable name for the new Time variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Time

Time{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The Time command creates a variable of the time type. This is useful for storing times and performing calculations.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

String conversions to time variables are locale specific, so use the date functions, DateSetSecond, DateSetMinute, and DateSetHour to place constant values in a Time variable.

Examples

Procedure Test

Time tmVar

Move (DateSetSecond(tmVar, 30)) To tmVar

Move (DateSetMinute(tmVar, 10)) To tmVar

Move (DateSetHour (tmVar, 10)) To tmVar

End_Procedure

This example declares a Time variable and initializes it to 10:10:30 am.

Time[] tmClassStart

This example declares 1 dynamic array variable, named tmClassStart, containing an undefined number of elements of type Time.

Time[5] tmClassStart

This example declares 1 static array variable, named tmClassStart, containing 5 of elements of type Time.

Time[][3] tmClassStart

This example creates a two-dimensional dynamic array variable named tmClassStart, containing an undefined number of elements of type Time. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Time variable, you should use the global_variable command to do so.


TimeSpan

See Also: Declaring Variables, Variable Declaration Commands, Time and Date Functions, Struct, Date, DateTime, Time

Purpose

Declares one or more TimeSpan variables.

Syntax

To declare TimeSpan variables

TimeSpan {identifier} [… {identifier}]

Where

  • Where {identifier} is a variable name for the new TimeSpan variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type TimeSpan

TimeSpan{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The TimeSpan command declares variables of the TimeSpan type. The purpose of a TimeSpan variable is to store the result of a calculation between DateTime or Time variables. TimeSpan can store a span of time of up to 65535 days.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure Test

TimeSpan tsVar

Move (DateSetSecond(tsVar, 30)) To tsVar

Move (DateSetMinute(tsVar, 10)) To tsVar

Move (DateSetHour(tsVar, 10)) To tsVar

Move (DateSetDay(tsVar, 30)) To tsVar

End_Procedure

This example declares a TimeSpan variable, then initializes its value to 30 days, 10 hours, 10 minutes and 30 seconds.

TimeSpan[] tsIntervals

This example declares 1 dynamic array variable, named tsIntervals, containing an undefined number of elements of type TimeSpan.

TimeSpan[5] tsIntervals

This example declares 1 static array variable, named tsIntervals, containing 5 of elements of type TimeSpan.

TimeSpan[][3] tsIntervals

This example creates a two-dimensional dynamic array variable named tsIntervals, containing an undefined number of elements of type TimeSpan. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • The TimeSpan type is a structured type with the same internal structure as a DateTime. Only Days, Hours, Minutes, and Seconds are stored.

  • TimeSpan types can also be used for declaring variables for storing the difference of two DateTime values, i.e. the subtraction of one DateTime value from another.

  • Use the date functions, DateSetMonth, DateSetDay, DateSetYear, DateSetSecond, DateSetMinute, and DateSetHour to manually place constant values in a TimeSpan variable.

  • If you need to define a global TimeSpan variable, you should use the global_variable command to do so.


UBigInt

See Also: Declaring Variables, Variable Declaration Commands, Struct, Integer, BigInt

Purpose

Declares one or more eight byte unsigned Integer variables.

Syntax

To declare UBigInt variables

UBigInt {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new UBigInt variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type UBigInt

UBigInt{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The UBigInt command declares unsigned integer variables of eight bytes in the range whose range is approximately 0 to (2^64)-1.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

UBigInt ubiMyVar

Move 1000000000000000 To ubiMyVar

End_Procedure

This example declares a UBigInt variable named ubiMyVar and initializes it.

UBigInt[] siLightYears

This example declares 1 dynamic array variable, named siLightYears, containing an undefined number of elements of type UBigInt.

UBigInt[5] siLightYears

This example declares 1 static array variable, named siLightYears, containing 5 of elements of type UBigInt.

UBigInt[][3] siLightYears

This example creates a two-dimensional dynamic array variable named siLightYears, containing an undefined number of elements of type UBigInt. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • You may do calculations with UBigInt variables, but any decimal values that results will be truncated without report of error.

  • Use the Move command to initialize the value of a UBigInt.

  • If you need to define a global UBigInt variable, you should use the global_variable command to do so.


UChar

See Also: Declaring Variables, Variable Declaration Commands, Struct, Char

Purpose

Declares one or more one byte unsigned Integer variables.

Syntax

To declare UChar variables

UChar {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new UChar variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type UChar

UChar{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The UChar command declares unsigned integer variables of one byte in the range 0 to +255.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

UChar ucMyVar

Move 1 To ucMyVar

End_Procedure

This example declares a UChar variable named ucMyVar and initializes its value to 1.

UChar[] ucBoatLength

This example declares 1 dynamic array variable, named ucBoatLength, containing an undefined number of elements of type UChar.

UChar[5] ucBoatLength

This example declares 1 static array variable, named ucBoatLength, containing 5 of elements of type UChar.

UChar[][3] ucBoatLength

This example creates a two-dimensional dynamic array variable named ucBoatLength, containing an undefined number of elements of type UChar. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global UChar variable, you should use the global_variable command to do so.


UInteger

See Also: Declaring Variables, Variable Declaration Commands, Struct, Integer, BigInt, UBigInt

Purpose

Declares one or more four byte unsigned Integer variables.

Syntax

To declare UInteger variables

UInteger {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new UInteger variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type UInteger

UInteger{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The UInteger command declares UInteger variables. Up to 9 UInteger variables may be declared on one command line, with their names separated by spaces.

The UInteger type is a 4 byte unsigned integer.

The valid range of this data type is 0 to 4GB minus 1.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

UInteger uMyVar

Move 1 To uMyVar

End_Procedure

This example declares a UInteger variable named uMyVar and initializes it.

UInteger[] uLightYears

This example declares 1 dynamic array variable, named uLightYears, containing an undefined number of elements of type UInteger.

UInteger[5] uLightYears

This example declares 1 static array variable, named uLightYears, containing 5 of elements of type UInteger.

UInteger[][3] uLightYears

This example creates a two-dimensional dynamic array variable named uLightYears, containing an undefined number of elements of type UInteger. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • You may do calculations with UInteger variables, but any decimal values that results will be truncated without report of error.

  • Use the Move command to initialize the value of a UInteger.

  • If you need to define a global UInteger variable, you should use the global_variable command to do so.


Unload_Driver

See Also: Load_Driver

Purpose

Unloads a loaded database driver.

Syntax

Unload_Driver driverName

Argument Explanation

driverName The name of the database driver.

What It Does

The unload_driver command unloads the specified driver from memory, which may release some system resources. It will also close any open files that use driver driverName.

Note that you do not need to use this command; if your program terminates without unloading drivers, you will not receive an error message.

unload_driver "DATAFLEX"

In this example, all DataFlex files are closed, all server connections are terminated, and the DataFlex driver is deinitialized.

Notes

  • It is not necessary to unload one driver before loading another; multiple drivers can be loaded at the same time.


Unlock

See Also: Transactions and DDOs, Lock, Reread

Purpose

In a multi user environment, to end the locked state of all database files imposed by the lock and reread commands. This command is usually not used when working with Data Dictionaries.

Syntax

unlock

What It Does

Unlock restores database files to a normal (unlocked) state after a lock or a reread command.

reread

increment vendor.counter

save vendor

unlock

An unlock is required after every lock or reread command, and commands requiring keyboard input must not be placed between the lock or reread and its unlock.

Notes

  • Files are unlocked in the reverse of the order of their numbers in the file list.

  • Where a program has more than one lock or reread command in effect at the same time, a separate unlock command must be provided for each such lock and reread.


Until

See Also: Boolean Expressions, Execution Control Commands, For, Loop, Repeat, While, Break, Boolean

Purpose

Establishes a conditional terminator for repeating blocks of code initiated with Repeat or While.

Syntax

repeat

... commands ...

until {expression}

What It Does

The until command sends execution back to the last previous repeat command until the test expression becomes true. When test becomes true, execution proceeds to the command following the until command.

Procedure AddRecs

String sName sAddress sPhone

repeat

readln sName sAddress sPhone // will set SeqEof if end of file

If not (SeqEOF) ;

Send SaveNewRecord sName sAddress sPhone

until (SeqEOF)

End_Procedure

In this example, the loop keeps executing until the end of the sequential file is encountered. This represents normal usage of this command. SeqEOF is the sequential end of file indicator.

Procedure AddRecs

Integer iCount

String sName sAddress sPhone

move 0 to iCount

repeat

readln sName sAddress sPhone

Send SaveNewRecord sName sAddress sPhone

increment iCount

until (iCount > 100)

End_Procedure

In this example, the loop keeps executing until Variable iCount becomes greater than or equal to 100 at which point execution moves to the next statement (end_procedure).

A repeat ... until block will always execute at least once.

You may make until subject to "compound" conditionals.

Procedure AddRecs

Integer iCount

String sName sAddress sPhone

move 0 to iCount

repeat

readln sName sAddress sPhone

If not (SeqEOF) begin

Send SaveNewRecord sName sAddress sPhone

increment iCount

end

until (SeqEOF (iCount > 100))

End_Procedure

SeqEOF is the sequential end of file indicator.

Notes

  • The statements inside blocks are usually indented to make the blocks more readable.

  • A variable or expression with a value of zero (0) is the test equivalent of false. A variable with a value other than zero is the test equivalent of true.

  • Until can also be used with statement blocks that were started with for or while, although such usage is considered to be unusual.


Use

See Also: #INCLUDE

Purpose

To incorporate separate source files into Visual DataFlex programs at compile time either as precompiled modules or as source code.

Syntax

use ["] [{path}]{SourceFileName}[{.ext}]} ["]

Where:

  • {Path} is optional.

  • {Path} can be relative or absolute, but is typically relative to the main source path (e.g. AppSrc in a typical workspace).

  • If {path} contains spaces, the entire path and filename should be enclosed in quotes.

  • {.ext} is not required if the extension is .pkg, but encouraged.

What It Does

Use searches for file {SourceFileName.ext} at the time the program is compiled. If the specified file is found and this file has not already been included in the program, its contents are loaded compiled as though they were part of the program. If the file is not found, an error is reported.

A Use package is only included once in a program. If the same package is used more than once in a program, it is included the first time and subsequent use commands are ignored.

use FinFuncs.pkg

In this example, File FinFuncs.pkg is incorporated into the compiling program if it has not already been included in the program with a previous use command.

Subdirectory Paths

Any source path may contain subdirectory paths. This provides an effective and recommended mechanism for organizing your files.

All subdirectories defined within a source path are considered to be part of the workspace.

Files in these workspace subdirectories must be referenced relative to their location of a main source path. Most often that main source path will be your AppSrc directory.

For example, assume you have the file AccountsEntry.vw located in the following directory structure.

C:\Visual Dataflex Projects

Order Entry

AppSrc

AccountsPayable

Views

AccountsEntry.vw

Reports

AccountsReceivable

Views

Reports

DDSrc

This file is accessed relative to the main source path, AppSrc, and is therefore referenced as follows:

Use AccountsPayable\Views\AcountsEntry.vw

The file will be located relative to your main source paths. In the above example, it will find the file under the AppSrc path (“C:\Visual Dataflex Projects\Order Entry\AppSrc\” + “AccountsPayable\Views\AcountsEntry.vw”).

Note that your use statement must include the entire relative path. The following statement would not find the same file:

Use AccountsEntry.vw // this will not find the same file

In the above example, the file would have to be located directly under a main source path (e.g. …\Appsrc\AccountsEntry.vw).

Subdirectories will be used most often under the AppSrc path. However, subdirectories may be located under and of the main workspace source paths (e.g. AppSrc, DDSrc) and all library source paths. All paths will be searched until the file is found. The path defined as AppSrc is always searched first.

Precompiled Code

Precompiled portions of source code may be incorporated into your programs by pre-compiling the package file and placing a use {SourceFileName.pkg} statement as the first (non comment) line of your program. This saves time in compilation of the overall program. If the precompiled file is missing, or some other non comment statement precedes the use command, the {SourceFileName.pkg} file will be recompiled as usual. This technique is typically used to use your pre-compiled "all entry" package – the package that includes all packages normally used by your application.

The default name for the Visual DataFlex standard "all entry" package for Windows projects is DFAllent.pkg. The default name for the Visual DataFlex standard "all entry" package for web projects is AllWebAppClasses.pkg.

// top of program

use DfAllent.pkg // this can (and should) be precompiled

use FinFuncs.pkg // this cannot be precompiled

Notes

  • Used files may themselves use other files, without limit. If through this or some other occurrence, the same {SourceFileName.ext} file is used more than one time, the file will be included only the first time. This is a key difference between use and the #INCLUDE compiler directive.


UShort

See Also: Declaring Variables, Variable Declaration Commands, Struct, Short

Purpose

Declares one or more two byte unsigned Integer variables.

Syntax

To declare UShort variables

UShort {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new UShort variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type UShort

UShort{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The UShort command declares unsigned integer variables of two bytes in the range 0 to 65535.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

UShort usMyVar

Move 1 To usMyVar

End_Procedure

This example declares a UShort variable named usMyVar and initializes it.

UShort[] usSeats

This example declares 1 dynamic array variable, named usSeats, containing an undefined number of elements of type UShort.

UShort[5] usSeats

This example declares 1 static array variable, named usSeats, containing 5 of elements of type UShort.

UShort[][3] usSeats

This example creates a two-dimensional dynamic array variable named usSeats, containing an undefined number of elements of type UShort. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global UShort variable, you should use the global_variable command to do so.


Valid_Drive

See Also: File_Exist, Get_Directory, Make_Directory, Make_Temp_File, Remove_Directory

Purpose

To check if a given drive letter is valid on the system.

Syntax

valid_drive driveName {integer-variable}

It is optional whether the value of driveName ends in a colon (:) or not.

What It Does

Valid_drive returns zero in {integer-variable} if the given driveName is mapped on the system. This command requires two parameters: the drive letter to check and the variable that will contain the return value.

Integer iDriveValid

Valid_Drive "K:" iDriveValid

In this example, the integer variable iDriveValid will contain 0 (zero) if K: is a valid drive on the operating system. It will contain -1 if it is not.


Variant

See Also: Declaring Variables, Variable Declaration Commands, Struct

Purpose

Declares one or more Variant Integer variables.

Syntax

To declare Variant variables

Variant {identifier} [… {identifier}]

Where

  • Where {identifier} is the name of a new Variant variable.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

To declare array variables of type Variant

Variant{dimension-list} {identifier} […{identifier}]

Where

  • {dimension-list} is a list of one or more array dimensions for the array. A dimension list is declared using square brackets []. One pair of brackets is used to declare each dimension. If the array is static, then you must specify the static size of each dimension between each pair of brackets. i.e. [{size}]. For more information about declaring arrays refer to Array Variable Assignments.

  • {identifier} may be between 1 and 4096 characters in length, must start with a letter, and may not contain spaces. Recommended characters are 0-9, a-z, A-Z and _ (underscore).

What It Does

The variant command declares variant variables. The Variant type is capable of storing values that change type dynamically. Variables of any other type (Integer, String, Date, etc) are statically bound to that type but a variable of the Variant type can assume values of differing types at runtime.

You would use a Variant type in situations where the actual type of your data is unknown at compile-time. This is a common situation when writing applications that use COM objects.

Multiple variables may be declared on one command line, with their names separated from each other by spaces. The only limitation to the number of variables declared on one line is the code line length (1024 characters). Variable names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

Examples

Procedure DoTest

Variant vMyData

Move 1 To vMyData

End_Procedure

This example declares a Variant variable named vMyData and initializes it.

Variant[] vVariantData

This example declares 1 dynamic array variable, named vVariantData, containing an undefined number of elements of type Variant.

Variant[5] vVariantData

This example declares 1 static array variable, named vVariantData, containing 5 of elements of type Variant.

Variant[][3] vVariantData

This example creates a two-dimensional dynamic array variable named vVariantData, containing an undefined number of elements of type Variant. Conceptually, this represents a rectangular array with an undefined number of rows, each of 3 columns.

You can declare dynamic multi-dimensional arrays where all dimensions are dynamic; these are called jagged arrays.

Notes

  • If you need to define a global Variant variable, you should use the global_variable command to do so.


Vconstrain

See Also: Constrain, Constrained_Clear, Constrained_Find, Vfind

Purpose

To provide constraints in programs when field and field parameters must be passed as integers instead of names. This command is usually not used when working with Data Dictionaries.

Syntaxes

vconstrain child_fileNum relates parent_fileNum

vconstrain fileNum as boolExpression

vconstrain fileNum fieldNum mode expression

vconstrain fileNum fieldNum mode fileNum2 fieldNum2

Argument Explanation

child_fileNum The number of the child file.

parent_fileNum The number of the parent file.

fileNum The number of the file to be constrained.

fieldNum The number of the field to be constrained.

boolExpression An expression that is treated as false if it evaluates to zero, true if non zero.

expression Any Visual DataFlex expression.

fileNum2 Number of the file to be constrained to.

fieldNum2 Number of the field to be constrained to.

mode One of the following symbols: lt, le, eq, ne, gt, ge, contains, or matches. Or an expression that evaluates to their symbolic values (contains = 7, matches = 6).

What It Does

Vconstrain works similarly to constrain, except that the constraint's file and field parameters are passed as integers instead of names. This allows you to define these file and field values at runtime instead of compile-time.

This command would most often be used within functions or procedures where the constraint values are passed as integer parameters.

Procedure BuildConstraint integer iFile integer iField

vconstrain iFile iField gt 100

End_Procedure

This is an advanced technique. In most programs you will use the constrain command to build your constraints.

See the constrain command for more information on the different types of constraints.


Vfind

See Also: Find, Found global indicator

Purpose

To provide find commands in programs whose parameters can be changed by users at run time. This command is usually not used when working with Data Dictionaries.

Syntax

vfind file_number index_number mode

Argument Explanation

File_number The number of the file to find records from.

Index_number The number of the index to use to find records.

Mode The find mode. It may be any of the following names or numbers: lt (0), le (1), eq (2), ge (3), or gt (4).

What It Does

The vfind command is useful for programs that need to perform finds where the file, index and mode are to be defined at runtime. Often, this information is provided through parameters passed to a procedure or function.

The found predefined indicator is set to return the result of the find operation.

Procedure WriteRecords integer iFile integer iIndex integer iCount

Integer iCounter

for iCounter from 1 to iCount

vfind iFile iIndex GT

// found indicator can be evaluated within parentheses

If not (Found) ;

Procedure_Return

Send WriteData

Loop

End_Procedure

This example shows how a procedure is passed a file and index to be used for record finding. It also shows how the found indicator is tested after each find to determine if the find was successful.

Notes

  • Like the other database commands, vfind requires the database file it addresses to be open.

  • Records found using the vfind command do not affect records or information within a data dictionary object. If you want your DDO to "know" about a record found with the vfind command you must send the message request_assign to the DDO.


While

See Also: Boolean Expressions, Execution Control Commands, For, Loop, Repeat, Until, Break, Boolean

Purpose

Marks a block of code to be executed repeatedly depending on a condition.

Syntax

while {Boolean-expression}

... commands ...

loop

What It Does

While executes when the expression is true. If the expression is false, execution skips to the first line following the next loop statement. If the expression is true, execution continues with the command following the while command. When loop is executed, execution returns to the while command, and test is evaluated as before.

String sName

Get FirstName to sName

while (sName <> "")

send CreateLetter sName

Get NextName to sName

loop

A while ... loop block will not execute, even the first time, when test is false.

While can be driven by a single Boolean value.

Integer bDone

Move False to bDone

while (not (bDone))

Send GetNextRecord

Move (Customer.Recnum = 0) to bDone

loop

In this example, the while loop will be executed until the value of customer.recnum is zero. The loop will always be executed at least once.

Sample

This sample separates a string into words by separating character groups (words) before and after any space in the text.

Function SplitStringIntoWords String sText returns String[]

String sWord

String[] Words

Integer iWordCount iSpacePos

// Repeat as long as sText contains data

While (sText <> "")

// Find the first/next space

Move (Pos (" ", sText)) To iSpacePos

// If a space was found

If (iSpacePos > 0) Begin

// Take the left part

Move (Left (sText, iSpacePos - 1)) To sWord

// Move the remainder to the text variable

Move (Right (sText, Length (sText) - iSpacePos)) To sText

End

// If no more spaces are found

Else Begin

// Make word equal to the text

Move sText To sWord

// Empty text to stop the loop

Move "" To sText

End

move sWord to Words[iWordCount]

increment iWordCount

Loop

function_return Words

End_Function // SplitStringIntoWords

Procedure OnClick

String sText

String[] Words

Move "Split this text into words" To sText

get SplitStringIntoWords sText to Words

End_Procedure // OnClick

Notes

  • You may exit from the middle of a loop by using break. If your loop is within a function or procedure (which it typically is), it may be terminated with function_return or procedure_return, which also terminate the function or procedure.

  • Statements inside blocks are usually indented to make the blocks more readable.

  • You may terminate a block which begins with while with any loop-terminating command, including loop and until (whose syntax provides for conditional control).

  • You may place While ... Loop blocks inside other looping blocks, up to a limit of 40. And you may freely intermingle the various types of loops. But you may not overlap them—you must end the innermost block first, then the next innermost, and so on.

  • You may make while subject to "compound" conditionals.

Number nWealth

Boolean bRich bSingle

Move True to bRich

Move True to bSingle

while (bRich AND bSingle)

Send Party

Get CurrentWealth to nWealth

Move (nWealth > 500000) to bRich

Get StillSingle to bSingle

loop

In this example, when both Booleans bRich and bSingle are true, the while loop executes the message party. The statuses of bRich and bSingle are checked and reset after each party, and the loop re-executes until either bRich or bSingle is false.

  • A variable or expression with a value of zero (0) is the test equivalent of false. A variable or expression with a value other than zero is the test equivalent of true.

  • You may apply if commands ("conditionals") to both the while statement and the while loop ending statement.

    However, conditionals which you apply before while are outside the loop. Conditionals in this position affect only the first execution of the block, not repeat executions, and they will supersede the while expression evaluation. The expression will be evaluated only when the conditional is true, so the while ... loop block will be executed only when the conditional is true and test is true.

    Conditionals which you apply after the while statement, or to the loop ending statement, are inside the loop. They will be evaluated each time the loop is executed.


Write

See Also: File I/O Commands, Append_Output, Direct_Output, Read, Set_Channel_Position, Writeln, Write_Hex, Channel command component, Sequential File I/O

Purpose

To write the values of one or more variables to a sequential file, device or text field.

Syntax

write [channel channelNum] value [ ... value]

The first value is required, and may be of any type. Additional values may be on the command line, separated by spaces. The number of additional values that can be on the command line is determined by memory, but should be upwards of 9 in any case.

If channel channelNum is omitted, the channel will be that specified in the last append_output, direct_output, output, write, or writeln command in which channel was specified or implied.

What It Does

Write writes data to the output file or device named in the last previous direct_output command. The first write command in the program writes data from the variable(s) named in its argument(s) to the first line of the output file or device until an end of line character is output (usually with a writeln). Subsequent writes write to the same file or device wherever the last write left off.

direct_output "output.txt"

write "Alice In Wonderland"

In this example, the literal string Alice In Wonderland (without quotation marks) is output to File output.txt.

The point in a file at which writing after an append_output command is done can also be changed by use of the set_channel_position command. Write-ing before the end of a file overwrites existing data. There is no insert mode for sequential output.

Write does not add any delimiters, embedders, or other formatting characters to the output, not even spaces between values. You must provide any such characters in arguments to the write command. Suppose, for example, that you wished to output two fields from Database File car, and that the field contents needed to be embedded in quotation marks (") and each field separated from the other by a comma. This command would do so:

write '"' car.make '","' car.model '"'

Here, single quotation marks (') are used to make literal constants out of the combinations of embedding and delimiting characters required in the output. If the value of car.make were CADILLAC, and of car.model, EL DORADO, the output would be:

"CADILLAC","EL DORADO"

In long and numerous commands, and with data which itself contains characters used as embedders, you can write, and read, your commands more easily if you place the required characters into Visual DataFlex variables, and use the variables to insert the required characters into the output.

string sTerm sInter

move '"' to sTerm

move '","' to sInter

write sTerm car.make sInter car.model sTerm

This example would output exactly the same string as the example above.

It is unnecessary ever to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program.

Notes

  • You must supply in the arguments to write all delimiters, embedders, and other formatting characters required by whatever program is to use the output. Refer to the documentation for the target program for its requirements, and how to adapt the requirements of your particular data to those requirements. Common data formats which you can emulate with write are ASCII, sequential, comma-delimited, mailmerge, and line-delimited.

  • If you want to output a new line after sending data for the last argument on the command line, use the writeln command.

  • Do not confuse write with the print command. Write sends data to a non-DataFlex file or device. Print moves data to a window.

  • The output file or device must be opened with the direct_output or append_output command.


Write_Hex

See Also: File I/O Commands, Write, WriteLn, Read

Purpose

To write binary data as two-byte hexadecimal numbers.

Syntax

write_hex [channel channelNum] value [ ... value]

Argument Explanation

channelNum A value of any class or type in the range 0 to 9, representing the output channel to use. This only needs to be given when output is going to multiple places.

value The data to be written.

What It Does

This command works similarly to the write command. Use write_hex to output hexadecimal digits, and write to print text normally.

Write_hex writes hexadecimal values for the characters in value to the file or device named in the last direct_output command. Write_hex can be used in conjuction with read_hex to convert data between binary and text formats.

direct_output "File.txt"

write_hex "ABCD EFGH"

This example will output the following text to FILE.TXT:

414243442045464748

The hex code for "A" (in ASCII) is 41, "B" is 42, "C" is 43, etc.


Writeln

See Also: File I/O Commands, Append_Output, Direct_Output, Readln, Set_Channel_Position, Write, Write_Hex, Channel command component, Sequential File I/O

Purpose

To write the values of one or more variables to a sequential file, device, or text field as a line of data.

Syntax

writeln [channel channelNum] [value ... value]

Value is optional, and may be of any type. Additional values may be on the command line, separated by spaces, without limit.

If channel channelNum is omitted, the channel will be that specified in the last append_output, direct_output, output, write, or writeln command in which channel was specified or implied.

What It Does

Writeln writes data from values, if any, to the output data file or device named in the last direct_output command, and then outputs an end of line character. Writeln writes to the output file or device at whatever point the preceding writeln or write command left off.

direct_output "inventry.txt"

number nTtankLevel

move 1250 to nTtankLevel

writeln nTankLevel

In this example, the value 1250 is output to Output File INVENTRY.TXT. The point in a file at which writing after an append_output command is done can also be changed by use of the set_channel_position command. Writeln-ing before the end of a file overwrites existing data. There is no insert mode for sequential output.

Writeln does not add any delimiters, embedders, or other formatting characters to the output, not even spaces between variables. You must provide any such characters in arguments to the writeln command. Suppose, for example, that you wished to output two fields from Database File car, and that the field contents needed to be embedded in quotation marks (") and each field separated from the other by a comma. This command would do so, adding an end of line character at the end:

writeln channel 2 '"' car.make '","' car.model '"'

Here, single quotation marks (') are used to make literal constants out of the combinations of embedding and delimiting characters required in the output. If the value of car.make were CADILLAC, and of car.model, EL DORADO, the output would be:

"CADILLAC","EL DORADO"

In long and numerous commands, and with data which itself contains characters used as embedders, you can write, and read, your commands more easily if you place the required characters into DataFlex variables, and use the variables to insert the required characters into the output.

string sTerm sInter

move '"' to sTerm

move '","' to sInter

writeln sTerm car.make sInter car.model sTerm

This example would output exactly the same string as the example above.

It is unnecessary ever to use the channel feature unless at some point you need more than one output destination, or more than one input source, at the same time in your program.

Notes

  • You must supply in the arguments to writeln all delimiters, embedders, and other formatting characters required by whatever program is to use the output. Refer to the documentation for the target program for its requirements, and how to adapt the requirements of your particular data to those requirements. Common data formats which you can emulate with writeln are ASCII, sequential, comma-delimited, mailmerge, line-delimited, printable, source, and text.

  • When used with no argument, writeln outputs only an end-of-line. If you find it convenient, you may intermingle write and writeln commands.

// These commands:

write sString

write nNumber

write dDate

writeln

// are exactly the same as this command:

writeln sString nNumber dDate

// and the same as these commands:

write sString

write nNumber

writeln dDate

  • Do not confuse writeln with the print command. Writeln sends data to a non-DataFlex file or device. Print moves data to an image window.

  • The output file or device must be opened with the direct_output or append_output command.


ZeroFile

See Also: Erasefile

Purpose

To erase all data from a database file, leaving the empty file definition in place.

Syntax

zerofile df_file

What It Does

Zerofile erases all data from df_file (provided it is open) while maintaining the file definition unchanged. After a zerofile command, the number of records in df_file is zero.

zerofile customer

In this example, all record data in Database File customer is deleted. The file definition of customer remains intact for future use.

Once a zerofile command has been executed, the only way to restore the data is from a backup copy of the file.

Notes

  • Be extremely careful in using this command. It is very powerful, and if used improperly could destroy valuable data.

  • You should never use the zerofile command in a multi-user situation, when another user may have the same file open. Doing so could result in a corrupted file.

  • Zerofile is useful in removing experimental or sample data from database files, and for reinitializing a database for a new period. However, because it erases all data, zerofile does not allow balances to be carried forward to the next period in df_file, nor any other data. Again, use the command with care.

  • Where you wish to actually delete a file, use the erasefile command. Zerofile merely removes all data from a database file, rather than erasing the file.

  • You can pass the file's logical name or file number (in the file list) to the zerofile command.

  • This command should not be used within a transaction; it will cause an error. A transaction starts with a begin_transaction command and ends with end_transaction.


Zerostring

See Also: variable, Put_String, Type

Purpose

To create a string of null (ASCII value zero) characters.

Syntax

zerostring length to variable

Argument Explanation

length The number of characters to clear.

variable The destination variable to be cleared.

What It Does

Zerostring writes length zeroes (0) into variable.

Zerostring 25 to sValue

The above command is functionally the same as:

Move (Repeat(character(0), 25)) to sValue

This command can be used to zero fill string that must be filled to a fixed length before they are passed to a DLL function.

ZeroString (icTextLen +1) To sHelp // add 1 for Cstring terminator

GetAddress of sHelp To lpsHelp

Send Windows_Message Of hoEditor CMM_GETWORD lpsCmPosition lpsHelp


Compiler Directives

This section describes each of the Visual DataFlex compiler directives. They are listed alphabetically. Compiler directives are used to control the features of the Visual DataFlex compiler. The compiler directives can perform such tasks as conditional compilation, switch compiler options, create new command macros, and so on.

Unlike other DataFlex commands, compiler directives (all begin with a pound [#] sign) must be written in CAPITAL LETTERS. If they contain any lowercase letters, they will not work.


#CHECK

Purpose

#CHECK checks the validity of an identifier against a list of type-checking characters.

Syntax

#CHECK {symbol} {type-list}

Argument Explanation

symbol Is the identifier that you wish the compiler to check.

type-list Is the list of type-checking characters that the {symbol} is tested against (see below).

What It Does

You may check the type and class of a symbol with the #CHECK command. #CHECK will generate an error message if the type or class of the symbol is not in the {type-list}.

The #CHECK is intended for type error checking. Both use negative logic: an error will be generated if the type or class of {symbol} matches one of the type check characters the {type-list} (see Symbol-Checking Characters below).

Symbol Checking Characters

Types

Character
Meaning

S

String

N

Number

D

Date

I

Integer

E

Expression

#

Indicator (obsolete)

X

Not an indicator (obsolete)

O

Group options {}

B

Group indicators {} (obsolete)

L

Label

Classes

Character
Meaning

c

Constant

f

File element

w

Window (obsolete)

v

Variable

G

Group {options} or {indicators}

Literal Content

Character
Meaning

"" any characters
in quotes

An error will be generated if the value of the
argument does not match one of the strings
in the quotes

Others

Character
Meaning

t

Error if typed (defined)

U

Error if untyped

R

Argument required

.

No more arguments

%

Special: Changes constant number to constant integer

$

Special: Changes all windows to type string

&

Special: For macros that don't call other macros

*These characters are case sensitive. They work only when CAPITALIZED.

An example of the #CHECK compiler directive is:

#CHECK iCount LGFCU

This example would declare a compile-time error if the symbol iCount is a label, group, file element, constant or is untyped.

The order of the type check characters has no significance.

Examples of using macros can be found in many of the package files.

Internal Typing of Symbols

The following information is intended for those interested in the internal workings of the macro processor and is not required to use DataFlex. These symbols are placed in the compiled program file.

Each symbol, whether constant, window or file, is #REPLACEd from its symbolic name in the program source code to one which is meaningful to the DataFlex runtime system. These symbols can be identified by a vertical bar "|" in the first character of the replacement symbol. The next two characters represent the class and type of the symbol. If the symbol is a constant, the final characters are its value. If it is a field, the final characters are the file and field numbers, separated by a comma. If it is a window, the final characters are its sequential number among the windows of the program.

  • |CN0 means CONSTANT, NUMBER, Value 0

  • |WS2 means WINDOW, STRING, Window Number 2

  • |CI1 means CONSTANT, INTEGER, Value 1

  • |CS'USA' means CONSTANT, STRING, Value USA

  • |WN3 means WINDOW, NUMERIC, Window Number 3

  • |FD2,1 means FIELD, DATE, File 2, Field 1

The characters used to identify type and class in symbols are the same as those shown above in the table of Symbol-Checking Characters for types and classes. Symbols can be addressed directly in source code, but except for the occasions described below, there is seldom need to do so.


#CHKSUB

Syntax

#CHKSUB {subsystem#} {version#}

What It Does

If a #CHKSUB directive is encountered, the compiler verifies that the version# is the same as the compiler's own version for the specified subsystem. If not, an error is generated, but compilation can be continued.

Not everything can be automatically checked by the compatibility system. For example, the compiler might find old package source due to an incorrect DFPATH. If you compile outdated code with a new compiler, it will run with a new runtime even if the code itself is obsolete. To help guard against this, there is a compiler directive you can use called #CHKSUB.


#COMMAND

Purpose

#COMMAND Alows you to define a new commands using sequences of existing DataFlex commands.

Syntax

#COMMAND {new-command} [{symbol-list1 … symbol-list9}]

directive line

:

directive line

#ENDCOMMAND

Argument Explanation

new-command Is the name assigned to the new command macro you have created. The identifier that you assign to the new command must not be a DataFlex reserved word.

symbol-list Each command may optionally be followed by, up to, nine lists of symbols. Each list corresponds to one of up to nine possible arguments that can be passed to the new command. The symbols are used to perform error type checking on the arguments during compilation. Symbol checking is more thoroughly explained in and after the explanation of the #CHECK compiler directive, which uses the same syntax. Do not type the [] brackets; they only signify that the command component is optional.

What It Does

When used in a program your new command will look just like any other command in DataFlex, but it will in fact cause execution of a sequence of other DataFlex commands. The command must be defined before it is first used in the program.

#COMMAND Sign_On

Showln

Showln 'EXAMPLE PROGRAM'

Showln '(c) 1999 DATA ACCESS CORP'

Showln

#ENDCOMMAND

This macro defines a new command, Sign_On. Whenever it is used in a program, the four indented command lines above will be executed in its place (it displays the two-line banner in quotation marks, surrounded by a couple of blank lines).

In the next example, suppose that we wish to be able to insert the name of the program (instead of the hard-coded legend EXAMPLE PROGRAM shown above) as an argument to the Sign_On command. The syntax for an argument is an exclamation point with an integer between 1 and 9 after it. The command model will then textually substitute the first argument written after the command into the command model wherever a !1 appears in it, the second argument (if any) wherever !2 appears, and so on).

#COMMAND Sign_On R .

Showln

Showln !1

Showln '(C) 1999 DATA ACCESS CORP.'

Showln

#ENDCOMMAND

The !1 used above would be replaced by the first argument following the use of Sign_On. A use of this new command macro could be:

Sign_On 'ACCOUNTS PAYABLE PROGRAM'

ACCOUNTS PAYABLE PROGRAM would then be substituted at the !1 position when the command was compiled. Nine arguments can be replaced in this manner (i.e. !1 !2 !3....!9). The symbol !0 is the total number of arguments that have been passed to a macro command.

The 'R' symbol in the #COMMAND definition specifies that one argument must be passed to the Sign_On command when it is used. The '.' symbol specifies that no further arguments may follow.

Notes

  • CAUTION: Macros are not routines. A macro used five times in a source program will be expanded each time, so frequent use of a large macro can result in excessive memory consumed by the executable program. Generally, larger macros can be more simply installed and used within less file space if written as procedures or functions.

  • The macro is a powerful tool. Replacements can be made anywhere within the expansion and a macro can even call other macros.


#COMPAT

Purpose

The #COMPAT directive sets the compile-time revision Integer !@.

Syntax

#COMPAT {revision-number}

What It Does

Compiled DataFlex programs files are automatically marked with a revision Integer. The default value of the integer is the revision of DataFlex under which the program was compiled. Programmers may wish to make up their own revision systems. The #COMPAT directive is used to set the value of the revision integer in the program file and the value of the compile-time Integer, !@.

#COMPAT and the compile-time directive differ from the x compile time option in that they can be placed in program code so that a given set of source code actually sets its own compatibility mode. Although the usual place to do this would be at the top of a program, the compatibility mode can in fact be changed in the middle of a program as well, as many times as desired.


#DATA

Purpose

Prepares the compiler to accept the arguments of an object declaration.

Syntax

#DATA

What It Does

The object system stores arguments to the object commands in the data area. The #DATA command prepares the compiler to accept a new set of arguments for the current object command that is being compiled. The address of the beginning of the argument is then stored in the command line argument |VL.


#DPUSH

Purpose

Pushes a symbol onto the data compile-time stack.

Syntax

#DPUSH {symbol}

What It Does

The #DPUSH directive will push a new argument into the data area. These arguments are used in the object system.

Example

#DPUSH !2


#ENTOPT

What It Does

Created and used by the compiler to evaluate the options of the last previous entry_item statement. The format of entry_item format options is similar to that of the standard entry command, but the information is placed in the object's data area, to be used at run time to set the options for the item.

#ENTOPT vendor.name {forceput, ientry =msg_joe}


#ENDHEADER

See Also: #HEADER, Precompiling

Purpose

To terminate a precompiled program-header section.

Syntax

#HEADER

source code to be precompiled

#ENDHEADER

What It Does

#HEADER … #ENDHEADER compiler directives: These directives mark a block of code for pre-compilation. You may not use a #HEADER … #ENDHEADER pair to split any compound statement (such as an object declaration).

An example of a program with a block marked for pre-compilation is shown below:

#HEADER

Use Windows.pkg

Use DFPanel.pkg

#ENDHEADER

A program may have no more than one #HEADER ... #ENDHEADER pair.

Notes

  • #ENDHEADER must be spelled in capital letters, as shown, contrary to the general rule of DataFlex that keywords are not case-sensitive.

  • #HEADER must be the first non-comment in a program. The compiler will ignore any pre-compiled block that does not begin at the top of the program.

  • You must set the pre-compile switch in the compiler to pre-compile the marked block. Refer to the compiler option flags section of the help.


#ERROR

Purpose

The #ERROR directive declares a compile time error.

Syntax

#ERROR {error-number} {error-message}

What It Does

The #ERROR command allows for user-supplied compile time errors to be generated. The #ERROR command takes two arguments, the {error-number}, and the {error-message}. The error number may be any number, but a special error number, 999, will abort the compiler immediately. The error text will be displayed like any other standard compile time error message.

#IF (!0<5)

#ERROR 200 The location parameter is required

#ENDIF


#FREF

Purpose

The #FREF directive instructs the compiler how to resolve a, so far, undefined symbol. The undefined symbol must be defined later in the program.

Syntax

#FREF {symbol1} {symbol2}

What It Does

The forward reference command #FREF takes two arguments separated by a space. The second argument is the symbol whose value should be moved to the first argument at the time in compilation when the first (forward referenced) symbol is defined. Used primarily for passing the line numbers of internal labels to the forward reference table of programs.

#FREF END$!r !a will fix up the symbol END$!r (an internal label) with the number of the program line on which END$!r is eventually defined. If END$!r is never defined in the program, Error 157 Forward reference not resolved is declared at the end of compilation.


#FREG

What It Does

Register a function. The #FREG command will register a function and its arguments to the compiler. All functions are registered in this way in order to check for the proper type and number of parameters.

#FREG get_my_name integer some_int returns string


#HEADER

See Also: Use Command, #ENDHEADER, Pre-Compilation

Purpose

To save time in program development and recompilation by designating the initial portion of a program's source code for precompilation.

Syntax

#HEADER

source code to be precompiled

#ENDHEADER

What It Does

Most programs are composed of a "static" part that does not usually change and a dynamic part, that is recompiled often. Multiple use statements are a common example of the first part of a program which may be considered static. This static portion of your program is called the "header".

You may define the header of your program and compile that portion only once. The header will be automatically included, precompiled, when you compile the dynamic portion of your program. This technique can significantly reduce the time it takes to recompile a large program.

A header of your program can be designated with the #HEADER and #ENDHEADER directives. When you compile a program with these commands with the -P compiler option, only the header will be compiled and a progname.FLP and progname.PKI file will be produced.

When you compile the program without the -P option, the .FLP will be included and the header will not be recompiled. Only the portion of your program after the #ENDHEADER will be compiled.

As portions of your program become complete and tested, you may move them into the header and recompile the header. It is your responsibility to make sure that the header is recompiled (with P) every time you change it.

#HEADER

use Dfallent.pkg

use vtable.pkg

use mypackage.pkg

#ENDHEADER

open persons

:

In this example, a program begins with a precompiled portion made up of three use commands. The portion of the program to recompile with every compilation begins with the open command following the #ENDHEADER directive.

#ENDHEADER must be used to terminate the precompiled section. A program may have no more than one #HEADER ... #ENDHEADER pair.

Notes

  • #HEADER must be spelled in capital letters, as shown.

  • Precompilation can also be accomplished through use of the use command, but the precompiled material in that case must be in a separate file.

  • Forward references are allowed from the first program (or header) to the second.

  • All symbols, variables, windows, objects, and files are carried forward from the first program to the second, just as if the programs were compiled together.

  • The header must compile without errors before it can be used.

  • Command blocks and object definitions may not span the #ENDHEADER directive. In general, anything you begin in the first part you must complete in the first part.

  • Both the files .FLP and .PKI must be accessible to include progname precompiled. If progname.FLP or progname.PKI cannot be found, the header will be recompiled and the #HEADER directive will have no effect.

  • The #HEADER directive must be the first line of the program (excluding comments). If you have both a use and #HEADER, the use command would go after the #HEADER.


#INCLUDE

See Also: Use

Purpose

To incorporate into a program at compile time, program source code from another source-code file.

Syntax

#INCLUDE path\filename.ext

What It Does

You can keep common macros and routines in files external to your program's source-code file and include their content in your program at compile time with the #INCLUDE command.

The entire file filename.ext will be included in the compilation process at the point(s) of the #INCLUDE(s). One #INCLUDEd file can #INCLUDE yet another file. #INCLUDEd files should be source (ASCII) format, not separately precompiled. The lines of the #INCLUDEd file(s) will not be displayed during compilation.

If a particular #INCLUDE path\filename.ext statement is repeated in a program, filename.ext will be included again. This contrasts with the use command, which will ignore any use statement that names a file that has already been included through a previous use statement.

Notes

  • #INCLUDE must be spelled in capital letters.


#IF

Purpose

The #IF command allows you to specify conditionally compiled code based on some expression that is evaluated at compile-time.

Syntax

#IF {expression}

{code to compile if expression true}

#ELSE

{code to compile if expression false}

#ENDIF

Argument Explanation

expression Is any valid Boolean compile-time expression (see below).

Compile-Time Boolean Expressions Syntax

Compile-time Boolean expressions have a very simple syntax as follows:

( {operand} {Boolean-operator} {operand} )

Argument Explanation

operand Is one of:

  • An Integer token, e.g., 1, 2, |CI100.

  • A hex token, e.g., $40000000.

  • An Integer compile-time variable, !z.

  • Command macro symbol !0 (number of arguments).

  • Another Boolean expression, e.g., (!q > 100).

operator Is one of >, <, =.

What It Does

If expression has a value other than zero, the true command lines will be included in the compiled program. Otherwise, the false command lines will be included. For example:

#COMMAND Show_Arguments

#IF (!0>0)

Show 'There are !0 arguments'

#ELSE

Show 'No arguments'

#ENDIF

#ENDCOMMAND

This will generate only one compiled line, the first show, if there are any arguments and the second show if there are not.

There must be an #ENDIF for every #IF, but the #ELSE is optional.

If we wanted to have debugging statements in our program that could be included or excluded based on a single statement, we could use an integer variable g that would be true (1) for debug mode and false (0) for runtime mode.

#SET G$ TRUE

(statements generating value for giTestvar)

#IF !g

show 'TEST VARIABLE=' giTestvar

#ENDIF

This example shows the debug flag initialized to true, followed by program command lines which, among other things, generate a value for variable giTestvar Where the debug flag was set true, then, the value of giTestvar will be displayed after the legend TEST VARIABLE=. When the program is debugged, the #SET line can be rewritten to set the debug flag false, and when the file is compiled, the lines triggering debugging statements will not be included.


#IFDEF

See Also: Define Command, #IFNDEF

Purpose

The #IFDEF command allows you to specify conditionally compiled code based on whether a symbol has been typed (or defined). This compiler directive does the opposite of the #IFNDEF compiler directive.

Syntax

#IFDEF {symbol}

{code to compile if symbol is typed}

#ELSE

{code to compile if symbol is not typed}

#ENDIF

What It Does

Any symbolic name which has a valid ICODE equivalent in the compiler's substitution table is said to be typed, any symbolic name which has no ICODE equivalent is said to be untyped.

Any file element, label or variable which you have declared is considered to be typed, and would test true when given as an argument to #IFDEF. On the other hand, a symbolic name such as RAZZO is meaningless to the compiler if it has not been declared to be a variable, label, or some other type of data, and would cause the #IFDEF to test false.


#IFNDEF

See Also

Purpose

The #IFNDEF command allows you to specify conditionally compiled code based on whether a symbol has not been typed (or defined). This compiler directive does the opposite of the #IFDEF compiler directive.

Syntax

#IFNDEF {symbol}

{code to compile if symbol is not typed}

#ELSE

{code to compile if symbol is typed}

#ENDIF

What It Does

Any symbolic name which has a valid ICODE equivalent in the compiler's substitution table is said to be typed, any symbolic name which has no ICODE equivalent is said to be untyped.

Any file element, label or variable which you have declared is considered to be typed, and would test false when given as an argument to #IFNDEF. On the other hand, a symbolic name such as RAZZO is meaningless to the compiler if it has not been declared to be a variable, label, or some other type of data, and would cause the #IFNDEF to test true.

Most often, the #IFNDEF compiler directive is used to conditionally exclude code from compilation in scenarios where code is shared between Windows and Web-based applications. Web-based applications cannot use Windows-based messages and classes, such as MessageBoxes.

In this case, the programmer would check for the existence of the IS$WebApp symbol, which will test false if compiled with Web-based packages, such as AllWebAppClasses.pkg. If compiling a Windows-based application, using a precompiled package such as DfAllEnt.pkg or Windows.pkg, this symbol would not be defined.

#IFNDEF IS$WebApp

send Stop_Box "The value you have typed is too large"

#ENDIF

This example compiles the line of code calling the Stop_Box Windows MessageBox message only if IS$WebApp is defined.


#IFCLASS

See Also: Define Command, #IFDEF

Purpose

The #IFCLASS command allows you to specify conditionally compiled code based the class of a symbol.

Syntax

#IFCLASS {symbol} {class-list}

{code to compile if symbol is in the class-list}

#ELSE

{code to compile if symbol is not in the class-list }

#ENDIF

Argument Explanation

symbol Is the identifier that you wish the compiler to check. It can be any valid token or identifier.

class-list Is the list of class-checking characters that the {symbol} is tested against (see below).

What It Does

Compiles the true code if the class of {symbol} is in the {type-list} otherwise it compiles the false code.

Classes

Character
Meaning

c

Constant

f

File element

w

Window (obsolete)

v

Variable

G

Group {options} or {indicators}


#IFSAME

Purpose

The #IFSAME command allows you to specify conditionally compiled code based on the comparison of a symbol to one or more literal values at compile-time.

Syntax

#IFSAME {symbol} {value1} [{value2 ... valueN}]

{code to compile if symbol matches one of the values}

#ELSE

{code to compile if symbol matches one of the values}

#ENDIF

What It Does

#IFSAME checks the value of the directive's first argument and compares it with the values that follow it on the directive line.

Each value should be separated by spaces from the next.

#IFSAME !2 Group "OBJECT"

In this example, the second argument passed to the host macro is checked to see whether its value matches that of either String variable Group or the string constant OBJECT. If the argument is found in the check list, the condition will evaluate to true and commands following #IFSAME will be compiled until the next #ELSE or #ENDIF.


#IFSUB

Purpose

The #IFSUB command allows you to specify conditionally compiled code based on whether a symbol is substitutable or not.

Syntax

#IFSUB {symbol}

{code to compile if true}

#ELSE

{code to compile if false}

#ENDIF

What It Does

Compiles the true code if the argument is the name of a substitutable symbol otherwise it compiles the false code.


#IFTYPE

Purpose

The #IFTYPE command allows you to specify conditionally compiled code based the type of a symbol.

Syntax

#IFTYPE {symbol} {type-list}

{code to compile if symbol is in the type-list}

#ELSE

{code to compile if symbol is not in the type-list }

#ENDIF

Argument Explanation

symbol Is the identifier that you wish the compiler to check. It can be any valid token or identifier.

type-list Is the list of type-checking characters that the {symbol} is tested against (see below).

What It Does

Compiles the true code if the class of {symbol} is in the {type-list} otherwise it compiles the false code.

Types

Character
Meaning

S

String

N

Number

D

Date

I

Integer

E

Expression

#

Indicator (obsolete)

X

Not an indicator (obsolete)

O

Group options {}

B

Group indicators {} (obsolete)

L

Label


#IF2TYPE

Purpose

The #IF2TYPE command works in the same way as the #IFTYPE command except that two symbols are tested together instead of just one.

Syntax

#IF2TYPE {symbol1} {symbol2} {type-list}

{code to compile if both symbols are in the type-list}

#ELSE

{code to compile if neither symbol is in the type-list}

#ENDIF


#NOISY

Purpose

The #NOISY directive specifies the compiler verbosity level.

Syntax

#NOISY {level}

What It Does

This directive is equivalent to the use of the V compiler option on the compiler command line, but permits variation of the verbosity level of the compiler from one point in the program to another. As many #NOISY directives may be used in a program as desired. It is used with Integers 0, 1, 2, or 99 following it, equivalent to 0, 1, 2, and 3 of the V compiler option.

#NOISY 0 will cause your original source code statements to display, together with the line number to which each has been assigned in the compiled program.

#NOISY 1 will include all source code lines from the main file and all lines from files being included by use of the use command or #INCLUDE directive. This output is useful when compiling packages. Packages often include other packages and if an error occurs in an included package, this level of output will aid in identification of the line number reported.

#NOISY 2 displays all source code, all included files, plus expansion of all macros.

#NOISY 99 displays all source code, all included files, all expansion of macros, and all substitutions.


#NUM

Purpose

Sets space aside in the static data area for a Number or Date runtime variable. Reserves 12 bytes per variable.

Syntax

#NUM V$


#POP

Purpose

Pops a value off the primary compile-time stack.

Syntax

#POP {compile-time-variable}

What It Does

Pops a value off the primary compile-time stack into a compile-time variable. The primary compile-time stack counter is decremented.

Example

#POP S$

In the above example the value at the top of the primary compile-time stack is pushed into the S$ compile-time variable.


#PUSH

Purpose

Pushes a compile-time variable onto the primary compile-time stack.

Syntax

#PUSH {compile-time-variable}

What It Does

Puts a value on top of the compile time stack and increments the compile time stack counter.

Example

#PUSH !r

In the above example the value of the R$ compile-time variable is pushed onto the primary compile-time stack.


#REAL

Purpose

Sets space aside in the static data area for a Real runtime variable. Reserves 8 bytes per variable.

Syntax

#REAL V$


#SET

Purpose

Assigns a value to an Integer compile-time variable.

Syntax

#SET {variable-identifier}$ {expression}

Argument Explanation

variable-identifier This is the identifier of the compile-time variable. The variable-identifier can be one of A…Z or ZA…ZZ and must be followed by a $ symbol.

expression This is an expression that is evaluated at compile-time and assigned to the compile-time variable.

What It Does

Macros and program files can use and evaluate integer numbers and expressions at compile time which are generally used for assigning sequential numbers to labels or compile-time variables. There are 52 such integer variables (named A...Z and ZA…ZZ).

The case of the compile-time variable has special meaning. If an upper case letter is used, the value of the variable is incremented before use; if a lower case letter is used, the value will remain unchanged. The compile-time variables are referenced with an exclamation point (!) preceding its letter. The value of the variable in text form is substituted for the !x in the line output.

The value of any Integer compile-time variable can be set with the #SET command.

Expression can be any Integer expression that can be evaluated at compile time, and it can itself contain Integer compile-time variables. Expression should be embedded in parentheses.

The following example means #SET Integer Variable F to the value of Integer Variable r minus one. Since r is lower case, it will not be automatically incremented.

#SET F$ (!r - 1)

Many of the compile-time variables are reserved for use by the DataFlex language. The following tables list each variable and a description of its use in the DataFlex macro language:

Variable | Usage
!A | Next line number
!B | reserved
!C | Next indicator number
!D | Next integer number
!E | Autopage window number
!F | Autopage page number
!G ~ !M | unused and available
!N | Static nesting level
!O | reserved
!P | reserved
!Q | Low level temporary
!R | Static structure number (begin ... end)
!S | Temporary, used by end, loop, until
!T | reserved
!U | reserved
!V | Next variable number
!W | reserved
!X | Temporary, enter and report file numbers
!Y | Temporary, keyproc
!Z | reserved

The compile-time variables used by the object commands are all two-character names beginning with Z:

Variable | Name | Usage
ZA$ | procedure/function | Label for procedures and functions
ZB$ | current_dep | The current dependent number to assign
ZC$ | current_message | The current flex message number
ZD$ | group_size | Size of the current item group
ZE$ | group_id | Unique ID of current item group
ZF$ | super_class_count | Count of objects in superclass
ZG$ | temp | Temp counter (items, functions etc.)
ZH$ | access_method | The current access method identifier
ZI$ | sub_obj_count | The sub object counter
ZJ$ | current_object | The current_object number
ZS$ | enum_flag | True when compiling in an enumeration list
ZT$ | enum_value | Current value being assigned in enumeration list


#SPOP

Purpose

Pops a value off the string compile-time stack.

Syntax

#SPOP

What It Does

The #SPOP command will pop the top string off of the string stack and place it in the string variable !$.


#SPUSH

Purpose

Pushes a value onto the string compile-time stack.

Syntax

#SPUSH {string-token}

What It Does

There is a single string stack implemented in the compiler. The string to push is passed as an argument to the #SPUSH command.


#STKSYM

Purpose

Destroy all stack type symbols, |S?.

Syntax

#STKSYM

What It Does

Local variables are assigned a symbol which begins with the |S class identifier. These symbols are treated as a special case to the compiler. Whereas most symbols are persistent throughout the compilation process, stack symbols are temporary. The #STKSYM command will destroy all previously known stack symbols, usually in preparation for a new function or procedure definition.


#STR

Purpose

Sets space aside in the static data area for a String runtime variable. Reserves declared size of string plus 3 bytes per variable.

Syntax

#STR V$


!@ - Revision Variable

What It Does

The compile time variable !@ stamps the compiled program file with the Visual DataFlex revision number under which it was compiled.

#IF (!@=100)

showln 'This is a Visual DataFlex 10.0 program'

#ELSE

showln 'This is not a Visual DataFlex 10.0 program'

#ENDIF

The !@ revision variable is reserved for purposes of revision compatibility and should not be changed by Visual DataFlex developers.


!$ - String Variable

What It Does

There is a single string variable, !$, defined by the compiler. The variable may be used to hold any character string needed by the programmer during the compilation process. The variable is used extensively in the object system to refer to the name of the class during object creation.

#SET $$ !1

#IFSAME !$ my_symbol

showln "IT'S MINE"

#ENDIF


Database API Attributes

The Database API Attributes are used in combination with the Get_Attribute, Set_Attribute, Structure_Start and Structure_End commands to query and manipulate the structure of database files. In addition to the API attributes, the SQL based Connectivity Kits define a number of "CLI Database Attributes". This type of attribute is used in combination with the CLI_Get_Database_Attribute (all these attributes are read only).

Attributes are defined on different levels. The supported levels are: Global, Driver, CLI Database, Table, Column, Index and Index_Segment. Depending on the attribute’s level, the number of arguments of the Set_Attribute and Get_Attribute command varies.

Some API attributes can only be used when using a specific Connectivity Kit. Global attribute are global and thus do not rely on a Connectivity Kit. All other attribute levels do rely on a Connectivity Kit. The basic set of attributes can be used for any Connectivity Kit, but some of these attributes do not make sense for the back end in use. The DF_FILE_MAX_RECORDS attribute for example, only makes sense when used with the Embedded Database.

This section describes each API and CLI Database attribute. They are listed alphabetically. It also describes the basic techniques for using the attributes in a Visual DataFlex program. Each attribute is described using the following topics: Level, Supported by, Type, Values and Remarks.

Refer to the Get_Attribute and Set_Attribute commands for further information on using these attributes.

All of the examples in this section of the documentation are designed to work with the data files provided with the Order Entry Sample Application workspace. Due to this, any of the example code provided here can easily be copied and pasted into the Studio and tested.

Note: You may want to back up the tables for the Order Entry Sample Application workspace before testing any example code that modifies the data file structure of these tables. To do so, you can simply copy the Data subdirectory of this workspace to another workspace or directory.

Example

For example, to test the example code for the DF_DATE_FORMAT API attribute, you can follow these steps:

  1. Open the Visual DataFlex Studio

  2. From the File menu, choose Select Workspace

  3. Select the Order Entry Sample Application workspace

  4. Press F5 to bring up the New Component dialog

  5. Select Blank View from the Data Entry Views tab page and click on the Ok button

  6. Select Controls Palette from the Tools menu

  7. Drag and drop a Button control from the Base tab of the Controls Palette onto the blank view

  8. With the button control on the view highlighted, select Component Explorer from the Component menu

  9. You will see the code editor with the button as the selected control in the left pane and the open code window with Procedure OnClick

  10. Paste the code from the DF_DATE_FORMAT API attribute under the Procedure OnClick. Add the line “Send ShowFormats” to the OnClick procedure. The finished code should look like this:

Procedure OnClick

Send ShowFormats

End_Procedure // OnClick

Procedure ShowFormats

Integer iDateFormat

String sDateFormat

Integer iDateSep

Integer iDecimalSep

Integer iThousandSep

Get_Attribute DF_DATE_FORMAT To iDateFormat

Get_Attribute DF_DATE_SEPARATOR To iDateSep

Get_Attribute DF_DECIMAL_SEPARATOR To iDecimalSep

Get_Attribute DF_THOUSANDS_SEPARATOR To iThousandSep

If (iDateFormat = DF_DATE_USA) Move "USA" To sDateFormat

Else If (iDateFormat = DF_DATE_EUROPEAN) Move "European" To sDateFormat

Else If (iDateFormat = DF_DATE_MILITARY) Move "Military" To sDateFormat

Else Move "Unknown" To sDateFormat

Send Info_Box ("Formats:\nDate:" * sDateFormat + ;

"\nDate separator:" * Character(iDateSep) + ;

"\nDecimal separator:" * Character(iDecimalSep) + ;

"\nThousand separator:" * Character(iThousandSep))

End_Procedure // ShowFormats

  11. Select Test Component from the Run menu.

  12. The Studio will prompt you to save the current view. You can simply name the File Name, Description and Object Name the same, for example CodeTestView.

  13. The view will now compile. Next, the application will run and you will see the view and the button.

  14. Click on the button. A message box will pop up to display your current date format, just as the code tells it to.


DF_ALL_FILES_TOUCHED

See also: Get_Attribute, Set_Attribute

Indicates which tables have been acted upon by the last reread or relate command.

Level

Global

Type

String, temporary

Access

Read Only

Values

4095-byte combinations of: DF_FILE_NOT_TOUCHED, DF_FILE_TOUCHED_INACTIVE, DF_FILE_TOUCHED_ACTIVE

Remarks

DF_ALL_FILES_TOUCHED is a string of 4095 bytes. Each byte represents a table. The first byte represents table number 1, and the last byte represents table number 4095. Each byte may have one of three values: DF_FILE_NOT_TOUCHED if the table was not involved in the last reread or relate, DF_FILE_TOUCHED_INACTIVE if the table was involved in the last reread or relate and its record buffer was inactive, or DF_FILE_TOUCHED_ACTIVE if the table was involved in the last reread or relate and its record buffer was active.

The DF_ALL_FILES_TOUCHED attribute is updated when a relate or reread operation occurs. This update does not take place when using the reread command with arguments! There are two ways to use the reread command. Without arguments and with arguments, although it is the same command that is used its implementation is different.

Procedure ShowAllTouched

Handle hTable

String sTable

String sTouched

Integer iTouched

Get_Attribute DF_ALL_FILES_TOUCHED To sTouched

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Move (Ascii(Mid(sTouched,1,hTable))) To iTouched

Case Begin

Case (iTouched = DF_FILE_NOT_TOUCHED)

Showln sTable " NOT touched."

Case Break

Case (iTouched = DF_FILE_TOUCHED_INACTIVE)

Showln sTable " touched INACTIVE."

Case Break

Case (iTouched = DF_FILE_TOUCHED_ACTIVE)

Showln sTable " touched ACTIVE."

Case Break

Case End

End

Until (hTable = 0)

End_Procedure // ShowAllTouched

Procedure ManipulateTouched

Open Salesp

Open Customer

Open Invt

Open Vendor

Open OrderHea

Open OrderDtl

Clear OrderHea

Find Gt OrderHea By 1

If (Found) Begin

Relate OrderHea

Showln "The touched status of the open buffers after Relate OrderHea:"

Send ShowAllTouched

End

Find Gt OrderDtl By 1

Reread OrderDtl

Unlock

Showln

Showln "The touched status of the open buffers after Relate OrderHea,"

Showln "a find on OrderDtl and then a reread with argument:"

Send ShowAllTouched

Reread

Unlock

Showln

Showln "The touched status of the open buffers after Relate OrderHea,"

Showln "a find on OrderDtl and then a reread without argument:"

Send ShowAllTouched

End_Procedure // ManipulateTouched

The procedure above shows the touched status after a relate, a reread with and a reread without arguments.


DF_DATABASE_ID

The handle of the database connection.

Level

CLI Database (use CLI_Get_Database_Attribute)

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Handle

Access

Read Only

Values

Any valid handle value

Remarks

The database API stores information about database drivers and the connections these drivers have in a layered way. You can enumerate through the loaded drivers and every connection opened by these drivers by using the DF_NUMBER_DRIVERS, DF_DRIVER_NAME, DF_DRIVER_NUMBER_SERVERS, and DF_DRIVER_SERVER_NAME global attributes.

The DF_DATABASE_ID attribute returns the handle of the database connection. This handle can be used to get type attributes of the types defined in the database.

The sample code below shows all database handles of all connections to SQL Server.

Procedure ShowServerList

Integer iNumDrivers

String sDriver

Integer iDriver

Integer iNumServers

String sServer

Integer iServer

Handle hDatabase

Get_Attribute DF_NUMBER_DRIVERS To iNumDrivers

For iDriver From 1 To iNumDrivers

Get_Attribute DF_DRIVER_NAME Of iDriver To sDriver

If (sDriver = "MSSQLDRV") Begin

Showln "Servers for driver " sDriver ":"

Get_Attribute DF_DRIVER_NUMBER_SERVERS Of iDriver To iNumServers

For iServer From 1 To iNumServers

Get_Attribute DF_DRIVER_SERVER_NAME Of iDriver iServer To sServer

Showln " " sServer

CLI_Get_Database_Attribute sDriver DF_DATABASE_ID iServer To hDatabase

Showln " Database id: " hDatabase

Send ShowDBTypes sDriver hDatabase

Loop

End

Loop

Showln

Showln "Done..."

End_Procedure // ShowServerList


DF_DATABASE_NUMBER_TYPES

The number of types available in the database.

Level

CLI Database (use CLI_Get_Database_Attribute)

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Integer

Access

Read Only

Values

Positive integer

Remarks

This attribute returns the number of types available in the database. Databases are identified by a handle; this handle should be acquired by the DF_DATABASE_ID or DF_FILE_DATABASE_ID attribute.

The sample code below shows type attributes of all types in a database.

Procedure ShowDBTypes String sDriver Handle hDatabase

Integer iNumTypes

Integer iType

String sTypeName

Handle hTypeID

Boolean bAutoinc

CLI_Get_Database_Attribute sDriver DF_DATABASE_NUMBER_TYPES hDatabase To iNumTypes

Showln "The database has: " iNumTypes " types."

For iType From 0 To (iNumTypes - 1)

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_NAME hDatabase iType To sTypeName

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_ID hDatabase iType To hTypeID

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_AUTOINC hDatabase iType To bAutoinc

Showln " " iType ", " sTypeName ", " hTypeID ", " (If(bAutoinc, "Auto Increment", ""))

Loop

End_Procedure // ShowDBTypes


DF_DATABASE_TYPE_AUTOINC

Indicates if the type is an auto incremented type.

Level

CLI Database (use CLI_Get_Database_Attribute)

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean

Access

Read Only

Values

True, False

Remarks

This attribute returns if the type is an "auto-increment" type. The type is identified by the handle to the database and the type's ordinal number. For a sample of showing type attributes see DF_DATABASE_NUMBER_TYPES.


DF_DATABASE_TYPE_ID

The type identifier.

Level

CLI Database (use CLI_Get_Database_Attribute)

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Enumeration List (Integer)

Access

Read Only

Values

SQL_UNKNOWN_TYPE, SQL_CHAR, SQL_NUMERIC, SQL_DECIMAL, SQL_INTEGER, SQL_SMALLINT, SQL_FLOAT, SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP, SQL_DATE, SQL_INTERVAL, SQL_TIME, SQL_TIMESTAMP, SQL_LONGVARCHAR, SQL_BINARY, SQL_VARBINARY, SQL_LONGVARBINARY, SQL_BIGINT, SQL_TINYINT, SQL_BIT, SQL_WCHAR, SQL_WVARCHAR, SQL_WLONGVARCHAR, SQL_GUID.

Remarks

This attribute returns the ID of the type. The type is identified by the handle to the database and the type's ordinal number. For a sample of showing type attributes, see DF_DATABASE_NUMBER_TYPES.


DF_DATABASE_TYPE_NAME

The type name.

Level

CLI Database (use CLI_Get_Database_Attribute)

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String

Access

Read Only

Values

A string containing the name of the type.

Remarks

This attribute returns the name of the type. The type is identified by the handle to the database and the type's ordinal number. For a sample of showing type attributes, see DF_DATABASE_NUMBER_TYPES.


DF_DATE_FORMAT

See Also: Get_Attribute, Set_Attribute

The date format that is in use by Visual DataFlex.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

DF_DATE_USA

DF_DATE_EUROPEAN

DF_DATE_MILITARY

Remarks

Dates, when presented as strings, can be of three different formats. The DF_DATE_FORMAT attribute indicates the format in use. The DF_DATE_USA date format is the month number followed by the day number followed by the year number (mm/dd/yyyy). The DF_DATE_EUROPEAN date format is the day number followed by the month number followed by the year number (dd/mm/yyyy), and the DF_DATE_MILITARY format is the year number followed by the month number followed by the day number (yyyy/mm/dd). The year number is either a two- or four-digit number. The numeric components of the date are separated by a character that is set with the DF_DATE_SEPARATOR attribute.

By default, the DF_DATE_FORMAT will conform to the regional settings on the machine. Windows visual controls also use the regional settings. If the DF_DATE_FORMAT does not conform to the regional settings, errors will occur when using certain Windows controls. For this reason you should only set this attribute on a temporary basis or in programs that have no user interface. Temporarily changing the date format is often used to output dates in a required format. Some applications need to output information for additional processing by other, possibly third party, applications. If the additional processing requires dates in a certain format the Visual DataFlex application should change the current date format to the required one, output the data and reset the current date format to its original value.

Procedure ShowFormats

Integer iDateFormat

String sDateFormat

Integer iDateSep

Integer iDecimalSep

Integer iThousandSep

Get_Attribute DF_DATE_FORMAT To iDateFormat

Get_Attribute DF_DATE_SEPARATOR To iDateSep

Get_Attribute DF_DECIMAL_SEPARATOR To iDecimalSep

Get_Attribute DF_THOUSANDS_SEPARATOR To iThousandSep

If (iDateFormat = DF_DATE_USA) Move "USA" To sDateFormat

Else If (iDateFormat = DF_DATE_EUROPEAN) Move "European" To sDateFormat

Else If (iDateFormat = DF_DATE_MILITARY) Move "Military" To sDateFormat

Else Move "Unknown" To sDateFormat

Send Info_Box ("Formats:\nDate:" * sDateFormat + ;

"\nDate separator:" * Character(iDateSep) + ;

"\nDecimal separator:" * Character(iDecimalSep) + ;

"\nThousand separator:" * Character(iThousandSep))

End_Procedure // ShowFormats

This example obtains the date and number format in use by Visual DataFlex and then pops up a message box that displays a message showing which format is in use.

Procedure OutputRecords Integer iChannel String sPathToFile

Integer iOrgDateFmt

Integer iOrgDateSep

Get_Attribute DF_DATE_FORMAT To iOrgDateFmt

Get_Attribute DF_DATE_SEPARATOR To iOrgDateSep

Set_Attribute DF_DATE_FORMAT To DF_DATE_MILITARY

Set_Attribute DF_DATE_SEPARATOR To (Ascii(‘-‘))

Direct_Output Channel iChannel sPathToFile

Clear OrderHea

Repeat

Find Gt Orderhea By 1

If (Found) Writeln Channel iChannel OrderHea.Order_Number “,” Orderhea.Order_date

Until (Not(Found))

Close_Output Channel iChannel

Set_Attribute DF_DATE_FORMAT To iOrgDateFmt

Set_Attribute DF_DATE_SEPARATOR To iOrgDateSep

End_procedure

This example temporarily changes the date format in use to output the contents of a table to an ASCII disk file. The date column is written in military format.


DF_DATE_SEPARATOR

See Also: Get_Attribute, Set_Attribute, DF_DECIMAL_SEPARATOR, DF_THOUSANDS_SEPARATOR

The decimal ASCII value of the character in use for separating the components of dates.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

0 255

Remarks

Dates, when presented as strings, are made up of three different parts (day, month and year). The DF_DATE_SEPARATOR attribute indicates the separator in use. The order of the parts is defined by the DF_DATE_FORMAT attribute. The three parts are separated by a character (usually ‘/’ for US and European dates and ‘-‘ for Military dates).

By default, the DF_DATE_SEPARATOR will conform to the regional settings on the machine. Windows visual controls also use the regional settings. If the DF_DATE_SEPARATOR does not conform to the regional settings, errors will occur when using certain Windows controls. For this reason you should only set this attribute on a temporary basis or in programs that have no user interface. Temporarily changing the date format is often used to output dates in a required format. Some applications need to output information for additional processing by other, possibly third party, applications. If the additional processing requires dates in a certain format the Visual DataFlex application should change the current date format to the required one, output the data and reset the current date format to its original value. For a sample on temporarily changing the date separator see DF_DATE_FORMAT.

Procedure ShowFormats

Integer iDateFormat

String sDateFormat

Integer iDateSep

Integer iDecimalSep

Integer iThousandSep

Get_Attribute DF_DATE_FORMAT To iDateFormat

Get_Attribute DF_DATE_SEPARATOR To iDateSep

Get_Attribute DF_DECIMAL_SEPARATOR To iDecimalSep

Get_Attribute DF_THOUSANDS_SEPARATOR To iThousandSep

If (iDateFormat = DF_DATE_USA) Move "USA" To sDateFormat

Else If (iDateFormat = DF_DATE_EUROPEAN) Move "European" To sDateFormat

Else If (iDateFormat = DF_DATE_MILITARY) Move "Military" To sDateFormat

Else Move "Unknown" To sDateFormat

Send Info_Box ("Formats:\nDate:" * sDateFormat + ;

"\nDate separator:" * Character(iDateSep) + ;

"\nDecimal separator:" * Character(iDecimalSep) + ;

"\nThousand separator:" * Character(iThousandSep))

End_Procedure // ShowFormats

This example obtains the date and number format in use by Visual DataFlex and then pops up a message box that displays a message showing which format is in use.


DF_DECIMAL_SEPARATOR

See Also: Get_Attribute, Set_Attribute, DF_DATE_SEPARATOR, DF_THOUSANDS_SEPARATOR

The decimal ASCII value of the radix (character to use to separate the integer portion of a number from the decimal portion).

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

0 255

Remarks

DF_DECIMAL_SEPARATOR allows the character used to separate the integer and decimal parts of a number (the radix) to be set.

By default, the DF_DECIMAL_SEPARATOR will conform to the regional settings on the machine. Windows visual controls also use the regional settings. If the DF_DECIMAL_SEPARATOR does not conform to the regional settings, errors will occur when using certain Windows controls. For this reason you should only set this attribute on a temporary basis or in programs that have no user interface. Temporarily changing the number format is often used to output numbers in a required format. Some applications need to output information for additional processing by other, possibly third party, applications. If the additional processing requires numbers in a certain format the Visual DataFlex application should change the current number format to the required one, output the data and reset the current number format to its original value.

Procedure ShowFormats

Integer iDateFormat

String sDateFormat

Integer iDateSep

Integer iDecimalSep

Integer iThousandSep

Get_Attribute DF_DATE_FORMAT To iDateFormat

Get_Attribute DF_DATE_SEPARATOR To iDateSep

Get_Attribute DF_DECIMAL_SEPARATOR To iDecimalSep

Get_Attribute DF_THOUSANDS_SEPARATOR To iThousandSep

If (iDateFormat = DF_DATE_USA) Move "USA" To sDateFormat

Else If (iDateFormat = DF_DATE_EUROPEAN) Move "European" To sDateFormat

Else If (iDateFormat = DF_DATE_MILITARY) Move "Military" To sDateFormat

Else Move "Unknown" To sDateFormat

Send Info_Box ("Formats:\nDate:" * sDateFormat + ;

"\nDate separator:" * Character(iDateSep) + ;

"\nDecimal separator:" * Character(iDecimalSep) + ;

"\nThousand separator:" * Character(iThousandSep))

End_Procedure // ShowFormats

This example obtains the date and number format in use by Visual DataFlex and then pops up a message box that displays a message showing which format is in use.

Procedure OutputOrderTotal Integer iChannel String sFilePath

Integer iOrgDecimalSep

Get_Attribute DF_DECIMAL_SEPARATOR To iOrgDecimalSep

Set_Attribute DF_DECIMAL_SEPARATOR To (Ascii('#'))

Direct_Output Channel iChannel sFilePath

Clear OrderHea

Repeat

Find Gt Orderhea By 1

If (Found) Writeln Channel iChannel OrderHea.Order_Number “,” Orderhea.Order_total

Until (Not(Found))

Close_Output Channel iChannel

Set_Attribute DF_DECIMAL_SEPARATOR To iOrgDecimalSep

End_Procedure // OutputOrderTotal

This example temporarily changes the number format in use to output the contents of a table to an ASCII disk file.


DF_DRIVER_CONFORMANCE

The conformance level of a driver.

Level

Driver

Type

Integer, permanent

Access

Read Only

Values

0, 1

Remarks

Part of the Visual DataFlex 11 improvements are improved database drivers. These new drivers have a conformance level of 1. Older drivers have a conformance level of 0.

The conformance level is used by the database API. Drivers with a conformance level of 0 support fewer functions then drivers with a conformance level of 1. If an old style driver (conformance level 0) is loaded, the database API will use a compatibility driver that simulates the newer functions. This makes it possible to treat all drivers in the same way regardless of their conformance level.

Driver level attributes are accessed by passing the index of the loaded driver to the Get_Attribute command. The index of a driver can be determined by enumerating through the loaded drivers.

Function DriverIndex String sDriver Returns Integer

String sCurrentDriver

Integer iNumberOfDrivers

Integer iDriver

Integer iCount

Move 0 To iDriver

Get_attribute DF_NUMBER_DRIVERS To iNumberOfDrivers

For iCount From 1 To iNumberOfDrivers

Get_attribute DF_DRIVER_NAME Of iCount To sCurrentDriver

If (Uppercase(sCurrentDriver)) Eq (Uppercase(sDriver)) ;

Move iCount To iDriver

Loop

Function_Return iDriver

End_Function // DriverIndex

Procedure ShowConformance String sDriver

Integer iConformance

Integer iDriver

Get DriverIndex sDriver To iDriver

Get_Attribute DF_DRIVER_CONFORMANCE Of iDriver To iConformance

Showln "The conformance level of driver " sDriver " is " iConformance

End_Procedure // ShowConformance

The sample procedure above shows the conformance level of the passed driver.


DF_DRIVER_NAME

See Also: Get_Attribute, Set_Attribute, DF_DRIVER_NUMBER_SERVERS, DF_DRIVER_SERVER_NAME

The name of the nth-loaded database driver.

Level

Global

Type

String, temporary

Access

Read only

Values

String representing a driver name

Remarks

Unlike other global attributes, this global attribute is indexed. To access the value of this attribute, use the fileNum parameter of the Get_Attribute command to represent the position of the driver in the driver table. As an example, to get the name of the second driver in the driver table, you could use the following command:

Get_Attribute DF_DRIVER_NAME Of 2 To sDriverName

The string variable sDriverName will contain the name of the second driver, if there is one.

The number of drivers may be determined by getting the value of the DF_NUMBER_DRIVERS attribute. We usually refer to database drivers with the term Connectivity Kit. In the discussion of this topic we use both terms.

By default there is always at least one database driver loaded. This is the driver that handles the Embedded Database. It reports it’s name as “DATAFLEX”. Other drivers are loaded dynamically. How many drivers are loaded depends on program logic. A driver will be loaded if:

  • There is an entry in the dfini.cfg file to load the driver on startup. The entry should be “4096=<DriverName>”.

  • An explicit Load_Diver command is executed.

  • The first action on the driver is done (implicit loading). If for example one opens a table accessed via the SQL Server Connectivity Kit it will be loaded automatically.

Procedure ShowDriverList

Integer iNumDrivers

String sDriver

Integer iDriver

Get_Attribute DF_NUMBER_DRIVERS To iNumDrivers

For iDriver From 1 To iNumDrivers

Get_Attribute DF_DRIVER_NAME Of iDriver To sDriver

Showln "Driver: " sDriver

Loop

Showln

Showln "Done..."

End_procedure // ShowDriverList

This example enumerates all loaded drivers and lists them.


DF_DRIVER_NUMBER_SERVERS

See Also: Get_Attribute, Set_Attribute, DF_DRIVER_NAME, DF_DRIVER_SERVER_NAME

The number of connections open for a Connectivity Kit.

Level

Global

Type

Integer, temporary

Access

Read only

Values

0 to maximum number of connections allowed for the driver

Remarks

Unlike other global attributes, this global attribute is indexed. To access the value of this attribute, use the fileNum parameter of the Get_Attribute command to represent the position of the driver in the driver table. As an example, to get the number of connections of the second driver in the driver table, you could use the following command:

Get_Attribute DF_DRIVER_NUMBER_SERVERS Of 2 To iNumConnections

The integer variable iNumConnections will contain the name of the second driver, if there is one.

The DF_DRIVER_NUMBER_SERVERS attribute is global and should work on any driver in the driver table. When used on the Embedded Database driver (DATAFLEX), an exception occurs.

The number of drivers may be determined by getting the value of the DF_NUMBER_DRIVERS attribute. We usually refer to database drivers with the term Connectivity Kit. In the discussion of this topic we use both terms.

Procedure ShowServerList

Integer iNumDrivers

String sDriver

Integer iDriver

Integer iNumServers

String sServer

Integer iServer

Get_Attribute DF_NUMBER_DRIVERS To iNumDrivers

For iDriver From 1 To iNumDrivers

Get_Attribute DF_DRIVER_NAME Of iDriver To sDriver

Showln "Servers for driver " sDriver ":"

If (sDriver <> "DATAFLEX") Begin

Get_Attribute DF_DRIVER_NUMBER_SERVERS Of iDriver To iNumServers

For iServer From 1 To iNumServers

Get_Attribute DF_DRIVER_SERVER_NAME Of iDriver IServer To sServer

Showln " " sServer

Loop

End

Loop

Showln

Showln "Done..."

End_procedure // ShowServerList

This example enumerates all loaded database drivers and lists them. For each individual driver, the names of all the open connections are listed.


DF_DRIVER_SERVER_NAME

See Also: Get_Attribute, Set_Attribute, DF_DRIVER_NAME, DF_DRIVER_NUMBER_SERVERS

The name of a connection for a driver.

Level

Global

Type

String, temporary

Access

Read only

Values

String representing a server name.

Remarks

Unlike other global attributes, this global attribute is indexed. To access the value of this attribute, use the {table-handle} and {field-num} parameter of the Get_Attribute command to represent the position of the driver in the driver table and the ordinal position of the connection. As an example, to get the number name the third connection of the second driver in the driver table, you could use the following command:

Get_Attribute DF_DRIVER_SERVER_NAME Of 2 3 To sServer

The string variable sServer will contain the name of the third connection of the second driver.

The contents of the connection name string depend on the Connectivity Kit that is used. The Embedded Database driver does not support connections (in theory there’s always one connection). The SQL based Connectivity Kits typically show a connect string as the name. For the Pervasive.SQL Connectivity Kit the server name will be a database Uniform Resource Indicator (URI) in case the database mode is set to use URIs, otherwise it does not support connections (like the Embedded Database there’s always one connection).

We usually refer to database drivers with the term Connectivity Kit. In the discussion of this topic we use both terms.

Procedure ShowServerList

Integer iNumDrivers

String sDriver

Integer iDriver

Integer iNumServers

String sServer

Integer iServer

Get_Attribute DF_NUMBER_DRIVERS To iNumDrivers

For iDriver From 1 To iNumDrivers

Get_Attribute DF_DRIVER_NAME Of iDriver To sDriver

Showln "Servers for driver " sDriver ":"

If (sDriver <> "DATAFLEX") Begin

Get_Attribute DF_DRIVER_NUMBER_SERVERS Of iDriver To iNumServers

For iServer From 1 To iNumServers

Get_Attribute DF_DRIVER_SERVER_NAME Of iDriver iServer To sServer

Showln " " sServer

Loop

End

Loop

Showln

Showln "Done..."

End_procedure // ShowServerList

This example enumerates all loaded database drivers and lists them. For each individual driver, the names of all the open connections are listed.


DF_FIELD_DEFAULT_VALUE

The default value of a column.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String

Access

Read / Write

Values

A string containing the default value of the column.

Remarks

This attribute sets up the database default value for a column. You can setup SQL Server defaults on a column in three different formats: literal, ODBC escape sequence or back-end string.

A literal default is set by using a string in single quotes. It should be a valid literal value for the SQL type of the column. An ODBC escape sequence is enclosed in curly brackets {}, and a back-end string is enclosed in square brackets [].

Typical examples of setting default values are:

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyCharField To "'Unknown'"

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyDateField To "{fn current_date()}"

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyCharField To "[convert(char(30), CURRENT_USER)]"

The default will be used when creating records. So if we were to have a table MyTable with columns A, B, C and use the code below, we would end up with a new row in MyTable having default values (if any) for columns B and C.

Clear MyTable

Begin_Transaction

Move "Not a default value" To MyTable.A

Saverecord MyTable

End_Transaction

See NULL Values and Defaults for more information.


DF_FIELD_FETCH_STATE

The fetch state of a column.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean

Access

Read / Write

Values

True, False

Remarks

This column attribute indicates if individual columns are selected or not. There is a special field number keyword to set this attribute for all columns in a table at once: DF_ALL_COLUMNS.

Set_Attribute DF_FIELD_FETCH_STATE Of MyTable.File_Number DF_ALL_COLUMNS To False

Set_Attribute DF_FIELD_FETCH_STATE Of MyTable.File_Number 1 To True

Set_Attribute DF_FIELD_FETCH_STATE Of MyTable.File_Number 2 To True

Set_Attribute DF_FIELD_FETCH_STATE Of MyTable.File_Number 3 To True

The code above sets the fetch state for all columns off and then sets the fetch state for the first three columns on. This means that only the first three columns will be fetched from the back end. This attribute can be used to improve performance.

When a table is opened the attribute is automatically set to true for all columns (all columns are fetched after opening). For more information on using this attribute, see the section Selective Column Fetching


DF_FIELD_INDEX

See Also: Get_Attribute, Set_Attribute

The number of the Main Index used for searching by the values in a field.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent

Access

Read / Write

Values

0 ~ highest index number defined on the table

Remarks

This attribute is also known as the field's Main Index. The main index is used when using a column name with the find command. As an example if you want to find the next customer by its name you could issue the command:

Find Gt Customer.Name

The command will result in the find logic getting the DF_FIELD_INDEX attribute of the Customer.Name column and finding the next record according to that index. If there is no main index defined on a column and a find operation as described above is attempted it will result in an DFERR_FIELD_NOT_INDEXED error.

The Main Index of a column is also used by the relate logic to determine which index to use to find a record in a file that is related to through the field. When the relation is a multi segment relation, the relate logic will use the main index of the first relating column. Assuming we have a relationship between two tables called Child and Parent where Child.FKCol1 and Child.FKCol2 relate to Parent.PKCol1 and Parent.PKCol2. Issuing a “Relate Child” command will find the parent record based on the main index of Parent.PKCol1.

When pressing a find key in a data entry object (DEO), the main index of the column edited by the DEO will be used by default. The data entry object calls the Field_Index function of the DataDictionary “owning” the table. That function will return the main index by default.

For the Embedded Database and Pervasive.SQL Connectivity Kits this is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. For the SQL based Connectivity Kits, it is possible to set this attribute outside a structure operation. This support is intended to be used when opening tables without intermediate files so the main index can be set if needed.

At the time that this attribute is set, the index it points to must exist when using the Embedded Database. If the index does not yet exists, the DFERR_ATTRIBUTE_VALUE_WARNING error will be generated. The other Connectivity Kits allow setting the attribute to a non-existent index. Make sure the index is created before ending the structure operation.

For the non Embedded Database Connectivity Kits the permanent value of this attribute is stored in the intermediate file using the Field_Index keyword.

Procedure ChangeMainIndex Handle hTable Integer iColumn Integer iNewIndex

Integer iOldIndex

String sColumn

String sTable

String sMessage

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_FIELD_INDEX Of hTable iColumn To iOldIndex

If (iOldIndex > 0) Begin

If (iOldIndex <> iNewIndex) ;

Move ("Column" * sColumn * "of table" * sTable * ;

"currently has main index:" * String(iOldIndex)) To sMessage

Else ;

Move ("Column" * sColumn * "of table" * sTable * ;

"already has main index:" * String(iOldIndex)) To sMessage

End

Else ;

Move ("Column" * sColumn * "of table" * sTable * "currently has no main index.") To sMessage

Send Info_Box sMessage

If (iOldIndex > 0 And iOldIndex <> iNewIndex) Begin

Structure_Start hTable

Set_Attribute DF_FIELD_INDEX Of hTable iColumn To iNewIndex

Structure_End hTable

End

Else ;

Close hTable

End_Procedure // ChangeMainIndex

The sample code above changes the main index of a column. It first gets the current setting of the main index and shows this. Only when the main index is already set and the new value is different, it permanently changes the main index for the column.


DF_FIELD_LENGTH

See Also: Get_Attribute, Set_Attribute, DF_FIELD_NATIVE_LENGTH

The length of a field.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent

Access

Read / Write

Values

1 – maximum number of bytes allowed for the field type.

Remarks

The effective length of a column, for ASCII, Text and Binary columns this is the maximum number of characters/bytes, for numeric columns the maximum number of digits (including digits after the decimal separator)l, for date columns, the DF_FIELD_LENGTH attribute is a constant value. If you wish to create a numeric field with digits after the decimal point, you must set the DF_FIELD_PRECISION attribute for that field after setting the DF_FIELD_LENGTH attribute. If you wish to create a numeric field without digits after the decimal point, it is not necessary to set the DF_FIELD_PRECISION attribute for that field.

For all Connectivity Kits this is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. For the non Embedded Database Connectivity Kits the permanent value of this attribute can be stored in the intermediate file using the Field_Length keyword.

In the Embedded Database, the DF_FIELD_LENGTH attribute of date columns will always be 6. Dates are stored as Julian integer values in a 3 byte integer. Numeric columns are stored a binary coded decimal values where each nibble uses four bits. Since the length of a column always spans complete bytes, the length of a numeric column is always an even value. The length of Binary and Text columns includes two bytes that are used to hold the length of the value of the column. Therefore, the maximum number of bytes of actual data that can be placed in these fields is DF_FIELD_LENGTH minus 2.

In the SQL based Connectivity Kits, the DF_FIELD_LENGTH attribute of date columns is a constant. The value of that constant depends on the actual SQL type on the back end. The CK’s report Date and DateTime columns as a DataFlex date type.

DF_TEXT and DF_BINARY in the Embedded Database

Note that for the Embedded database driver, the usable size of a DF_TEXT or DF_BINARY column will be two bytes less than the declared length. Thus, if you declare a text column with a size of 256 bytes, you will be able to store up to 254 characters in this column. The amount of space occupied on the disk is the actual length of the contents, if any, plus 2 bytes, unless compression is not turned on. In that event, the amount of space occupied will be the declared length of the column, regardless of whether the column has any content.

DF_TEXT and DF_BINARY column length in SQL based CK’s

The maximum size of text and binary columns varies greatly between different back ends. For the Embedded Database it is 16kb, for SQL Server it is 2Gb. When opening a table in such a back –end, it usually reports the column length as 2Gb. When using the SQL based connectivity kits, the size of such columns will be truncated at 16kb by default. You can increase this size by editing the FIELD_LENGTH intermediate file keyword or setting the DF_FIELD_LENGTH attribute to the desired length when creating the column. Note that these columns are part of a table’s buffer and the size you specify for it will be allocated in memory when the table is opened.

Procedure AddLastNameColumn Handle hTable

Integer iColumn

Open hTable Mode DF_EXCLUSIVE

Structure_Start hTable

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "LastName"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Structure_End hTable

End_Procedure // AddLastNameColumn

This example adds a field named LastName, of type ASCII and length 50 to the end (as the last field) of the table.

Procedure AddAmountColumn Handle hTable

Integer iColumn

Open hTable Mode DF_EXCLUSIVE

Structure_Start hTable

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Amount"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 8

Set_Attribute DF_FIELD_PRECISION Of hTable iColumn To 2

Structure_End hTable

End_procedure // AddLastNameColumn

This example adds a field named Amount, of type BCD (Numeric) and length 8, with 6 digits before and 2 digits following the decimal point to the end (as the last field) of the table.

Procedure CreateTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "RIMSample.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To True

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "RIMSample"

Set_Attribute DF_FILE_GENERATE_RECORD_ID_METHOD Of hTable To RIM_IDENTITY_COLUMN

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To 0

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 4

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Name"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (5 * (2^20))

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "RimSample001"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:RIMSample"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "RIM sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "RIMSamp"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "RIMSamp.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

This example creates a SQL Server table with a text column of 5 megabytes.


DF_FIELD_IS_NULL

Does a field have the “NULL value”?

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC) and the Pervasive.SQL Connectivity Kit

Type

Boolean

Access

Read / Write

Values

True, False

Remarks

This attribute indicates if a column has the "null value". The attribute is true when a field has the null value and false otherwise. Columns can only get the “NULL value” if they are “nullable”. You can query the “nullability” of a column with the DF_FIELD_NULL_ALLOWED attribute.

A null value is a special marker that is used when the value of a column is unknown. You can set this attribute to force a column to have the null value. See NULL Values and Defaults for more information.

Procedure CreateRecord

Begin_Transaction

Clear MyTable

Move "UniqueValue" To MyTable.ID

Move "SomeOtherValue" To MyTable.OtherColumn

Set_Attribute DF_FIELD_IS_NULL Of MyTable.File_Number 3 To True

SaveRecord MyTable

End_Transaction

End_Procedure // CreateRecord

The example above creates a new record in table MyTable. It fills two columns with an explicit value and gives column number 3 the “NULL value”.


DF_FIELD_NAME

See Also: Get_Attribute, Set_Attribute, DF_FIELD_NUMBER

The name of a column.

Level

Column

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

A string containing the name of the column.

Remarks

The name of a column, the maximum length and legal characters depend on the back end in use. The Embedded Database only supports uppercase characters, the other Connectivity Kits support mixed case column names.

In the Embedded Database, column names can be any combination of characters, up to 15 characters long, that starts with a letter and contains no punctuation other than underscore (_).

For all Connectivity Kits this is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. For the non Embedded Database Connectivity Kits the permanent value of this attribute can be stored in the intermediate file using the Field_Name keyword.

Procedure ShowNames Handle hTable

String sTable

String sColumn

Integer iNumColumns

Integer iColumn

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Showln "The columns in table " sTable " have the following names:"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Showln (Right(" " + String(iColumn), 5)) ": " sColumn

Loop

End_Procedure // ShowNames

This example retrieves and displays the name of all columns in the table.

Procedure AddLastNameColumn Handle hTable

Integer iColumn

Open hTable Mode DF_EXCLUSIVE

Structure_Start hTable

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "LastName"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Structure_End hTable

End_Procedure // AddLastNameColumn

This example adds a field named LAST_NAME, of type ASCII and length 50 to the end (as the last field) of the table.


DF_FIELD_NATIVE_LENGTH

See Also: Get_Attribute, Set_Attribute

The length of a column in the record buffer.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent

Access

Read Only

Values

1 (minimum) ~ max field size (maximum)

Remarks

The native length is the length, in bytes, a column takes up in the record buffer allocate by the Connectivity Kit for the table.

The sum of the values of the DF_FIELD_NATIVE_LENGTH attributes for each field (or part of a field) in an overlap field must add up to the value of the DF_FIELD_NATIVE_LENGTH attribute of the overlap field.

For all Connectivity Kits this is a permanent attribute that can not directly be set. It can be set indirectly by setting the DF_FIELD_LENGTH and/or DF_FIELD_PRECISION attributes.

Function BufferSize Handle hTable Returns Integer

Integer iNumColumns

Integer iNativeLength

Integer iBufferSize

Integer iColumn

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NATIVE_LENGTH Of hTable iColumn To iNativeLength

Move (iBufferSize + iNativeLength) To iBufferSize

Loop

Function_Return iBufferSize

End_Function // BufferSize

This example calculates the buffer size using the native length of all columns in the table.


DF_FIELD_NATIVE_TYPE

The native type of a column.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Enumeration list (Integer)

Access

Read / Write

Values

SQL_UNKNOWN_TYPE, SQL_CHAR, SQL_NUMERIC, SQL_DECIMAL, SQL_INTEGER, SQL_SMALLINT, SQL_FLOAT, SQL_REAL, SQL_DOUBLE, SQL_DATETIME, SQL_VARCHAR, SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP, SQL_DATE, SQL_INTERVAL, SQL_TIME, SQL_TIMESTAMP, SQL_LONGVARCHAR, SQL_BINARY, SQL_VARBINARY, SQL_LONGVARBINARY, SQL_BIGINT, SQL_TINYINT, SQL_BIT, SQL_WCHAR, SQL_WVARCHAR, SQL_WLONGVARCHAR, SQL_GUID

Remarks

This attribute returns the ID of the column's native type. The DataFlex Database API supports 5 actual types (ASCII, Numeric, Date, Text and Binary) and one logical type (Overlap). SQL Databases typically support more than 5 types. The Connectivity Kit will convert a column’s type to one of the 5 supported types and report that in the DF_FIELD_TYPE attribute. The DF_FIELD_NATIVE_TYPE attribute allows more control over a column’s type.

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation.

Procedure ChangeCharToVarchar Handle hTable

Integer iNumColumns

Integer iColumn

Integer iNativeType

Structure_Start hTable

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To iNativeType

If (iNativeType = SQL_CHAR) ;

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_VARCHAR

Loop

Structure_End hTable

End_Procedure // ChangeCharToVarchar

This example changes all char columns of a table into varchar.


DF_FIELD_NATIVE_TYPE_NAME

The name of the native type of a column.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String

Access

Read / Write

Values

A string containing the column name.

Remarks

This string attribute can be used to fine tune native type settings. It is possible that more than one type use the same type identifier (DF_FIELD_NATIVE_TYPE). This is the case for identity types and user defined types. In these cases one can use the DF_FIELD_NATIVE_TYPE_NAME to specify the exact mapping. You must set this attribute to the exact type string used by the back-end (the value is case sensitive).

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation.

In SQL Server for example one can define additional types and bind rules to a user defined type. It is possible to define a type to store information and add a form of validation to the database server by creating a rule for the type. One could, for example, create a type and accompanying rule for storing Dutch zip codes.

A Dutch zip code is a four-digit number followed by a space followed by two uppercase characters. In order to define this type, define the rule in SQL Server Enterprise Manager as follows:

Then create the type in Enterprise Manager as follows:

This type "DutchZipCode" can be used in table definitions like:

Procedure ChangeZipCodeColumn Handle hTable

Integer iNumColumns

Handle hColumn

String sName

Structure_Start hTable

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For hColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_Name Of hTable hColumn To sName

If (Uppercase(sName) = "ZIPCODE")

Set_Attribute DF_FIELD_NATIVE_TYPE_NAME Of hTable hColumn To "DutchZipCode"

Loop

Structure_End hTable

End_Procedure // ChangeCharToVarchar

If one tries to save invalid data into the column of type DutchZipCode, SQL Server will generate an error.


DF_FIELD_NULL_ALLOWED

Does a field support having the “NULL value”?

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC) and the Pervasive.SQL Connectivity Kit

Type

Boolean

Access

Read / Write

Values

True, False

Remarks

This attribute indicates if a column allows "null values" to be stored. The attribute is true when a column allows null values and false otherwise. A null value is a special marker that is used when the value of a column is unknown. See NULL Values and Defaults for more information.

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation.

To place the “Null value” in a column and to see if a column contains the “Null value” use the DF_FIELD_IS_NULL column attribute.

Procedure ShowNullAllowed Handle hTable

Integer iNumColumns

Boolean bAllowed

Integer iColumn

String sTable

String sColumn

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Showln "The columns in table " sTable " have NULL settings:"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_FIELD_NULL_ALLOWED Of hTable iColumn To bAllowed

Show (Right(" " + String(iColumn), 5)) ": " sColumn

Showln " " (If(bAllowed, "NULL", "NOT NULL"))

Loop

End_Procedure // ShowNullAllowed

This example shows the null allowed setting for all columns of a table.


DF_FIELD_NUMBER

See Also: Get_Attribute, Set_Attribute, Field_Map, DF_FIELD_NAME

The number of a field within a table.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, temporary

Access

Read Only

Values

0 ~ maximum fields allowed in database

Remarks

Columns are numbered starting at 1 and ascend in numerical sequential order. For recnum tables, the record number of the record can be addressed as (pseudo-) field 0.


DF_FIELD_OFFSET

See Also: Get_Attribute, Set_Attribute, DF_FIELD_OVERLAP

The offset of the column in the record.

Level

Column

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

1 ~ maximum record length

Remarks

DF_FIELD_OFFSET specifies the location of the beginning of the column in the record. It may only be set for Overlap columns. To define an overlap column two attributes need to be set: DF_FIELD_OFFSET and DF_FIELD_LENGTH.

In previous Visual DataFlex version overlap columns where used to define relationships that should have been a multi segment relationship. Visual DataFlex 11 supports multi segment relationships. This greatly reduces (eliminates) the need for having overlap columns.

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. For the SQL based Connectivity Kits, the permanent value of this attribute for overlap columns can be stored in the intermediate file using the Field_Overlap_Start or Field_Overlap_Offset_Start keywords.

Procedure ShowOffset Handle hTable

Integer iNumColumns

Integer iOffset

Integer iColumn

String sTable

String sColumn

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Showln "The columns in table " sTable " have offsets:"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_FIELD_OFFSET Of hTable iColumn To iOffset

Showln (Right(" " + String(iOffset), 10)) ": " sColumn

Loop

End_Procedure // ShowOffset

This example show the offset for every column in the table.

Procedure AddOverlap Handle hTable Integer iStart Integer iEnd

Integer iStartOffset

Integer iEndOffset

Integer iEndLength

Integer iColumn

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FIELD_OFFSET Of hTable iStart To iStartOffset

Get_Attribute DF_FIELD_OFFSET Of hTable iEnd To iEndOffset

Get_Attribute DF_FIELD_NATIVE_LENGTH Of hTable iEnd To iEndLength

Move (iEndOffset + iEndLength) To iEndOffset

Structure_Start hTable

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To ("OVL_" - String(iStart) - "_" - String(iEnd))

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_OVERLAP

Set_Attribute DF_FIELD_OFFSET Of hTable iColumn To iStartOffset

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (iEndOffset - iStartOffset)

Structure_End hTable

End_procedure // AddOverlap

This example creates an overlap field named OVL_X_Y (where X is the column number the overlaps start at and Y the column number where the overlap ends) in the table.


DF_FIELD_OLD_NUMBER

See Also: Get_Attribute, Set_Attribute

The field number of the field in the previous structure.

Level

Column

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read / Write

Values

0 ~ maximum fields allowed in database

Remarks

During structure operations on an existing file, DF_FIELD_OLD_NUMBER specifies which position in the existing file the field occupies. For new fields, DF_FIELD_OLD_NUMBER is 0. This attribute can be used to move data from one field to another during the data restructure.

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. The Pervasive.SQL Connectivity Kit does not support setting this attribute, the other Connectivity Kits, including the Embedded Database, do support setting this attribute.

Procedure MoveColumn Handle hTable Integer iOld Integer iNew

String sColumn

Integer iType

Integer iLength

Integer iPrecision

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FIELD_NAME Of hTable iOld To sColumn

Get_Attribute DF_FIELD_TYPE Of hTable iOld To iType

If (iType <> DF_DATE) ;

Get_Attribute DF_FIELD_LENGTH Of hTable iOld To iLength

If (iType = DF_BCD) ;

Get_Attribute DF_FIELD_PRECISION Of hTable iOld To iPrecision

Structure_Start hTable

Delete_Field hTable iOld

Create_Field hTable At iNew

Set_Attribute DF_FIELD_NAME Of hTable iNew To sColumn

Set_Attribute DF_FIELD_TYPE Of hTable iNew To iType

If (iType <> DF_DATE) ;

Set_Attribute DF_FIELD_LENGTH Of hTable iNew To iLength

If (iType = DF_BCD) ;

Set_Attribute DF_FIELD_PRECISION Of hTable iNew To iPrecision

Set_Attribute DF_FIELD_OLD_NUMBER Of hTable iNew To iOld

Structure_End hTable

End_Procedure // MoveColumn

This example moves a column with its contents to another position in the table.


DF_FIELD_OVERLAP

See Also: Get_Attribute, Set_Attribute, DF_FIELD_OFFSET

Indicates whether a given field overlaps another given field.

Level

Column

Supported by

All Connectivity Kits

Type

Boolean, permanent

Access

Read only

Values

True, False

Remarks

If the first field overlaps the second field given as parameters of the get_attribute command, then DF_FIELD_OVERLAP is True. If not, the value is False.

In previous Visual DataFlex version overlap columns where used to define relationships that should have been a multi segment relationship. Visual DataFlex 11 and higher supports multi segment relationships. This greatly reduces (eliminates) the need for having overlap columns.

Get_Attribute DF_FIELD_OVERLAP Of 11 4 7 To bOverlap

This example checks the fourth field against the seventh field of table number 11. If Field 4 is an Overlap field, and it overlaps Field 7, then bOverlap (a Boolean variable) will contain true, otherwise it will contain false.


DF_FIELD_PRECISION

See Also: Get_Attribute, Set_Attribute

The number of decimal places in a numeric field.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent

Access

Read / Write

Values

0 ~ maximum number of decimal positions for the back end in use

Remarks

Field precision is the number of digits to the right of the decimal separator. The total number (including decimal digits) of digits in a column can be found via the DF_FIELD_LENGTH attribute. If you wish to create a numeric field with digits after the decimal point, you must set the DF_FIELD_PRECISION attribute for that field after setting the DF_FIELD_LENGTH attribute. If you wish to create a numeric field without digits after the decimal point, it is not necessary to set the DF_FIELD_PRECISION attribute for that field.

This is a permanent attribute that can only be set inside a Structure_Start ... Structure_End operation. For the SQL based Connectivity Kits, the permanent value of this attribute for overlap columns can be stored in the intermediate file using the Field_Precision keyword.

In the Embedded Database numeric columns are stored a binary coded decimal values where each nibble uses four bits. Since the length of a column always spans complete bytes, the length of a numeric column is always an even value. When DF_FIELD_PRECISION is set, the value provided will be rounded up to an even number with a maximum size of 8.

If the field addressed is not numeric, you will receive an error (Bad attribute value).

Procedure ShowPrecision Handle hTable

String sTable

String sColumn

Integer iNumColumns

Integer iColumn

Integer iType

Integer iPrecision

Integer iLength

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Showln "The columns in table " sTable " have the following names:"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Show (Right(" " + String(iColumn), 5)) ": " sColumn

Get_Attribute DF_FIELD_TYPE Of hTable iColumn To iType

Get_Attribute DF_FIELD_LENGTH Of hTable iColumn To iLength

If (iType <> DF_BCD) ;

Showln "(" iLength ")"

Else Begin

Get_Attribute DF_FIELD_PRECISION Of hTable iColumn To iPrecision

If (iPrecision > 0) ;

Showln "(" (iLength - iPrecision) "," iPrecision ")"

Else ;

Showln "(" iLength ")"

End

Loop

End_Procedure // ShowPrecision

This example loops through all the columns in the table and displays the field name and the size of the column.

Procedure AddAmountColumn Handle hTable

Integer iColumn

Open hTable Mode DF_EXCLUSIVE

Structure_Start hTable

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Amount"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 8

Set_Attribute DF_FIELD_PRECISION Of hTable iColumn To 2

Structure_End hTable

End_Procedure // AddLastNameColumn

This example adds a field named Amount, of type BCD (Numeric) and length 8, with 6 digits before and 2 digits following the decimal point to the end (as the last field) of the table.


DF_FIELD_READ_ONLY

A column’s read only setting.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Enumeration list, permanent

Access

Read / Write

Values

RO_NO, RO_IGNORECHANGE, RO_ACCEPTCHANGE, RO_ERRORONCHANGE

Remarks

In some cases it is not desirable that a certain column is changed through the Connectivity Kit. It is possible to handle certain column updates through triggers. If one goes that way, it would be needed to change every program that accesses that table so it no longer updates the column in question. Alternatively, one could use the DF_FIELD_READ_ONLY attribute and the program logic does not have to change.

This is a permanent attribute that can be set inside and outside a Structure_Start ... Structure_End operation. For the SQL based Connectivity Kits, the permanent value of this attribute is stored in the intermediate file using the Field_Precision keyword.

We expect that this attribute will rarely be used. When a need for setting the read only state of a column arises, this will almost certainly be done in the intermediate file. For a description of the meaning of the possible values of the attribute see Field_Read_Only intermediate file keyword.


DF_FIELD_RELATED_FIELD

See Also: Get_Attribute, Set_Attribute, Set_Relate, DF_FIELD_RELATED_FILE

The field number, in a related table, to which the field which the attribute is being used on, relates.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent/temporary

Access

Read / Write

Values

0 ~ maximum fields in the parent table

Remarks

This attribute should always be used in conjunction with the DF_FIELD_RELATED_FILE attribute. The combination of DF_FIELD_RELATED_FILE and DF_FIELD_RELATED_FIELD attributes defines a relationship between two tables. Since these attributes are mutually dependent, see DF_FIELD_RELATED_FILE for a description of both attributes.


DF_FIELD_RELATED_FILE

See Also: Get_Attribute, Set_Attribute, Set_Relate, DF_FIELD_RELATED_FIELD

The number of the table containing to which the field which the attribute is being used on relates.

Level

Column

Supported by

All Connectivity Kits

Type

Integer, permanent/temporary

Access

Read / Write

Values

A table number, table numbers range from 1 to 4095.

Remarks

This attribute should always be used in conjunction with the DF_FIELD_RELATED_FIELD attribute. The combination of DF_FIELD_RELATED_FILE and DF_FIELD_RELATED_FIELD attributes defines a relationship between two tables. Since these attributes are mutually dependent, both attributes are documented in this topic.

A relationship between two tables allows you to prevent redundant data in the database. If, for example, a database stores sales information, one would have a table called sales to store information about each sale like salesdate, product and amount. There is also information about the customer like the name, and address. If the customer information would be stored in the sales table, the customer information would be duplicated for every purchase the customer makes. It is better to store the customer information once in a separate table and put a reference in the sales table that points to a record in the customer table. This reference is called a relationship. Usually records in a table are identified by one or more columns in that table, the primary key. When creating a relationship columns are added to the child file with the same type and length as the columns in the primary key of the parent file, the foreign key.

In Visual DataFlex relationships are defined by setting column attributes (DF_FIELD_RELATED_FILE and DF_FIELD_RELATED_FIELD). This means you can only define one relationship between two tables. If there are multiple columns in a child table referencing columns in one parent table, the relationship is regarded as a multi segment relationship. Prior to revision 11, Visual DataFlex did not support multi segment relationships. In these versions one used overlap columns to simulate multi segment relationships. The direct support for multi segment relationships greatly reduces (eliminates) the need for overlap columns.

If there is a need to define more then one relationship between two tables, alias tables for the parent must be used. Every database query language supports a form of creating aliases for tables. In Visual DataFlex aliases are created by creating an additional filelist entry pointing to the same physical table and setting the DF_FILE_ALIAS attribute for the original and the alias table(s).

If the DF_FIELD_RELATED_FILE attribute is zero the column does not have a relationship (regardless of the value of the DF_FIELD_RELATED_FIELD attribute).

If the DF_FIELD_RELATED_FILE is not zero and DF_FIELD_RELATED_FIELD is zero it defines a so called Recnum relation. Recnum relations have been discouraged by Data Access for many years but it may be possible that legacy systems still have such relationships. It is strongly discouraged to use this type of relation.

This is a permanent attribute that can be set inside and outside a Structure_Start ... Structure_End operation. For the non Embedded Database Connectivity Kits, the permanent value of this attribute is stored in the intermediate file using the Field_Related_File, FieldRelated_Field keywords. If the attribute is set outside of a structure operation the setting is in effect until it is reset or the program ends. A shortcut to set both attributes is the Set_Relate command.

Procedure ShowTree Handle hTable Integer iLevel

Boolean bOpen

Integer iNumColumns

Integer iColumn

Handle hParent

Handle hoSet

Integer iItem

Integer iNumParents

String sTable

Get Create U_Set To hoSet

Get_Attribute DF_FILE_OPENED Of hTable To bOpen

If (Not(bOpen)) ;

Open hTable

//*** Show this table

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln (Repeat(" ", iLevel)) sTable

//*** Place all parent tables in the set

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_RELATED_FILE Of hTable iColumn To hParent

If (hParent > 0) ;

Send Add_Element Of hoSet hParent

Loop

//*** Now show the members of the set

Get Item_Count Of hoSet To iNumParents

For iItem From 0 To (iNumParents - 1)

Get Value Of hoSet Item iItem To hParent

Send ShowTree hParent (iLevel + 1)

Loop

If (Not(bOpen)) ;

Close hTable

Send Destroy Of hoSet

End_Procedure // ShowTree

This example shows a recursive function that displays a tree of all ancestors (parents, grandparents and so forth) of the passed table.

Procedure CreateTable

Handle hTable

Integer iColumn

Integer iIndex

Handle hoWorkspace

String sPath

String sOrgDirectory

//*** Make sure table comes in first directory of datapath by making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create physical table contacts

Move 0 To hTable

Structure_Start hTable "DATAFLEX"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_MAX_RECORDS Of hTable To 150000

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Customer_Number"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 6

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ContactDate"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (8 * 1024)

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 2

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Structure_End hTable

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Contact sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Contact"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Contact.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

In this sample a new table called Contact is created. It has here columns: Customer_Number of type Numeric(6), Contactdate of type Date and Comment of type Text(8192) with an index on Customer_number and ContactDate (descending). The table is used in upcoming example code. The table will be created in the first directory of the data path of the current workspace; an fd file will be created in the first directory of the DDSrc path of the current workspace.

Procedure UseTempRelation

Handle hTable

Boolean bCustFound

Integer iContactCount

Open Customer

Open Contact

Set_Relate Contact.Customer_Number To Customer.Customer_Number

Clear Customer

Repeat

Find Gt Customer By 1

Move (Found) To bCustFound

If (bCustFound) Begin

Showln "Contacts for customer: " ;

(Trim(Customer.Name)) "have taken place on the following dates:"

Move 0 To iContactCount

Attach Contact

Find Ge Contact By 1

If (Found) ;

move (Customer.Customer_number = Contact.Customer_Number) to Found

While (Found)

If (iContactCount > 0) ;

Show ", "

Show Contact.Contactdate

Increment iContactCount

Find Gt Contact By 1

If (Found) ;

move (Customer.Customer_number = Contact.Customer_Number) to Found

End

If (iContactCount = 0) ;

Showln "NO CONTACTS"

Else ;

Showln

End

Until (Not(bCustFound))

Close Contact

Close Customer

End_Procedure // UseTempRelation

In this example the Contact table is opened and a temporary relation to the Customer table is created using the Set_Relate command.

Set_Relate Contact.Customer_Number To Customer.Customer_Number

Note that the following two lines of code are equivalent to the Set_Relate:

Set_Attribute DF_FIELD_RELATED_FILE Of Contact.File_Number 1 To Customer.File_number

Set_Attribute DF_FIELD_RELATED_FIELD Of Contact.File_Number 1 To 1

Next the Customer table records are traversed and for every Customer record all the child Contact records are traversed. The first child record is found by using the Attach command to move value of the Customer.Customer_Number column into the Contact.Customer_number column.

Procedure MakeRelationPermanent

Handle hTable

Open Customer

Open Contact Mode DF_EXCLUSIVE

Move Contact.File_Number To hTable

Structure_Start hTable

Set_Attribute DF_FIELD_RELATED_FILE Of hTable 1 To Customer.File_number

Set_Attribute DF_FIELD_RELATED_FIELD Of hTable 1 To 1

Structure_End hTable

Close Customer

End_Procedure // MakeRelationPermanent

In this example the relation from Contact to Customer is made permanent.


DF_FIELD_STORE_TIME

The time portion for a datetime column when creating new records.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Integer, permanent

Access

Read / Write

Values

0 ~ Maximum number of seconds in a day (60 * 60 * 24 = 86400)

Remarks

This attribute sets the time portion of a datetime column. The time portion will be stored upon every save operation for which the column has changed. The value represents the number of seconds in the day where:

  • A negative value less than -1 means that the client system time is used.

  • A value of -1 means that the server time is used.

  • A value between 0 and 86400 (inclusive) means represents the time by the number of seconds in the day.

This attribute can be set both inside and outside a Structure_Start ... Structure_End operation. A more flexible way to manipulate the time portion of a datetime column is the DF_FIELD_TIME attribute.

We recommend using the DF_FIELD_TIME attribute instead of the DF_FIELD_STORE_TIME attribute.


DF_FIELD_TIME

The time portion for a datetime column.

Level

Column

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, temporary

Access

Read / Write

Values

A string in the format hh:mm:ss

Remarks

This attribute can be used to get or set the time portion of a datetime type column. This attribute is more flexible than the DF_FIELD_STORE_TIME attribute. You can set or get this attribute at any time while the DF_FIELD_STORE_TIME is only applied when saving. The string is in the format "hh:mm:ss".

This attribute can be only set outside of a Structure_Start ... Structure_End operation.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The procedure above creates a new table in the SQL Server Northwind database. It is used to store clock in and clock out information of employees. Note that the table creates two columns of type date, but since SQL Server does not support the date type, these will be creates as datetime columns in SQL Server.

Procedure Clockin Integer iEmployee

DateTime dtNow

Begin_Transaction

Clear Clock

Move iEmployee To Clock.Employeeid

Move (CurrentDateTime()) To dtNow

Move (Left(dtNow, Pos(" ", dtNow) - 1)) To Clock.ClockInTime

Set_Attribute DF_FIELD_TIME Of Clock.File_Number 2 To ;

(Right(dtNow, Length(dtNow) - Pos(" ", dtNow)))

Saverecord Clock

End_Transaction

End_Procedure // ClockOut

Procedure ClockOut Integer iEmployee

DateTime dtNow

Boolean bFound

Clear Clock

Move iEmployee To Clock.Employeeid

Fill_Field Clock.File_number 2 With DF_HIGH

Find Gt Clock By 1

Move (Found) To bFound

If (bFound) Begin

Begin_Transaction

Move (CurrentDateTime()) To dtNow

Move (Left(dtNow, Pos(" ", dtNow) - 1)) To Clock.ClockOutTime

Set_Attribute DF_FIELD_TIME Of Clock.File_Number 3 To ;

(Right(dtNow, Length(dtNow) - Pos(" ", dtNow)))

Saverecord Clock

End_Transaction

End

End_Procedure // ClockOut

The sample procedures above use the DF_FIELD_TIME attribute to store information in a Clock record.

Procedure ShowTime

Boolean bFound

DateTime dtIn

DateTime dtOut

String sTime

Clear Clock

Find Gt Clock By 1

Move (Found) To bFound

While (bFound)

If (Clock.Clockintime <> 0 And Clock.Clockouttime <> 0) Begin

Get_Attribute DF_FIELD_TIME Of Clock.File_Number 2 To sTime

If (Pos(".", sTime) > 0) ;

Move (Left(sTime, Pos(".", sTime) - 1)) To sTime

Move (String(Clock.Clockintime) * sTime) To dtIn

Get_Attribute DF_FIELD_TIME Of Clock.File_Number 3 To sTime

If (Pos(".", sTime) > 0) ;

Move (Left(sTime, Pos(".", sTime) - 1)) To sTime

Move (String(Clock.Clockouttime) * sTime) To dtOut

Showln Clock.Employeeid " - " dtIn " " dtOut " - " (dtOut - dtIn)

End

Find Gt Clock By 1

Move (Found) To bFound

End

End_Procedure // ShowTime

In the sample procedure above the contents of the Clock table are listed. Note that in order to be able to move the time portion to a Visual DataFlex datetime variable the fraction of the time must be removed. In SQL Server datetime columns are stored using fractions of seconds, the Visual DataFlex datetime variable does not support time fractions.


DF_FIELD_TYPE

See Also: Get_Attribute, Set_Attribute

The data type of the column.

Level

Column

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_ASCII, DF_BCD, DF_DATE, DF_OVERLAP, DF_TEXT, DF_BINARY

Remarks

The data type of the column. The list of supported type is limited to the original Embedded Database types. Most non Embedded Databases support a larger list of types. The Visual DataFlex Database API and runtime directly support the types listed here. Connectivity Kits will project the back end type onto one of the supported types. An integer column, for example, will be projected onto a DF_BCD column. The SQL based Connectivity Kits allow fine tuning the back end type via the column attributes DF_FIELD_NATIVE_TYPE and DF_FIELD_NATIVE_TYPE_NAME.

This attribute can be only set inside of a Structure_Start ... Structure_End operation.

The meaning of the different values is:

Enum value

Short

Description

DF_ASCII

Ascii

ASCII columns may contain any characters and are used when numeric formatting will not be required.

DF_BCD

Numeric

Numeric columns may contain only the numbers 0 thru 9, a period, and a plus or minus sign.

DF_DATE

Date

Dates are input and output as they appear (month/day/year, etc.), but in most database systems, such as the embedded database, they are stored in a different way.

The Embedded Database stores dates as Julian numbers representing the number of days since the first day of Year 1.

DF_OVERLAP

Overlap

Logical columns defined in terms of other physical columns, which must be contiguous. They do not take up space in the table, as they are "virtual" columns.

For Overlap columns, you must specify the start position of the column by specifying the offset (DF_FIELD_OFFSET) the length of the column is defined by specifying the length (DF_FIELD_LENGTH) of the column.

The support of multi segment relationships in VDF11 makes the use overlap columns superfluous.

DF_TEXT

Text

Text columns (often called "memo" columns) are for storing large amounts of text in ASCII format.

DF_BINARY

Binary

Binary columns are used to store any characters, but in a binary format. Binary columns are used primarily for storing graphics as bit images.

DF_TEXT and DF_BINARY in the Embedded Database

Note that for the Embedded database driver, the usable size of a DF_TEXT or DF_BINARY column will be two bytes less than the declared length. Thus, if you declare a text column with a size of 256 bytes, you will be able to store up to 254 characters in this column. The amount of space occupied on the disk is the actual length of the contents, if any, plus 2 bytes, unless compression is not turned on. In that event, the amount of space occupied will be the declared length of the column, regardless of whether the column has any content.

DF_TEXT and DF_BINARY column length in SQL based CK’s

The maximum size of text and binary columns varies greatly between different back ends. For the Embedded Database it is 16kb, for SQL Server it is 2Gb. When opening a table in such a back end, it usually reports the column length as 2Gb. When connecting to a table through a SQL based connectivity kit, the size of such columns will be truncated at 16kb by default. You can increase this size by editing the Field_Length intermediate file keyword or setting the DF_FIELD_LENGTH attribute to the desired length when creating the column. Note that binary columns are part of a table’s buffer and the size you specify for it will be allocated in memory when the table is opened.

Procedure ShowTypes Handle hTable

Integer iNumColumns

Integer iColumn

Integer iType

String sTable

String sColumn

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Types for table " sTable ":"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_FIELD_TYPE Of hTable iColumn To iType

Show " " sColumn

Case Begin

Case (iType = DF_ASCII)

Showln " - Ascii"

Case Break

Case (iType = DF_BCD)

Showln " - Numeric"

Case Break

Case (iType = DF_DATE)

Showln " - Date"

Case Break

Case (iType = DF_OVERLAP)

Showln " - Overlap"

Case Break

Case (iType = DF_TEXT)

Showln " - Text"

Case Break

Case (iType = DF_BINARY)

Showln " - Binary"

Case Break

Case End

Loop

End_Procedure // ShowTypes

The sample procedure above shows the type for all columns in the passed table.

Procedure AddTurnover

Handle hTable

Integer iColumn

Open Customer Mode DF_EXCLUSIVE

Move Customer.File_number To hTable

Structure_Start hTable

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "TurnOver"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_PRECISION Of hTable iColumn To 2

Structure_End hTable

End_Procedure // AddTurnover

The sample procedure above adds a numeric (8.2) column called TurnOver to the Customer table.

Procedure CreateTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "RIMSample.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To True

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "RIMSample"

Set_Attribute DF_FILE_GENERATE_RECORD_ID_METHOD Of hTable To RIM_IDENTITY_COLUMN

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To 0

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 4

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Name"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (5 * (2^20))

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "RimSample001"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:RIMSample"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "RIM sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "RIMSamp"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "RIMSamp.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

This example creates a SQL Server table with a text column of 5 megabytes.


DF_FILE_ALIAS

See Also: Get_Attribute, Set_Attribute, Alias Tables, Alias Tables and DDOs, DF_FILE_LOGICAL_NAME, DF_FILE_PHYSICAL_NAME, DF_FILE_ROOT_NAME, DF_FILE_DISPLAY_NAME

Indicates whether the table is an alias.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, temporary

Access

Read / Write

Values

DF_FILE_ALIAS_DEFAULT, DF_FILE_IS_MASTER, DF_FILE_IS_ALIAS

Remarks

Alias tables are needed when multiple logical tables map to one physical table. In the Visual DataFlex environment an alias is created by placing the same physical table in multiple locations in the filelist. This is done by entering the same physical name (DF_FILE_ROOT_NAME) in the filelist slot while entering different user (DF_FILE_DISPLAY_NAME) and table (DF_FILE_LOGICAL_NAME) names. Alias tables allow a program to use multiple global table buffers for the same physical table. See Alias Tables for a detailed description.

DF_FILE_ALIAS allows a program to have multiple open instances of a given table without causing deadlocks against itself. When a table has been opened more than once, one table must have DF_FILE_ALIAS set to DF_FILE_IS_MASTER. Each additional instance of the opened table must have DF_FILE_ALIAS set to DF_FILE_IS_ALIAS.

DF_FILE_ALIAS_DEFAULT indicates that the table is neither an alias nor a master file. This value is the default for this attribute.

This attribute can be only set outside of a Structure_Start ... Structure_End operation.

The recommended placement for the code setting this attribute in a Windows or Web Application is in the DataDictionary class, at the very top of the methods section in Database Builder, before the DataDictionary class definition.

Assuming we make an alias table for the Customer table and name it Cust2, we would place the following code into the methods section of the Customer and Cust2 DataDictionaries, respectively.

In the master file DataDictionary (Customer table in this example):

Set_Attribute DF_FILE_ALIAS of Customer.File_Number to DF_FILE_IS_MASTER

Class Customer_DataDictionary is a DataDictionary

…

In the alias file DataDictionary (Cust2 table in this example):

Set_Attribute DF_FILE_ALIAS of Cust2.File_Number to DF_FILE_IS_ALIAS

Class Cust2_DataDictionary is a DataDictionary

…


DF_FILE_CHANGED

See Also: Get_Attribute, Set_Attribute

Indicates whether the data in the table’s record buffer has been changed.

Level

Table

Supported by

All Connectivity Kits

Type

Boolean, temporary

Access

Read Only

Values

True, False

Remarks

The DF_FILE_CHANGED attribute indicates if the global table buffer has changed since the last clear or successful find operation. Clearing the buffer or doing a successful find will set the attribute to false. Moving data to the buffer will set the attribute will to true.

If data is moved to the buffer that is already there, this is not regarded as a change. So if an ASCII column has value “A value” after a successful find, moving “A value” to that column will not set the DF_FILE_CHANGED attribute to true.

Procedure CheckUppercased

Integer iTotalRecords

Integer iBadRecords

Boolean bFound

Boolean bChanged

Move 0 To iTotalRecords

Move 0 To iBadRecords

Clear Salesp

Find Gt Salesp By 1

Move (Found) To bFound

While (bFound)

Move (Uppercase(Salesp.Id)) To Salesp.Id

Get_Attribute DF_FILE_CHANGED Of Salesp.File_number To bChanged

If (bChanged) ;

Increment iBadRecords

Increment iTotalRecords

Find Gt Salesp By 1

Move (Found) To bFound

End

If (iBadRecords > 0) ;

Showln iBadRecords " of " iTotalRecords " are not properly uppercased."

Else ;

Showln "All records are properly uppercased."

End_Procedure // CheckUppercased

The sample procedure above runs a check on the Salesp table. It checks if the Salep.Id column contains an uppercased value for all records.


DF_FILE_COMMITTED

See Also: Get_Attribute, Set_Attribute

Indicates whether the last end_transaction was successful on the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read Only

Values

True, False

Remarks

When a table is opened, its DF_FILE_COMMITTED attribute will be set to true. Begin_Transaction will set the attribute false for every open table. End_Transaction will set the attribute for every open table to true when successful.

If a file's DF_FILE_TRANSACTION attribute has a value of DF_FILE_TRANSACTION_NONE, then the file's DF_FILE_COMMITTED attribute will always have a value of True.

This attribute will rarely be used. To find out if a transaction was successful use the DF_TRANSACTION_ABORT attribute.

Procedure ShowUncommitted

Handle hTable

Boolean bCommitted

Boolean bAborted

String sTable

Get_Attribute DF_TRANSACTION_ABORT To bAborted

If (bAborted) Begin

Showln "Tables that are uncommitted are:"

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_COMMITTED Of hTable To bCommitted

If (Not(bCommitted)) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln " " sTable

End

End

Until (hTable = 0)

End

End_Procedure // ShowUncommitted

The sample procedure above shows a list of tables that have their DF_FILE_COMMITTED attribute set to false.


DF_FILE_COMPRESSION

See Also: Get_Attribute, Set_Attribute

The type of table compression used by the table.

Level

Table

Supported by

The Embedded Database and the Pervasive.SQL Connectivity Kit

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_FILE_COMPRESS_NONE, DF_FILE_COMPRESS_FAST, DF_FILE_COMPRESS_STANDARD, DF_FILE_COMPRESS_CUSTOM

Remarks

The Embedded Database and Pervasive.SQL support table compression. When table compression is used the amount of data that a table needs on disk is reduced. The way the data in the table is compressed is setup by the DF_FILE_COMPRESSION attribute.

This attribute can be only set inside of a Structure_Start ... Structure_End operation.

The Pervasice.SQL Connectivity Kit supports the values DF_FILE_COMPRESS_NONE and DF_FILE_COMPRESS_STANDARD.

Value | Meaning
DF_FILE_COMPRESS_NONE | Indicates there will be no data compression.
DF_FILE_COMPRESS_STANDARD | Uses Pervasive.SQL’s table compression.

The Embedded Database supports all possible values. The meaning of the values form the Embedded Database is:

Value | Meaning
DF_FILE_COMPRESS_NONE | Indicates there will be no data compression.
DF_FILE_COMPRESS_FAST | Uses run length encoding for data compression. In run length encoding a repeating sequence of the same characters is replaced by the number the character is repeated and the character itself. So a value of “aaaaaaaaaa” would be replaced by “10a”.
DF_FILE_COMPRESS_STANDARD | Uses Huffman encoding compression. The frequency table used is based in the English language.
DF_FILE_COMPRESS_CUSTOM | Uses Huffman encoding compression. The frequency table used is based on the contents of the table. When custom compression is used on tables whose contents changes frequently it is possible to recompress the table. Recompressing will rebuild the frequency table and then recompress the data.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. That is why SQL based Connectivity Kits will return DF_FILE_COMPRESS_NONE for every table accessed, trying to set the attribute will be ignored.

Procedure RecompressTables

Handle hTable

Handle hStruct

Integer iCompression

String sTable

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

If (Uppercase(sTable) <> "FLEXERRS") Begin

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_COMPRESSION Of hTable To iCompression

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

If (iCompression = DF_FILE_COMPRESS_CUSTOM) Begin

Showln "Recompressing table: " sTable

Move hTable To hStruct

Structure_Start hStruct

Structure_End hStruct DF_STRUCTEND_OPT_RECOMPRESS

End

Else Begin

Showln "Table " sTable " not custom compressed."

Close hTable

End

End

End

Until (hTable = 0)

End_Procedure // RecompressTable

The sample procedure above will recompress all tables that use custom compression.


DF_FILE_DATABASE_ID

The handle to the database connection to use with CLI_Get_Database_Attribute.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Handle, temporary

Access

Read Only

Values

Any valid handle

Remarks

This table attribute returns the handle to the database connection of the table. This handle can be used in subsequent CLI_Get_Database_Attribute commands.

Procedure ShowDBTypes String sDriver Handle hDatabase

Integer iNumTypes

Integer iType

String sTypeName

Handle hTypeID

Boolean bAutoinc

CLI_Get_Database_Attribute sDriver DF_DATABASE_NUMBER_TYPES hDatabase To iNumTypes

Showln "The database has: " iNumTypes " types."

For iType From 0 To (iNumTypes - 1)

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_NAME hDatabase iType To sTypeName

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_ID hDatabase iType To hTypeID

CLI_Get_Database_Attribute sDriver DF_DATABASE_TYPE_AUTOINC hDatabase iType To bAutoinc

Showln " " iType ", " sTypeName ", " hTypeID ", " ;

(If(bAutoinc, "Auto Increment", ""))

Loop

End_Procedure // ShowDBTypes

Procedure ShowTableDBTypes Handle hTable

Handle hDatabase

String sDriver

Get_Attribute DF_FILE_DATABASE_ID Of hTable To hDatabase

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

Send ShowDBTypes sDriver hDatabase

End_Procedure // ShowTableDBTypes

The sample procedures above show all supported types in the database of a table.


DF_FILE_DISPLAY_NAME

See Also: Get_Attribute, Set_Attribute, DF_FILE_PHYSICAL_NAME

The table’s user-display name, as stored in the file-list file.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

A string containing the table's user-display name.

Remarks

The display name can contain alphanumeric characters as well as ASCII characters above 32 and be up to 31 characters long. The display name is intended to be a phrase or description associated with a table and is typically used for prompts in tools (Database Builder, Database Explorer and so forth).

Unlike other permanent table level attributes, the filelist attributes (DF_FILE_DISPLAY_NAME, DF_FILE_ROOT_NAME and DF_FILE_LOGICAL_NAME) can be set outside of a Structure_Start ... Structure_End operation. These attributes are actually stored in the filelist and not in the database or table.

To add a table to an existing filelist, the 3 filelist attributes must be set at the same time. To remove a table from the filelist the 3 filelist attributes must be set to an empty string.

Procedure ShowFilelistNames

Handle htable

String sRoot

String sDisplay

String sTable

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Get_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln hTable ", " sRoot ", " sDisplay ", " sTable

End

Until (hTable = 0)

End_Procedure // ShowFilelistNames

The sample procedure above show all the filelist attributes.

Procedure NewEntry Handle hTable String sRoot String sDisplay String sTable

Set_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

End_Procedure // ShowFilelistNames

The sample procedure above creates a new filelist entry at a given slot. It can also be used to remove a filelist entry by passing empty strings for the three filelist attributes.

Procedure CreateNewFilelist String sNewList

Handle hoWorkspace

String sPath

Integer iMaxSlots

//*** Make sure new filelist comes in first directory of datapath

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - sNewList) To sPath

//*** Create the disk file

Direct_Output sPath

Write "filelist.cfg"

Close_output

//*** Use the disk file as fileist

Set_attribute DF_FILELIST_NAME To sPath

//*** Create all the slots

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iMaxSlots

Send NewEntry iMaxSlots "" "" ""

End_Procedure // CreateNewFilelist

The sample procedure above uses the filelist attributes to create a new empty filelist. It calls the NewEntry procedure defined above.


DF_FILE_DRIVER

See Also: Get_Attribute, Set_Attribute

The name of the database driver for the table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read Only

Values

Any valid database driver name.

Remarks

The attribute shows the name of the database driver/Connectivity Kit used to access the table. This is the name of the dynamically loadable module (dll). The value of this attribute can be:

Value | Driver
DATAFLEX | Embedded Database
DB2_DRV | IBM DB2 Universal Database
DFBTRDRV | Pervasive.SQL
MSSQLDRV | Microsoft SQL Server
ODBC_DRV | ODBC

The value of the attribute cannot be set directly. It is set indirectly when creating a new table. The driver to use for a new table is passed to the Structure_Start command. To create a new ODBC table for example one would need to issue:

Handle hTable

Move 0 To hTable

Structure_Start hTable "ODBC_DRV"

Procedure ShowDriver

Handle hTable

String sTable

String sDriver

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

Showln sTable " -- " sDriver

End

Until (hTable = 0)

End_Procedure // ShowUncommitted

The sample procedure above shows the driver for every open table.


DF_FILE_DUMMY_UPDATE_COLUMN

The number of the dummy update column.

Level

Table

Supported by

The ODBC Connectivity Kit

Type

Integer, permanent

Access

Read / Write

Values

1 .. number of columns in the table.

Remarks

The attribute stores the number of the column used when the dummy update mechanism is active. When using ODBC, it is possible to connect to a wide variety of databases, and even non databases. The locking mechanisms supported by these databases vary from sophisticated, to simple to none at all. The ODBC Connectivity Kit attempts to use a mechanism called positioned update. Desktop databases usually do not support positioned updates. In these cases, a different update mechanism, called SQLSetPos that allows for records to be locked, is used. If the back end does not support exclusive locks on records, the Connectivity Kit will perform a “dummy update” to lock the record. This mechanism will ensure that records are locked when they are found while in a transaction. Since most ODBC drivers do not support table locking, there is a difference between Visual DataFlex locking and ODBC locking.

The dummy update mechanism updates a record (without changing any field value) directly after it has been found. By default, the record identity column is set to the value just got from the find. This happens in the find logic. In a standard table there is no record identity and the dummy update column should be set. In a recnum table, if the record identity column is not "updatable" (it could be an auto-increment, for example), you can set up an alternative column by using the attribute.

Usually this will be set in the intermediate file keyword by using the keyword Dummy_Update_Column.

Note that you only need to set a dummy update column if the database only supports SQLSetPos and it does not support exclusive locks to be set by SQLSetPos.

See Transactions for more information.


DF_FILE_FETCH_ALL_COLUMNS

Indicates if selective column fetching is on or off for the table.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

This table attribute indicates if selective column fetching is ON or OFF for the table. When a table is opened the attribute is automatically set to true (all columns will be fetched after opening).

Selective Column Fetching (SCF) offers a way to programmatically influence the number of columns that are fetched from the back-end. This feature is especially useful when looping through records. It is supported by the SQL Connectivity Kits. Limiting the number of columns that are fetched reduces the amount of data that is sent from the database server to the client, thus improving performance.

There are two levels in which SCF can be controlled. It can be switched ON or OFF at the table level using the DF_FILE_FETCH_ALL_COLUMNS attribute. It can be switched ON or OFF for individual columns using the DF_FIELD_FETCH_STATE attribute.

This attribute can be only set outside of a Structure_Start ... Structure_End operation.

For more information on using this attribute, see the Selective Column Fetching section.


DF_FILE_GENERATE_RECORD_ID_METHOD

Indicates how the record identity column of a recnum table is filled.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Enumeration list, permanent

Access

Read / Write

Values

RIM_NONE, RIM_IDENTITY_COLUMN, RIM_EXTERNAL, RIM_DISPENSER_TABLE

Remarks

The Generate_Record_ID_Method setting indicates how the record identity column is filled. There are four possible values:

Value

Meaning

RIM_NONE

Record identifiers are not generated by the back-end. Record identity values must be filled by giving the columns an explicit value in the application.

When a new record is created, the value in the record identifier column is passed to the back-end.

RIM_IDENTITY_COLUMN

The record identifier is filled by the back-end using the features the server provides for this (identity columns).

When a new record is created, the value in the record identifier column is not passed to the back-end.

This value is only applicable to the SQL Server and DB2 Connectivity Kits.

RIM_EXTERNAL

The record identifier is generated by the back-end but in some other way than using identity columns. For example: one could use triggers.

When a new record is created, the value in the record identifier column is not passed to the back-end.

RIM_DISPENSER_TABLE

The record identifier value is dispensed from a table that keeps track of the next available record identity value. The dispenser logic is enforced using triggers when records are inserted.

When a new record is created, the value in the record identifier column is not passed to the back-end.

When a table is opened a check will be done to see if the triggers, the dispenser table and the record in the dispenser table for the table being opened exist. If one (or more) of these is missing, it will automatically be created.

This value is only applicable to the DB2 Connectivity Kit.

This attribute can be only set inside of a Structure_Start ... Structure_End operation. The value of this attribute is stored in the intermediate file using the intermediate file keyword Generate_Record_ID_Method.

Setting the attribute to RIM_IDENTITY for a table accessed through the SQL Server or DB2 CK will ensure the record identity column is created with the identity attribute set. This means the column is automatically filled by the back end.

Procedure CreateTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "RIMSample.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To True

Set_Attribute DF_FILE_LOGIN Of hTable To "SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "RIMSample"

Set_Attribute DF_FILE_GENERATE_RECORD_ID_METHOD Of hTable To RIM_IDENTITY_COLUMN

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To 0

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 4

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Name"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (5 * (2^20))

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "RimSample001"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:RIMSample"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "RIM sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "RIMSamp"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "RIMSamp.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

This example creates a SQL Server recnum table with a hidden record identity (primary_index = 0) column. Hidden record identity columns are called “RECNUM”. The column has its DF_FILE_GENERATE_RECORD_ID_METHOD set to RIM_IDENTITY_COLUMN so the identity column has the SQL Server identity attribute set.


DF_FILE_GET_RID_AFTER_CREATE

Indicates if the value of the record identity column of a recnum table is filled after creating a new record.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, permanent/temporary

Access

Read / Write

Values

True, False

Remarks

When set to true, after records are created in a table, the assigned record identity is moved to the record buffer used by DataFlex. Setting this attribute to false will switch off moving the new identity to the record buffer. This eliminates a Client/Server communication roundtrip, thus speeding up performance when creating records.

For the SQL Server Connectivity Kit the way the record identity is moved to the buffer depends on the setting of the DF_FILE_GENERATE_RECORD_ID_METHOD attribute. If that attribute is set to RIM_IDENTITY_COLUMN, the Ident_Current function of SQL Server will be used (@@IDENTITY in pre SQL Server 2000 version).

For the DB2 Connectivity Kit the way the record identity is moved to the buffer depends on the setting of the DF_FILE_GENERATE_RECORD_ID_METHOD attribute. If that attribute is set to RIM_IDENTITY_COLUMN the IDENTITY_VAL_LOCAL function of DB2 will be used. When the DF_FILE_GENERATE_RECORD_ID_METHOD attribute is set to RIM_DISPENSER_TABLE, the record identity value will be selected from the dispenser table.

For all SQL connectivity Kits the way the record identity is moved to the buffer when the DF_FILE_GENERATE_RECORD_ID_METHOD attribute is set to RIM_NONE or RIM_EXTERNAL is the same, the maximum value of the record identity column is used.

Be aware that setting this attribute to false can result in unwanted or erroneous behavior. Switching off the move behavior can speed up bulk creation of records. Normally you will only use this attribute from within the program logic where it will be used in massive record creations. In such cases, it will be switched off, then the records are created after which the attribute is switched back ON.

This attribute can be set both inside and outside of a Structure_Start ... Structure_End operation. The value of this attribute is stored in the intermediate file using the intermediate file keyword Get_RID_After_Create.

Procedure CopyRecord Handle hSource Handle hDest

Integer iNumColumns

Integer iColumn

String sValue

Get_Attribute DF_FILE_NUMBER_FIELDS Of hSource To iNumColumns

Begin_Transaction

Clear hDest

For iColumn From 1 To iNumColumns

Get_Field_value hSource iColumn To sValue

Set_Field_Value hDest iColumn To sValue

Loop

SaveRecord hDest

End_Transaction

End_Procedure // CopyRecord

Procedure CopyTable Handle hSource Handle hDest

Integer iIndex

Boolean bFound

Boolean bOrgGetRIDAfterCreate

//*** Primary index attribute not supported by Embedded Database

//*** and Pervasive.SQL, avoid errors.

Set_Attribute DF_REPORT_UNSUPPORTED_ATTRIBUTES To False

Get_Attribute DF_FILE_PRIMARY_INDEX Of hSource To iIndex

Set_Attribute DF_REPORT_UNSUPPORTED_ATTRIBUTES To False

//*** Reset DF_FILE_GET_RID_AFTER_CREATE

Get_Attribute DF_FILE_GET_RID_AFTER_CREATE Of hDest To bOrgGetRIDAfterCreate

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE Of hDest To False

//*** Loop through all records from source

Clear hSource

Repeat

vFind hSource iIndex Gt

Move (Found) To bFound

If (bFound) ;

Send CopyRecord hSource hDest

Until (Not(bFound))

//*** Reset DF_FILE_GET_RID_AFTER_CREATE

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE Of hDest To bOrgGetRIDAfterCreate

End_Procedure // CopyTable

The two procedures above copy all data from one table to another. The DF_FILE_GET_RID_AFTER_CREATE attribute of the destination table (the table where records are created) is switched off before the copy process starts and reset to its original value after the copy process finishes.


DF_FILE_HANDLE_TYPE

See Also: Get_Attribute, Set_Attribute

The type of a table handle.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, temporary

Access

Read Only

Values

DF_FILE_HANDLE_BAD, DF_FILE_HANDLE_CLOSED, DF_FILE_HANDLE_OPENED, DF_FILE_HANDLE_EXISTING_RESTRUCTURE. DF_FILE_HANDLE_NEW_RESTRUCTURE

Remarks

This attribute indicates the type of the handle. If the file handle is invalid, the attribute's value will be DF_FILE_HANDLE_BAD. The value will be DF_FILE_HANDLE_CLOSED or DF_FILE_HANDLE_OPENED, respectively, for an unopened file and a file opened with open.

When restructuring an existing table, there are two table handles, the handle that points to the original table and the one that points to the table that is being restructured. A code fragment that shows two such handles is shown below:

Handle hTable

Handle hStruct

Open hTable Mode DF_EXCLUSIVE

Move hTable To hStruct

Structure_Start hStruct

The value of the DF_FILE_HANDLE_TYPE for hTable will be DF_FILE_HANDLE_OPENED, the value for hStruct will be DF_FILE_HANDLE_EXISTING_RESTRUCTURE.

When creating a new table, there will be one handle that points to the table to be created. A code fragment that shows such a handle to create a Pervasive.SQL table is shown below:

Handle hStruct

Structure_Start hStruct “DFBTRDRV”

The value of the DF_FILE_HANDLE_TYPE for hStruct will be DF_FILE_HANDLE_NEW_RESTRUCTURE.

Procedure ShowHandleTypes

Handle hTable

Integer iHandleType

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_HANDLE_TYPE Of hTable To iHandleType

Case Begin

Case (iHandleType = DF_FILE_HANDLE_BAD)

Showln hTable " BAD"

Case Break

Case (iHandleType = DF_FILE_HANDLE_CLOSED)

Showln hTable " CLOSED"

Case Break

Case (iHandleType = DF_FILE_HANDLE_OPENED)

Showln hTable " OPENED"

Case Break

Case (iHandleType = DF_FILE_HANDLE_EXISTING_RESTRUCTURE)

Showln hTable " EXISTING RESTRUCTURE"

Case Break

Case (iHandleType = DF_FILE_HANDLE_NEW_RESTRUCTURE)

Showln hTable " NEW RESTRUCTURE"

Case Break

Case End

End

Until (hTable = 0)

End_Procedure // ShowHandleTypes

The procedure above will show the value of DF_FILE_HANDLE_TYPE for every table defined in the filelist.


DF_FILE_INTEGRITY_CHECK

See Also: Get_Attribute, Set_Attribute, DF_HIGH_DATA_INTEGRITY

Indicates whether the file should be integrity-checked during the normal course of operation.

Level

Table

Supported by

The Embedded Database

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

The Embedded Database implements header integrity checking as Cyclic Redundancy Check (CRC) header checking. An Embedded Database table’s data is stored in a disk file with the extension .dat. This disk file is made up of a header, followed by the actual data. When header integrity checking is on, a CRC is computed over the header and is stored in a separate disk file with extension .hdr. Every time the header of the table is updated, the .hdr disk file is also updated. When the table is opened, its header is checked against the .hdr information. If the information does not match, an error (DFERR_HEADER_CRC_BAD) is generated.

If the integrity checking results in the DFERR_HEADER_CRC_BAD error, the table can be repaired using Database Builder (Maintenance .. Repair Damaged headers) or by calling the FLEX_GET_REPAIRS_NEEDED and FLEX_REPAIR_FILE pass through functions via Call_Driver.

This attribute can be only set inside of a Structure_Start ... Structure_End operation.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. It however does not make any sense in some back ends. That is why SQL based Connectivity Kits and the Pervasive.SQL Connectivity Kit will return false for every table accessed, trying to set the attribute will be ignored.

Procedure RepairDamagedHeaderTables

Handle hTable

Boolean bCheckOn

String sRoot

Integer iRepairNeeded

Integer iVoid

String sVoid

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_INTEGRITY_CHECK Of hTable To bCheckOn

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

If (bCheckOn) Begin

Call_Driver 0 "DATAFLEX" Function FLEX_GET_REPAIRS_NEEDED Callback 0 ;

Passing sRoot sVoid 0 Result iRepairNeeded

If (iRepairNeeded <> FLEX_HEADER_OK) Begin

Showln sRoot " is being repaired"

Call_Driver 0 "DATAFLEX" Function FLEX_REPAIR_FILE Callback 0 ;

Passing sRoot sVoid 0 Result iVoid

End

Else ;

Showln sRoot " has integrity on, does not need repairing."

End

Else ;

Showln sRoot " does not have integrity on."

End

Until (hTable = 0)

End_Procedure // RepairDamagedHeaderTables

The sample procedure above checks all tables in the filelist. If they have integrity checking switched on it checks if repairs are needed, if so, the table is repaired.


DF_FILE_IS_SYSTEM_FILE

See Also: Get_Attribute, Set_Attribute

Indicates if the table is a system table.

Level

Table

Supported by

All Connectivity Kits

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

A system table is a table with a single record, usually used to store global counters. When a system table is opened, the first and only record is automatically loaded into the file buffer.

Database drivers are not required to enforce that system tables have one record and one record only. If a program creates a record in a system table that already contains a record, the driver will not generate an error. At this moment no database driver, including the driver for the Embedded Database, enforces this rule.

The SQL based Connectivity Kits only support tables with at least one unique index. System tables accessed through these CK’s must have an index.

System tables are typically used to record global information that is static for an application’s installation. Information like company name, installed modules, configuration settings is often stored in a system table. The DataDictionary class supports a mechanism to create auto increment columns by using a system table to store the last assigned number via the Define_Auto_Increment command.

Using a system table to assign auto increment values in a record locking environment can restrict concurrency. The system table record will be involved, and locked, in every transaction in which records using the auto increment feature are created. This results in a system in which only one record creating transaction can be handled at any given moment. The system table acts a “transaction serializer” in such an environment. To make optimal use of the record locking capabilities one could consider alternative mechanisms to assign auto increment values. Possibilities are to use the back ends auto increment features (if present) or move to a table that uses one record per auto increment value. This is not an issue when using the Embedded Database, it uses table locking. The Pervasive.SQL Connectivity Kit supports both table and record locking. The SQL based Connectivity Kits use record locking.

This attribute can only be set inside a Structure_Start ... Structure_End operation. For the SQL based Connectivity Kits, it is possible to set this attribute outside a structure operation. This support is intended to be used when opening tables without intermediate files. Be aware that since you can only set this attribute after the table is open, the automatic find that normally happens when a system table is opened, does not take place when setting the attribute in this way.

Procedure ShowSystemTables

Handle hTable

Boolean bSystemTable

String sTable

Integer iStatus

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_IS_SYSTEM_FILE Of hTable To bSystemTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_STATUS Of hTable To iStatus

If (bSystemTable) ;

Showln sTable " is a system table and its buffer is ;

" (If(iStatus = DF_FILE_ACTIVE, "active", "NOT active"))

Else ;

Showln sTable " is NOT a system table and its buffer is ;

" (If(iStatus = DF_FILE_ACTIVE, "active", "NOT active"))

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowSystemTables

The sample procedure above will open every table in the filelist and check if it is a system table. Next to that it will show the status of the table’s (global) record buffer.

Procedure CreateSystemTable

Handle hTable

Integer iColumn

Handle hoWorkspace

String sPath

String sOrgDirectory

//*** Make sure table comes in first directory of datapath by making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create physical table contacts

Move 0 To hTable

Structure_Start hTable "DATAFLEX"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "SysTable"

Set_Attribute DF_FILE_IS_SYSTEM_FILE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "CompanyName"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "OrderNumber"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Structure_End hTable

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "SysTable"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "System table sample"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "SysTable"

Open hTable

//*** Generate fd

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "SysTable.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

//*** Create the record!

Clear hTable

Begin_Transaction

Set_Field_Value hTable 1 To "Enter company name here..."

SaveRecord hTable

End_Transaction

Close hTable

End

End_Procedure // CreateSystemTable

This sample procedure creates a system table called SysTable, places it in the filelist and creates it one (and only) record.


DF_FILE_LAST_INDEX_NUMBER

See Also: Get_Attribute, Set_Attribute, DF_INDEX_NUMBER_SEGMENTS

The number of the last index of the file.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read Only

Values

0 ..

Remarks

The DataFlex way to handle indices is by assigning a number to an index and using that number to identify the sort order used in find operations. The Embedded Database uses this concept and identifies an index by using an index number. Pervasive.SQL also uses index numbers to identify its indices. In databases accessed through the SQL based Connectivity Kits, indices are usually identified by a name. The SQL based Connectivity Kits offer ways to map an index name to an index number.

Index numbering does not have to be continuous; the range of index numbers defined for a table can contain “holes”. The DF_FILE_LAST_INDEX_NUMBER attribute returns the last index number actually in use. To test if an index exists use the DF_INDEX_NUMBER_SEGMENTS attribute; when it returns 0 (zero) the index does not exist, when it returns a value greater than 0 (zero) the index does exist.

This attribute cannot be set directly. It is manipulated by using the Create_index and Delete_index commands.

In some database systems, database files (e.g. DataFlex files) can have index "holes". As an example, a DataFlex file may have Indexes 1, 2, 4, and 8. In this case, there would be no Index Number 3, 5, 6 and 7. For such a file, DF_FILE_LAST_INDEX_NUMBER would be 8. To determine which index numbers are used and which are not, examine the DF_INDEX_NUMBER_SEGMENTS attribute for each index number. Those showing 0 are unused (no segments).

Procedure ShowIndices Handle hTable

String sTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

String sIndex

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Index information for table: " sTable

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index number: " iIndex " (" sIndex ")"

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowIndices

The sample procedure above shows all indices of a table, it presents an index by the names of the segments separated by commas.


DF_FILE_LOCK_TYPE

See Also: Get_Attribute, Set_Attribute

Specifies the locking type to be used on the table.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_LOCK_TYPE_NONE, DF_LOCK_TYPE_FILE, DF_LOCK_TYPE_RECORD

Remarks

If a table’s DF_FILE_LOCK_TYPE attribute has a value of DF_LOCK_TYPE_NONE, then no locking will be done for it. Using this value causes the value of the DF_FILE_MULTIUSER attribute to be set to DF_FILE_USER_SINGLE. A value of DF_LOCK_TYPE_FILE indicates locking will be done at the table level, and a value of DF_LOCK_TYPE_RECORD indicates that locking will be done at the record level.

Note that setting a table’s lock type to DF_LOCK_TYPE_NONE can result in data corruption. It is only safe to do if the table is never ever updated (no records are created, updated or deleted) or the application updating the table is doing so in true single user mode (only one process is accessing the table). Since locking is an expensive operation, this setting was used to tune performance. This is no longer needed for applications that use DataDictionary or DataSet objects. These objects use smart file mode to ensure only those tables that are actually updated are locked.

The DF_FILE_LOCK_NONE attribute value is left over from the time when there where single user/process operating systems. Modern operating systems allow multiple processes to run simultaneously. When two (or more) processes access a table at the same time, they are in fact using the table in a multi user fashion which requires a form of locking.

For the Embedded Database, the locking type must be set to either DF_LOCK_TYPE_FILE or DF_LOCK_TYPE_NONE. The locking type DF_LOCK_TYPE_NONE can only be used with applications that do not use DataSets or Data Dictionaries.

For Pervasive.SQL, the DF_FILE_LOCK_TYPE attribute cannot be set. It is possible to set the lock type to no locking, table locking or record locking but not on a table by table basis. The lock type is a global setting for the Pervasive.SQL Connectivity Kit. It can be set using the DFBTR_SET_TRANSACTION_TYPE command. The value returned for the attribute depends on what was passed to the DFBTR_SET_TRANSACTION_TYPE command in the following way:

Pervasive.SQL lock type | Attribute value
DFBTRTT_NONE | DF_LOCK_TYPE_NONE
DFBTRTT_EXCLUSIVE | DF_LOCK_TYPE_FILE
DFBTRTT_CONCURRENT | DF_LOCK_TYPE_RECORD

For tables accessed through the SQL Based Connectivity Kits the DF_FILE_LOCK_TYPE attribute an attempt to set the attribute will be ignored. It will always return the value DF_LOCK_TYPE_RECORD.

This attribute can only be set inside a Structure_Start ... Structure_End operation. We expect this attribute will very rarely be set. The default value will be used in most cases.

Procedure ShowPotentialProblemTables

Handle hTable

Integer iLockType

String sTable

Integer iDangerous

Move 0 To hTable

Move 0 To iDangerous

Repeat

Get_Attribute DF_FILE_NEXT_USED of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOCK_TYPE Of hTable To iLockType

Get_Attribute DF_FILE_LOGICAL_NAME of hTable To sTable

If (iLockType = DF_LOCK_TYPE_NONE) Begin

Showln "DANGER! Table " sTable " will not be locked!"

Increment iDangerous

End

Close hTable

End

Until (hTable = 0)

If (iDangerous = 0) ;

Showln "All tables in the filelist will be properly locked."

End_Procedure // ShowPotentialProblemTables

The sample procedure above will check every table in the filelist for its lock type setting. When tables exists that have their lock type set to DF_LOCK_TYPE_NONE these will be reported as potential problem tables.


DF_FILE_LOGICAL_NAME

See Also: Get_Attribute, Set_Attribute, DF_FILE_PHYSICAL_NAME

The logical file name stored in the file list for the table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

The logical name can contain alphanumeric characters as well as ASCII characters above 32 and be up to 8 characters long. The exclamation point may only be used as the last character in this string.

Remarks

The logical name can contain alphanumeric characters as well as ASCII characters above 32 and be up to 8 characters long. The logical name is the name used in the source code to identify a table.

Unlike other permanent table level attributes, the filelist attributes (DF_FILE_DISPLAY_NAME, DF_FILE_ROOT_NAME and DF_FILE_LOGICAL_NAME) can be set outside of a Structure_Start ... Structure_End operation. These attributes are actually stored in the filelist and not in the database or table.

To add a table to an existing filelist, the 3 filelist attributes must be set at the same time. To remove a table from the filelist the 3 filelist attributes must be set to an empty string.

Procedure ShowFilelistNames

Handle htable

String sRoot

String sDisplay

String sTable

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Get_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln hTable ", " sRoot ", " sDisplay ", " sTable

End

Until (htable = 0)

End_Procedure // ShowFilelistNames

The sample procedure above show all the filelist attributes.

Procedure NewEntry Handle hTable String sRoot String sDisplay String sTable

Set_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

End_Procedure // ShowFilelistNames

The sample procedure above creates a new filelist entry at a given slot. It can also be used to remove a filelist entry by passing empty strings for the three filelist attributes.

Procedure CreateNewFilelist String sNewList

Handle hoWorkspace

String sPath

Integer iMaxSlots

//*** Make sure new filelist comes in first directory of datapath

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - sNewList) To sPath

//*** Create the disk file

Direct_Output sPath

Write "filelist.cfg"

Close_output

//*** Use the disk file as fileist

Set_attribute DF_FILELIST_NAME To sPath

//*** Create all the slots

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iMaxSlots

Send NewEntry iMaxSlots "" "" ""

End_Procedure // CreateNewFilelist

The sample procedure above uses the filelist attributes to create a new empty filelist. It calls the NewEntry procedure defined above.


DF_FILE_LOGIN

See Also: Get_Attribute, Set_Attribute, DF_DRIVER_SERVER_NAME

The string used to log in to the server/database that contains this table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

String value.

Remarks

The DF_FILE_LOGIN attribute holds the back end specific string that is needed to login to the server/database that contains the table.

For SQL Based Connectivity Kits this attribute should contain a so called connection string. See Server_Name intermediate file keyword for details on connection strings.

For Pervasive.SQL, it depends on the database mode the CK is running under. If the database mode is off, the DF_FILE_LOGIN attribute has no meaning. If the database mode is on, the DF_FILE_LOGIN attribute contains the Uniform Resource Indicator (URI) that identifies the table. See URI intermediate file keyword for details on URI’s.

For the Embedded Database, this attribute has no meaning.

This attribute can only be set inside a Structure_Start ... Structure_End operation.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The sample procedure above creates a table called Clock in the Northwind database of the SQL Server instance running on the local machine. Next it adds the table to the filelist.


DF_FILE_MAX_RECORDS

See Also: Get_Attribute, Set_Attribute

The guaranteed maximum number of records allowed in the table.

Level

Table

Supported by

The Embedded Database

Type

Numeric, permanent

Access

Read / Write

Values

1 ~ 16711679

Remarks

The DF_FILE_MAX_RECORDS attribute holds the guaranteed maximum number of records that can be stored in a table.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. That is why the Pervasive.SQL and SQL based Connectivity Kits will return a constant value for every table accessed, trying to set the attribute will be ignored.

In the Embedded Database the value of this attribute is used to determine the number of levels in the indices defined on the table. An index is a tree like structure. Depending on the segments in the index an index node can have a constant number of child nodes. When DF_FILE_MAX_RECORDS is set, all indices are given the number of levels to accommodate that number. This attribute does not hold the “real” maximum number of records. It is usually possible to store more records then the value in this attribute.

The indices of a table in the Embedded Database are pre-allocated. The tree structure needed to store the information is already in place only the leaf level must be filled. This ensures constant performance when using the index regardless of the number of records in the table. Finding a record will be just as fast when there’s only one record in the table as when there are millions of records. Other databases will automatically let an index grow to accommodate the number of records. This includes expanding the tree with another level. This approach uses less disk space but results in unpredictable performance. For such databases, the time it takes to find a record depends on the number of records in the table.

Assume a table with two indices defined, index 1 can have 3 child nodes per node, index 2 can have 5 child nodes per node. The following table lists the possible number of records that can be indexed by the indices defined on the table.

Number of levels | Index 1 | Index 2
1 | 3 | 5
2 | 9 | 25
3 | 27 | 125
4 | 81 | 625
5 | 243 | 3125
6 | 729 | 15625
7 | 2187 | 78125
8 | 6561 | 390625
9 | 19683 | 1953125

The “real” maximum number of records for different settings of DF_FILE_MAX_RECORDS is listed below:

Max Records | “Real” Maximum | Levels in index | Levels in index 2
10 | 25 | 3 | 2
100 | 125 | 5 | 3
1000 | 2187 | 7 | 5
10000 | 15625 | 9 | 6

In the table above the index that defines the “real” maximum number of records is indicated by making the value for its levels bold.

Note that sometimes increasing the DF_FILE_MAX_RECORDS value will not result in a change of the “real” maximum. If, in the example above, we would increase the value from 1000 to 2000, the “real” maximum would not change.

Some applications use logic to automatically increase the maximum number of records setting when the actual number of records in the table exceeds a certain threshold, more then 80% filled e.g. The operation of increasing the maximum number of records involves a rebuild of all indices defined for the table. That is quite en expensive operation. One would want to be sure the operation does make sense before starting it. That is why you should make sure you use the real maximum to check against.

The sample code below demonstrates how the “real” maximum number of record for a given table can be calculated.

Define C_MAXINDEXCAPACITY For |CI$00feffff

Function IndexCapacity Integer iKeylength Integer iLevels Returns Integer

Integer iCapacity

Integer iBlocking

Move (1024.0 / (iKeylength + 3)) To iBlocking

Move (((iBlocking ^ iLevels) - 1) Min C_MAXINDEXCAPACITY) To iCapacity

Function_Return iCapacity

End_Function // IndexCapacity

Function RealMaximum Handle hTable Returns Integer

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iKeyLength

Integer iLevels

Integer iIndexCapacity

Integer iTableCapacity

Move 0 To iTableCapacity

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_KEY_LENGTH Of hTable iIndex To iKeyLength

Get_Attribute DF_INDEX_LEVELS Of hTable iIndex To iLevels

Get IndexCapacity iKeyLength iLevels To iIndexCapacity

If (iTableCapacity = 0 Or iTableCapacity > iIndexCapacity) ;

Move iIndexCapacity To iTableCapacity

End

Loop

Function_Return iTableCapacity

End_Function // RealMaximum


DF_FILE_MAX_ROWS_FETCHED

The maximum size of the result set.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Numeric, permanent

Access

Read / Write

Values

0 ..

Remarks

The number of records, result sets of find operations on this table should be limited to. The default value is 0 (zero), which means that result sets will not be limited. All other positive integer values will limit the result set to that value.

Database servers use the SQL language to manipulate data. SQL is a set oriented language. Every statement works on set(s) and results in a set. A Visual DataFlex find command will be translated into its SQL counterpart, which is sent to the database server. The SQL statement will result in a set of rows that satisfy the condition of the statement for the find command. This result set can have no, one or more rows. In some cases, a result set will contain all rows of a table.

This attribute can be set both inside and outside a Structure_Start ... Structure_End operation. The value of this attribute is stored in the intermediate file using the Max_Rows_Fetched keyword.

Procedure ShowRecord Handle hTable

Integer iNumColumns

Integer iColumn

String sValue

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Field_value hTable iColumn To sValue

If (iColumn > 1) ;

Show ", "

Show sValue

Loop

Showln

End_Procedure // ShowRecord

Procedure ChangeMaxRowsFetchedTemporary Handle hTable Integer iIndex Integer iTempSetting

Integer iOldSetting

Boolean bFound

Integer iSetSize

Get_Attribute DF_FILE_MAX_ROWS_FETCHED Of hTable To iOldSetting

Set_Attribute DF_FILE_MAX_ROWS_FETCHED Of hTable To iTempSetting

Move True To bFound

Clear hTable

While (bFound)

Showln

Showln "*** New Set ***"

Showln

Move 0 To iSetSize

Repeat

vFind hTable iIndex Gt

Move (Found) to bFound

If (bFound) Increment iSetSize

If (bFound And iSetSize <= iTempSetting) ;

Send ShowRecord hTable

Until (Not(bFound) Or iSetSize = iTempSetting)

End

Set_Attribute DF_FILE_MAX_ROWS_FETCHED Of hTable To iOldSetting

End_Procedure // ChangeMaxRowsFetchedTemporary

The sample procedure above temporarily changes the max rows fetched setting of a table to output all its records.

Procedure ChangeMaxRowsFetchedPermanent Handle hTable Integer iNewSetting

Open hTable Mode DF_EXCLUSIVE

Structure_Start hTable

Set_Attribute DF_FILE_MAX_ROWS_FETCHED Of hTable To iNewSetting

Structure_End hTable

End_Procedure // ChangeMaxRowsFetchedPermanent

The sample procedure above changed the max rows fetched setting of a table permanently.


DF_FILE_MODE

See Also: Get_Attribute, Set_Attribute

The access mode for the table.

Level

Table

Supported by

All Connectivity Kits

Type

Flag of bits, temporary

Access

Read / Write

Values

Any iored combination of the following modes:

DF_FILEMODE_DEFAULT, DF_FILEMODE_NO_REREAD, DF_FILEMODE_NO_LOCKS, DF_FILEMODE_NO_EDITS, DF_FILEMODE_NO_DELETES, DF_FILEMODE_NO_FINDS, DF_FILEMODE_NO_CREATES

Predefined combinations of the above:

DF_FILEMODE_READONLY, DF_FILEMODE_SINGLE_USER

Remarks

Access modes affect operational characteristics of a table.

Value | Meaning
DF_FILEMODE_DEFAULT | No access restrictions on the table.
DF_FILEMODE_NO_REREAD | Reread on the table is not allowed.
DF_FILEMODE_NO_LOCKS | The table will not be locked.
DF_FILEMODE_NO_EDITS | Records in the table cannot be edited.
DF_FILEMODE_NO_DELETES | Records in the table cannot be deleted.
DF_FILEMODE_NO_FINDS | Records in the table cannot be found.
DF_FILEMODE_NO_CREATES | Records in the table cannot be created.

DF_FILEMODE_READONLY combines DF_FILEMODE_NO_REREAD, DF_FILEMODE_NO_LOCKS, DF_FILEMODE_NO_EDITS, DF_FILEMODE_NO_DELETES, and DF_FILEMODE_NO_CREATES.

DF_FILEMODE_SINGLE_USER combines DF_FILEMODE_NO_REREAD and DF_FILEMODE_NO_LOCKS.

You can make your own combinations of access restrictions by using the bitwise or operator (ior) to combine individual modes. If for example you would want to place a restriction on table MyTable that no records can be created or updated you would use the following code fragment:

Set_Attribute DF_FILE_MODE Of MyTable.File_Number To ;

(DF_FILEMODE_NO_EDITS iOr DF_FILEMODE_NO_CREATES)

It is expected that the only settings an average Visual DataFlex programmer will need are DF_FILEMODE_DEFAULT and DF_FILEMODE_READONLY. Since the DataSet and DataDictionary classes support smart file mode, setting the file mode is not needed to tune for lock performance. Setting file mode to read only for reporting can improve report speed.

Function OverallTotal Returns Number

Number nTotal

Integer iOrgMode

Get_Attribute DF_FILE_MODE Of OrderHea.File_Number To iOrgMode

Set_Attribute DF_FILE_MODE Of OrderHea.File_Number To DF_FILEMODE_READONLY

Clear OrderHea

Find Gt OrderHea By 1

While (Found)

Add OrderHea.Order_total To nTotal

Find Gt OrderHea By 1

End

Set_Attribute DF_FILE_MODE Of OrderHea.File_Number To iOrgMode

Function_Return nTotal

End_Function // OverallTotal

The sample function above sets the file mode of the OrderHea table temporarily to read only and then calculates to total amount of all orders.


DF_FILE_MULTIUSER

See Also: Get_Attribute, Set_Attribute

Specifies whether the table is to be usable to more than one user concurrently.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_FILE_USER_MULTI, DF_FILE_USER_SINGLE

Remarks

When the attribute is set to DF_FILE_USER_MULTI, the table can be accessed in a multi user fashion. If the attribute is set to DF_FILE_USER_SINGLE the table can only be accessed by one process at a time. There is no check build in to guarantee that only one process is accessing the table. This means that if a table’s DF_FILE_MULTIUSER attribute is set to DF_FILE_USER_SINGLE and multiple processes access it at the same time, the table will be corrupted. This attribute is set to DF_FILE_USER_SINGLE automatically if the DF_FILE_LOCK_TYPE attribute is set to DF_LOCK_TYPE_NONE.

This attribute is left over from the time when there where single user/process operating systems. Modern operating systems allow multiple processes to run simultaneously. When two (or more) processes access a table at the same time, they are in fact using the table in a multi user fashion.

This attribute can only be set inside a Structure_Start ... Structure_End operation. We expect this attribute will very rarely be set. The default value will be used in most cases.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. It however does not make any sense in some back ends. That is why the Pervasive.SQL and SQL based Connectivity Kits will return DF_FILE_USER_MULTI for every table accessed, trying to set the attribute will be ignored.

Procedure ShowPotentialProblemTables

Handle hTable

Integer iMultiUser

String sTable

Integer iDangerous

Move 0 To hTable

Move 0 To iDangerous

Repeat

Get_Attribute DF_FILE_NEXT_USED of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_MULTIUSER Of hTable To iMultiUser

Get_Attribute DF_FILE_LOGICAL_NAME of hTable To sTable

If (iMultiUser = DF_FILE_USER_SINGLE) Begin

Showln "DANGER! Table " sTable " will not be locked!"

Increment iDangerous

End

Close hTable

End

Until (hTable = 0)

If (iDangerous = 0) ;

Showln "All tables in the filelist will be properly locked."

End_Procedure // ShowPotentialProblemTables

The sample procedure above will check every table in the filelist for its multi user setting. When tables exists that have their multi user setting set to DF_FILE_USER_SINGLE these will be reported as potential problem tables.


DF_FILE_NEXT_EMPTY

See Also: Get_Attribute, Set_Attribute, DF_FILE_NEXT_OPENED, DF_FILE_NEXT_USED

The number of the next unused slot in the filelist (in ascending order).

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

0 .. 4095

Remarks

This attribute returns the next unused slot in the filelist (in ascending order). A filelist slot is considered empty if the DF_FILE_ROOT_NAME attribute of that slot is empty. If there is no higher-numbered empty slot in the filelist, DF_FILE_NEXT_EMPTY is 0 (zero).

Function IsSlotFree Handle hTable Returns Boolean

Handle hNext

Get_Attribute DF_FILE_NEXT_EMPTY Of (hTable - 1) To hNext

Function_Return (hTable = hNext)

End_Function // IsSlotFree

The sample function above determines if the slot for a given handle is free.


DF_FILE_NEXT_OPENED

See Also: Get_Attribute, Set_Attribute, DF_FILE_NEXT_EMPTY, DF_FILE_NEXT_USED

The number of the next opened table (in ascending order).

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read Only

Values

0 .. 4095

Remarks

This attribute returns the filelist number of the next opened table (in ascending order). If there is no higher-numbered open table, DF_FILE_NEXT_OPENED is 0 (zero).

Procedure ShowOpenTables

Handle hTable

String sRoot

String sDisplay

String sTable

Showln "Open tables:"

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Get_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln " " hTable ": " sTable " (" sRoot ", " sDisplay ")"

End

Until (hTable = 0)

End_Procedure // ShowOpenTables

The sample procedure above determines and displays the filelist numbers and names of all tables open in the current application.


DF_FILE_NEXT_USED

See Also: Get_Attribute, Set_Attribute, DF_FILE_NEXT_EMPTY, DF_FILE_NEXT_OPENED

The next occupied number in the filelist (in ascending order).

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

0 .. 4095

Remarks

This attribute returns the next used slot in the filelist (in ascending order). A filelist slot is considered used if the DF_FILE_ROOT_NAME attribute of that slot is not empty. If there is no higher-numbered used slot in the file list, DF_FILE_NEXT_USED is 0 (zero).

Procedure ShowUsedTables

Handle hTable

String sRoot

String sDisplay

String sTable

Showln "Used tables:"

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Get_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln " " hTable ": " sTable " (" sRoot ", " sDisplay ")"

End

Until (hTable = 0)

End_Procedure // ShowUsedTables

The sample procedure above determines and displays the filelist slot numbers and names of all tables used in the filelist.


DF_FILE_NUMBER

See Also: Get_Attribute, Set_Attribute

The number that is used as a handle for an opened table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read / Write

Values

1 .. 4095

Remarks

The number that is used as a handle for an opened table. The table must be opened for this attribute to have a value. This attribute can be used to find the original table handle of a table that is being restructured.

Procedure ShowOriginalHandle

Handle hTable

Handle hOriginal

Open Customer Mode DF_EXCLUSIVE

Move Customer.File_Number To hTable

Structure_Start hTable

Get_Attribute DF_FILE_NUMBER Of hTable To hOriginal

Showln "Handle, number: " hTable ", " hOriginal

Structure_Abort hTable

Close Customer.File_number

End_Procedure // ShowOriginalHandle

The sample procedure above shows the handle to the customer table being restructured and its original handle.


DF_FILE_NUMBER_FIELDS

See Also: Get_Attribute, Set_Attribute

The number of columns in the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read O

Values

1 ~ maximum number of columns allowed in the database

Remarks

This attribute returns the number of columns in the table. Possible overlap columns are included in this value. The attribute cannot be directly set. It is indirectly manipulated by using the Create_Field and Delete_Field commands.

Procedure ShowNames Handle hTable

String sTable

String sColumn

Integer iNumColumns

Integer iColumn

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

Showln "The columns in table " sTable " have the following names:"

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Showln (Right(" " + String(iColumn), 5)) ": " sColumn

Loop

End_Procedure // ShowNames

This example retrieves and displays the name of all columns in the table.


DF_FILE_NUMBER_SQL_RELATIONS

The number of columns in the table that are part of a foreign key.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Integer, permanent

Access

Read Only

Values

1 ~ maximum number of columns allowed in the database

Remarks

When a table is opened the foreign key information is retrieved from the back end. This information can be used to examine the relationships as they are defined on the back end.

Procedure ShowSQLRelations Handle hTable

Integer iNumRelations

Integer iFKColumn

String sFkTable

String sFKSchema

String sFKColumn

String sPKSchema

String sPKTable

String sPKColumn

Integer iCurRel

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_NUMBER_SQL_RELATIONS Of hTable To iNumRelations

If (iNumRelations > 0) Begin

Get_Attribute DF_FILE_TABLE_NAME Of hTable To sFKTable

Get_Attribute DF_FILE_OWNER Of hTable To sFKSchema

For iCurRel From 1 To iNumRelations

Get_Attribute DF_SQL_RELATION_COLUMN Of hTable iCurRel To iFKColumn

Get_Attribute DF_SQL_RELATION_RELATED_SCHEMA Of hTable iCurRel To sPKSchema

Get_Attribute DF_SQL_RELATION_RELATED_TABLE Of hTable iCurRel To sPKTable

Get_Attribute DF_SQL_RELATION_RELATED_COLUMN Of hTable iCurRel To sPKColumn

Get_Attribute DF_FIELD_NAME Of hTable iFKColumn To sFKColumn

Showln sFKSchema "." sFKTable "." sFKColumn " relates to ;

" sPKSchema "." sPKTable "." sPKColumn

Loop

End

End

Until (hTable = 0)

End_Procedure // ShowSQLRelations

The sample procedure above shows all columns that are part of a foreign key of the given table.


DF_FILE_OPEN_MODE

See Also: Get_Attribute, Set_Attribute

The mode in which the table was opened.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, temporary

Access

Read Only

Values

DF_SHARE, DF_EXCLUSIVE

Remarks

The DF_FILE_OPEN_MODE attribute retrieves the mode with which a table was opened. The DF_EXCLUSIVE mode signifies that a table has been opened in exclusive mode. The DF_SHARE mode is the normal file mode allowing multiple processes to access the table.

This attribute cannot be set directly; it reflects the way a table was opened by the open command. Below is a code fragment that opens table MyExclusive exclusively and table MyShared in shared mode:

Open MyExclisive Mode DF_EXCLUSIVE

Open MyShared

Note that in order to open a table in shared mode you do not need to specify an open mode. When the open mode is not explicitly specified, DF_SHARED is assumed. To open a table in shared mode one could also use the code below:

Open MyShared Mode DF_SHARED

The Embedded Database and Pervasive.SQL support opening table in exclusive mode. If a process attempts to open a table (other shared or exclusive) that is already opened exclusive by some other process an error will be generated, DFERR_FILE_ACCESS_VIOLATION. If a process attempts to open a table in exclusive mode that is already opened in shared mode by some other process the DFERR_FILE_ACCESS_VIOLATION will also be generated.

In the SQL environment used by the SQL Based Connectivity Kits, there is no such concept as opening a table, therefore there is also no such concept as opening a table exclusively or shared. The attribute is supported and will correctly reflect the mode used in the open command. If a process attempts to open a (SQL Based) table that is already opened exclusive by some other process no error will be generated and the attempt succeeds.

The Structure_Start and Sort commands require the table to be opened in exclusive mode. As a result all the commands that must be executed inside a Structure_Start ... Structure_End operations, including the Structure_End itself, require the table to be open in exclusive mode.

Procedure ShowOpenMode

Handle hTable

String sTable

Integer iMode

Showln "Open tables open mode:"

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_OPEN_MODE Of hTable To iMode

Showln " " hTable ", " sTable ", " (If(iMode = DF_EXCLUSIVE, "Exclusive", "Shared"))

End

Until (hTable = 0)

End_Procedure // ShowOpenMode

The sample procedure above shows the open mode for all tables open in an application.

Define C_SORT_SUCCESS For 0

Define C_SORT_FAILED_OPENEXCLUSIVE For 1

Define C_SORT_FAILED_REOPENSHARED For 2

Function SortTable Handle hTable Returns Integer

Integer iMode

Boolean bOpenExclusive

Boolean bOpenShared

Integer iStatus

Move C_SORT_SUCCESS To iStatus

Get_Attribute DF_FILE_OPEN_MODE Of hTable To iMode

If (iMode <> DF_EXCLUSIVE) Begin

//*** Make sure we don't see the can't open error

Send Ignore_Error Of Error_Object_ID DFERR_CANT_OPEN_DATA_FILE

Send Ignore_Error Of Error_Object_ID DFERR_FILE_ACCESS_VIOLATION

move False to Err

Close hTable

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_OPENED Of hTable To bOpenExclusive

If (Not(bOpenExClusive)) ;

Move C_SORT_FAILED_OPENEXCLUSIVE To iStatus

Send Trap_Error Of Error_Object_ID DFERR_CANT_OPEN_DATA_FILE

Send Trap_Error Of Error_Object_ID DFERR_FILE_ACCESS_VIOLATION

End

Else ;

Move (True) To bOpenExclusive

If (bOpenExclusive) Begin

Sort hTable

//*** If we re-opened the table try to restore previous situation

If (iMode <> DF_EXCLUSIVE) Begin

//*** Make sure we don't see the can't open error

Send Ignore_Error Of Error_Object_ID DFERR_CANT_OPEN_DATA_FILE

Send Ignore_Error Of Error_Object_ID DFERR_FILE_ACCESS_VIOLATION

move False to Err

Close hTable

Open hTable

Get_Attribute DF_FILE_OPENED Of hTable To bOpenShared

If (Not(bOpenShared)) ;

Move C_SORT_FAILED_OPENEXCLUSIVE To iStatus

Send Trap_Error Of Error_Object_ID DFERR_CANT_OPEN_DATA_FILE

Send Trap_Error Of Error_Object_ID DFERR_FILE_ACCESS_VIOLATION

End

End

Function_Return iStatus

End_Procedure // SortTable

The sample function above will attempt to sort a table. If the table is not opened exclusive, it will attempt to do so. If the table is open exclusive, it will be sorted. If the function opened the table itself, it will attempt to restore the shared mode by reopening the table.


DF_FILE_OPENED

See Also: Get_Attribute, Set_Attribute

Indicates if the table is opened in the current application.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read Only

Values

True, False

Remarks

If DF_FILE_OPENED is true, the table is opened in the current application. This attribute will not return whether the table is opened in another application, only the current one. This attribute cannot be set directly; it reflects the open commands executed by the application.

There is no generic way to check if a table is open in another application. If the database used supports exclusive open mode, one could attempt to open the table exclusively and if that fails conclude that the table is open in some other application. Although it would work, it is a pretty blunt way to check this.

The Visual DataFlex open logic will not open a table if there already is an open table using the same number. If one would attempt to open two different tables using the same table number, the second attempt will not have any effect. One can use the DF_FILE_OPENED attribute to determine if the table is already open and decide to close the table or use another table number. Note that table numbers used by an application do not need to correspond 100% with the table numbers assigned in the filelist.

Function FirstAvailableNumber String sTable Returns Handle

Integer iNumTables

Handle hTable

Boolean bOpen

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iNumTables

For hTable From 1 To iNumTables

Get_Attribute DF_FILE_OPENED Of hTable To bOpen

If (Not(bOpen)) ;

Function_Return hTable

Loop

Function_Return 0

End_Function // FirstAvailableNumber

The sample function above returns the first available number to open a table.


DF_FILE_OWNER

See Also: Get_Attribute, Set_Attribute

The owner of the table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

Any valid owner string.

Remarks

The owner of the table, if there is no owner of the table the string is empty.

The Embedded Database does not support table owners and will always return an empty string. Trying to set the attribute will generate a DFERR_UNSUPPORTED_ATTRIBUTE error.

The Pervasive.SQL Connectivity Kit supports table owners. A Pervasive.SQL owner name puts a password on a table. Owner names do have an additional attribute:

Owner attribute | Meaning
READONLY | The Pervasive.SQL engine will allow opening the table without ownername for read-only access.
ENCRYPT | The Pervasive.SQL engine will encrypt the data in the data table. The owner name must be specified when opening the table.

You can use the attribute to get the owner name. Setting the owner name must be done via the DFBTR_Set_Owner command. This command allows you to specify the owner name attribute next to the owner name itself. Owner names are stored in the intermediate file using the Owner keyword.

The SQL Based Connectivity Kits support owner names. They will project the DF_FILE_OWNER attribute on the schema, or in case of SQL Server owner, of the table. You can set this attribute both inside and outside a Structure_Start ... Structure_End operation. If set outside of a structure operation, all open cursors for the table will be closed. Owner names are stored in the intermediate file using the Schema_Name keyword.

Procedure ShowOwner

Handle hTable

String sTable

String sOwner

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_OWNER Of hTable To sOwner

Showln sTable " -- " sOwner

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowOwner

The sample procedure above opens all tables in the filelist and shows the table and owner name for every table.

Procedure ChangeOwner String sOldOwner String sNewOwner

Handle hTable

String sOwner

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_OWNER Of hTable To sOwner

If (sOwner = sOldOwner) ;

Set_Attribute DF_FILE_OWNER Of hTable To sNewOwner

End

Until (hTable = 0)

End_Procedure // ChangeOwner

The sample procedure above changes the owner for every open table that has a given owner name. Note that this procedure will only work for a table accessed through a SQL Based Connectivity Kit.


DF_FILE_PHYSICAL_NAME

See Also: Get_Attribute, Set_Attribute

The table name, including the path, of the table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

A string containing the physical name of the table.

Remarks

DF_FILE_PHYSICAL_NAME is the physical name of the opened table. This is not the same as the name used to open the table inside an application using the Open command. The name used to open a table using the open command can be determined by using the DF_FILE_LOGICAL_NAME attribute. If the “open as” variant of the open command is used, one can specify the physical table name.

This attribute can only be set inside a Structure_Start ... Structure_End operation when creating a new table. It cannot be set when restructuring an existing table. The DF_FILE_PHYSICAL_NAME attribute can include a path, so it can be used to specify the location where the new data table should be created.

Setting the DF_PHYSICAL_NAME of a table does not add this table to the filelist. After creating a table with a valid physical name, the attributes DF_FILE_LOGICAL_NAME, DF_FILE_ROOT_NAME and DF_FILE_DISPLAY_NAME must be set in order to add a table to a filelist.

The Embedded Database stores a table in several disk files. The data is stored in a .dat file (a .vld when compression is on), the indices in .k?? files, the column names in a .tag file, All these disk files have the same name part, the extension is different. The physical name of a table is this common part.

The Pervasive.SQL Connectivity Kit allows access to a table via an intermediate file or directly. If an intermediate file present for the table, the physical name will be the path to the intermediate file. If no intermediate file is present, the physical name will be the name of the table on disk.

The SQL Based Connectivity Kits allow access to a table via an intermediate file or directly. If an intermediate file is used, the physical name of the table is the name of the intermediate file. If a table is opened directly, the physical name is the string used to open the table. This string is on the form “<DriverName>:<SchemaName>#<TableName>@<ConnectionString>”.

Procedure ShowPhysicalNames

Handle hTable

String sTable

String sPhysicalName

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_PHYSICAL_NAME Of hTable To sPhysicalName

Showln sTable " -- " sPhysicalName

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowPhysicalNames

The sample procedure above shows the physical name of every table in the filelist.

Procedure CreateTable

Handle hTable

Integer iColumn

Integer iIndex

Handle hoWorkspace

String sPath

String sOrgDirectory

//*** Make sure table comes in first directory of datapath by making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create physical table contacts

Move 0 To hTable

Structure_Start hTable "DATAFLEX"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_MAX_RECORDS Of hTable To 150000

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Customer_Number"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 6

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ContactDate"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (8 * 1024)

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 2

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Structure_End hTable

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Contact sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Contact"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Contact.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

The sample procedure above creates an Embedded Database table called Contact.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To "SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The sample procedure above creates a SQL Server table called Clock. Note that the physical name of the table is set to the name of the intermediate file.


DF_FILE_PRIMARY_INDEX

See Also: DF_FILE_RECNUM_TABLE, DF_INDEX_NUMBER_SEGMENTS, DF_INDEX_SEGMENT_FIELD

Specifies if the index number of the primary index – the index that uniquely identifies a record.

Level

Table

Supported by

All Connectivity Kits

Type

Integer, permanent

Access

Read / Write

Values

0 ~ maximum number of indexes allowed by the database

Remarks

The primary index of a table is the number of the index that uniquely identifies a record in that table. The Visual DataFlex database API demands that every table has at least one such index. This index is used to keep a pointer to a record. The primary index concept was introduced in Visual DataFlex 11 along with related concepts as standard tables and RowIds.

Part of the Visual DataFlex 11 improvements are improved database drivers. These new drivers have a conformance level of 1. Older drivers have a conformance level of 0 and do not support the DF_FILE_PRIMARY_INDEX attribute. The conformance level of a driver can be queried by using the DF_DRIVER_CONFORMANCE attribute.

Primary indexes apply to both recnum and standard tables. In a recnum table, primary index will often be 0 (zero). In a standard table the segments of the primary index will comprise the fields that uniquely identify a record. Most often these fields will be your primary key.

This attribute can only be set inside a Structure_Start ... Structure_End operation. The SQL Based Connectivity Kits store the value of the attribute in the intermediate file under the Primary_Index keyword.

Function DriverIndex String sDriver Returns Integer

String sCurrentDriver

Integer iNumberOfDrivers

Integer iDriver

Integer iCount

Move 0 To iDriver

Get_attribute DF_NUMBER_DRIVERS To iNumberOfDrivers

For iCount From 1 To iNumberOfDrivers

Get_Attribute DF_DRIVER_NAME Of iCount To sCurrentDriver

If (Uppercase(sCurrentDriver)) Eq (Uppercase(sDriver)) ;

Move iCount To iDriver

Loop

Function_return iDriver

End_Function // DriverIndex

Procedure ShowPrimaryIndex

Handle hTable

String sTable

String sDRiver

Integer iDriver

Integer iConformance

Integer iPrimaryIndex

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

Get DriverIndex sDriver To iDriver

Get_Attribute DF_DRIVER_CONFORMANCE Of iDriver To iConformance

If (iConformance >= 1) ;

Get_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iPrimaryIndex

Else ;

Move 0 To iPrimaryIndex

Showln sTable " -- " iPrimaryIndex

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowPrimaryIndex

The sample procedure above shows the primary index of every table in the filelist. If the table is accessed through a conformance 0 driver, the primary index is set to 0 (zero).

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To "SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The sample procedure above creates a standard table called Clock with one unique index that is set to be the primary index.


DF_FILE_RECNUM_TABLE

See Also: DF_FILE_PRIMARY_INDEX, DF_FILE_RECORD_IDENTITY

Specifies if the table contains a Recnum field.

Level

Table

Supported by

All Connectivity Kits

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

The DF_FILE_RECNUM_TABLE attribute determines if Recnum is used to define a Table's record identity. Typically this attribute is used to determine if the Recnum field can be used for a table.

When DF_FILE_RECUM_TABLE is true, records in the table are identified by a single numeric column. This may be a logical or physical column. In either case the table will have a column with number 0 that is called recnum. This column can be accessed via Table.Recnum. A Recnum column is treated in a special way. If a value is moved to the recnum column, the buffer is made inactive (the DF_FILE_STATUS attribute is set to DF_FILE_INACTIVE). If a buffer is inactive a save operation on that buffer will create a new record.

When DF_FILE_RECNUM_TABLE is false, records in the table are identified by one or more columns of any type. The identifying columns are defined by setting the DF_FILE_PRIMARY_INDEX attribute.

A recnum table’s column numbers start at 0 (zero) where a standard table’s column numbers start at 1. Attempting to access column 0 (zero) of a standard table will result in an error message (DFERR_FIELD_NUMBER_RANGE).

Note that this attribute determines how the table handles unique identities. It does not determine whether the programming interface will use a Recnum or RowId style programming interface. All table types can and should be accessed using the RowId programming interface. If the RowId programming interface is used, you will not need to know if Recnum is supported, hence, you should rarely need to use this attribute.

This attribute can only be set inside a Structure_Start ... Structure_End operation. The SQL Based Connectivity Kits store the value of the attribute in the intermediate file under the Recnum_Table keyword.

The Embedded Database only supports recnum tables, in other words, the value of DF_FILE_RECNUM_TABLE is always true for an Embedded Database table.

The Pervasive.SQL Connectivity Kit only supports recnum tables, in other words, the value of DF_FILE_RECNUM_TABLE is always true for a Pervasive.SQL table.

The SQL Based Connectivity Kits support both recnum and standard tables, starting at version 4. Older versions of these Connectivity Kits only support recnum tables.

Procedure ShowRecnumTables

Handle hTable

String sTable

Boolean bRecnumTable

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_RECNUM_TABLE Of hTable To bRecnumTable

Showln sTable " -- " (If(bRecnumTable, "RECNUM", "STANDARD")) " table"

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowRecnumTables

The sample procedure above shows all tables in the filelist and of every table it shows if it is recnum or a standard table.

Procedure ShowRecord Handle hTable

Boolean bRecnumTable

Integer iNumColumns

Integer iColumn

Integer iStart

String sValue

Get_Attribute DF_FILE_RECNUM_TABLE Of hTable To bRecnumTable

If (bRecnumTable) ;

Move 0 To iStart

Else ;

Move 1 To iStart

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From iStart To iNumColumns

Get_Field_Value hTable iColumn To sValue

If (iColumn > iStart) ;

Show ", "

Show (Trim(sValue))

Loop

Showln

End_Procedure // ShowRecord

The sample procedure above shows the contents of a record of a given table. If this is a recnum table it shows the value of the recnum column.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The sample procedure above creates a standard table called Clock with one unique index that is set to be the primary index.


DF_FILE_RECORD_IDENTITY

See Also: Get_Attribute, Set_Attribute

The number of the field of the recnum table to be used to identify records.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

0 ~ maximum number of fields allowed in a file of the database system

Remarks

This attribute identifies the field that is to function as the equivalent of RECNUM in each file of any database system that does not support or use record numbers the way DataFlex does. This can be an existing field. It must, at all times, have a unique value for each record. Once a field has been designated by this attribute, its index (whatever its actual number) may be addressed as Index 0.

Note that there must be an index defined on the record identity column. That index should have one segment, the record identity column. Record identity columns must be numeric with 0 (zero) precision (no decimals).

This attribute can only be set inside a Structure_Start ... Structure_End operation. The SQL Based Connectivity Kits store the value of the attribute in the intermediate file under the Primary_Index keyword. The Pervasive.SQL Connectivity Kit stores the type of record identity column in the intermediate file under the Recnum_Support keyword.

For the Embedded Database, this attribute will always have a value of (field) zero. If you attempt to set it to any value other than zero for such a table, you will receive an error. Both the record identity column and its index are logical objects in the table.

For the Pervasive.SQL Connectivity Kit, this attribute will always have a value of (field) zero. The Pervasive.SQL Connectivity Kit supports two types of recnum columns; one logical column and one physical column. The logical column is a handle to the record. The physical column is a hidden column, called recnum, that is paced at the beginning of the record. This column can be created by the conversion process to preserve the original record numbers. You only need to convert in this way if the recnum column of the original table contains meaningful information.

For the SQL Based Connectivity Kits this attribute can have a non zero value. The attribute is only meaningful when the table is a recnum table. For standard tables, DF_FILE_PRIMARY_INDEX should be used to determine the identifying columns. A record identity with value 0 (zero) means that the recnum column will be hidden, although there is a physical column, it will not be reported by the Connectivity Kit. This will be the case with most recnum tables accessed through a SQL Based Connectivity Kit. Note that when the record identity is an existing visible column, there are two ways to address that column. If, for example, a table has a column called CustomerNumber that is also used as record identifier, you can address the column in the following ways:

Move Table.CustomerNumber To iVar

Move Table.Recnum To iVar

Move iVar To Table.CustomerNumber

Move iVar To Table.Recnum

Of the four commands above the last one is special. Moving a value to recnum will inactivate the record buffer (the DF_FILE_STATUS attribute is set to DF_FILE_INACTIVE). If a buffer is inactive a save operation on that buffer will create a new record.

Procedure ShowRecordIdentifiers

Handle hTable

String sTable

Boolean bRecnumTable

Integer iIndex

String sKey

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_RECNUM_TABLE Of hTable To bRecnumTable

If (bRecnumTable) Begin

Get_Attribute DF_FILE_RECORD_IDENTITY Of hTable To iColumn

Get_Attribute DF_FIELD_NAME of hTable iColumn To sColumn

Move ("(" - sColumn - ")") To sKey

End

Else Begin

Get_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of Htable iIndex To iNumSegments

Move "(" To sKey

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME of hTable iColumn To sColumn

If (iSegment > 1) ;

Move (sKey - ", ") To sKey

Move (sKey + sColumn) To sKey

Loop

End

Showln sTable " -- " sKey

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowRecordIdentifiers

The sample procedure above shows all tables in the filelist with their identifying columns.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "RNClock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To True

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "RNClock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Set_Attribute DF_FILE_RECORD_IDENTITY Of hTable To 0

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The sample procedure above creates a SQL Server recnum table in the Northwind database. This table has a hidden recnum column.


DF_FILE_RECORD_LENGTH

See Also: Get_Attribute, Set_Attribute, DF_FILE_RECORD_LENGTH_USED

The length, in bytes, of a physical record in the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

0 ~ maximum number of bytes allowed in a record of the database system

Remarks

The physical record length of a table refers to the amount of space allocated on disk for records in the table.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. That is why the Pervasive.SQL and SQL based Connectivity Kits will return the aggregate length of the columns for every table accessed, and trying to set the attribute will be ignored.

In the Embedded Database, the physical record length may not represent the aggregate length of the columns in the table although it will always be at least that large.

When columns are added to or changed in a database table in a way that increases record length, the Embedded Database driver will automatically increase the record length as needed. If you are changing a table definition so that columns are removed or reduced in size, you may want to decrease the record length, as it is not automatically adjusted. Doing so may improve many database operations, such as rereading records from disk and reindexing of the table.

This attribute can only be set inside a Structure_Start ... Structure_End operation. You may want to set this attribute directly if you wish to use fixed record lengths. In that case, if you add new fields or increase existing fields and they fit into the existing record length, restructuring should be somewhat faster. The record length for an Embedded Database table can be:

• At least 8 bytes

• Any value between 8 and 256

• Above 256 record length are incremented in multiples of 128 bytes

If the record length is set to a non-supported value, the value is automatically corrected.

Procedure ShowRecordLength

Handle hTable

String sTable

Integer iRecordLength

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_RECORD_LENGTH Of hTable To iRecordLength

Showln sTable " -- " iRecordLength

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowRecordLength

The sample procedure above shows the record length of every table in the filelist.

Procedure FixupLengthMismatch

Handle hTable

handle hStruct

String sTable

Integer iRecordLength

Integer iRecordLengthUsed

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

//*** Cannot open flexerrs exclusive!

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

If (Uppercase(sTable) <> "FLEXERRS") Begin

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_RECORD_LENGTH Of hTable To iRecordLength

Get_Attribute DF_FILE_RECORD_LENGTH_USED Of hTable To iRecordLengthUsed

If (iRecordLength - iRecordLengthUsed > 128) Begin

Move hTable To hStruct

Structure_Start hStruct

Set_Attribute DF_FILE_RECORD_LENGTH Of hStruct To iRecordLengthUsed

Structure_End hStruct

End

Close hTable

End

End

Until (hTable = 0)

End_Procedure // FixupLengthMismatch

The sample procedure above adjusts the record length of this tables that have a mismatch between the record length and the aggregate of the length of the column greater then 128 bytes.


DF_FILE_RECORD_LENGTH_USED

See Also: Get_Attribute, Set_Attribute, DF_FILE_RECORD_LENGTH

The number of bytes actually used for fields in a physical record in the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read Only

Values

0 to value of the DF_FILE_RECORD_LENGTH attribute.

Remarks

The Embedded Database has the ability to declare a physical record length greater than the aggregate length of the fields in the file. The value of the DF_FILE_RECORD_LENGTH_USED attribute is the aggregate length of the fields in the file and may be less than the DF_FILE_RECORD_LENGTH attribute's value.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. That is why the Pervasive.SQL and SQL based Connectivity Kits will return the aggregate length of the columns for every table accessed.

Procedure ShowLengthMismatch

Handle hTable

String sTable

Integer iRecordLength

Integer iRecordLengthUsed

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_RECORD_LENGTH Of hTable To iRecordLength

Get_Attribute DF_FILE_RECORD_LENGTH_USED Of hTable To iRecordLengthUsed

If (iRecordLength <> iRecordLengthUsed) ;

Showln sTable " has a record length mismatch of " (iRecordLength - iRecordLengthUsed) ;

"(" iRecordLength " - " iRecordLengthused ") bytes."

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowLengthMismatch

The sample procedure above shows the name of every table in the filelist that has a different record length then the aggregate length of all columns.

Procedure FixupLengthMismatch

Handle hTable

handle hStruct

String sTable

Integer iRecordLength

Integer iRecordLengthUsed

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

//*** Cannot open flexerrs exclusive!

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

If (Uppercase(sTable) <> "FLEXERRS") Begin

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_RECORD_LENGTH Of hTable To iRecordLength

Get_Attribute DF_FILE_RECORD_LENGTH_USED Of hTable To iRecordLengthUsed

If (iRecordLength - iRecordLengthUsed > 128) Begin

Move hTable To hStruct

Structure_Start hStruct

Set_Attribute DF_FILE_RECORD_LENGTH Of hStruct To iRecordLengthUsed

Structure_End hStruct

End

Close hTable

End

End

Until (hTable = 0)

End_Procedure // FixupLengthMismatch

The sample procedure above adjusts the record length of this tables that have a mismatch between the record length and the aggregate of the length of the column greater then 128 bytes.


DF_FILE_RECORDS_USED

See Also: Get_Attribute, Set_Attribute, DF_FILE_MAX_RECORDS

The number of records that exist in the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read Only

Values

0 ~ maximum number of records allowed in the database

Remarks

This attribute represents the number of records currently in the table, not including deleted records. This attribute cannot be set directly. It is set indirectly by adding and/or removing records.

In SQL back ends, the only way to get the number of record in a table is to count them. Depending on the back end, this can be an expensive operation. Be careful when using this attribute.

Procedure ShowRecordsUsed

Handle hTable

String sTable

Integer iNumRecords

Number nTotalRecords

Move 0 To hTable

Move 0 To nTotalRecords

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_RECORDS_USED Of hTable To iNumRecords

Showln sTable " -- " iNumRecords

Add iNumRecords To nTotalRecords

Close hTable

End

Until (hTable = 0)

Showln "Total -- " nTotalRecords

End_Procedure // ShowRecordsUsed

The sample procedure above shows the number of records in use for every table in the filelist. At the end it shows the total number of records.


DF_FILE_REFIND_AFTER_SAVE

Must a record be found again directly after saving it.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

If database triggers are defined on a table that fill one (or more) columns in a row that is created or updated, you may use this attribute if you want these new column values to be available directly after the save operation. Setting this attribute to true will ensure that the record buffer is up-to-date. Setting this attribute to false (the default), will switch re-fetching the row off. This eliminates a Client/Server communication roundtrip, thus speeding up performance when creating records.

This attribute can be set both inside and outside of a Structure_Start ... Structure_End operation. The value of the attribute is stored in the intermediate file using the keyword Refind_After_Save.

Procedure CreateTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "RIMSample.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To True

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "RIMSample"

Set_Attribute DF_FILE_GENERATE_RECORD_ID_METHOD Of hTable To RIM_IDENTITY_COLUMN

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To 0

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 4

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Name"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 50

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (5 * (2^20))

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "RimSample001"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:RIMSample"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "RIM sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "RIMSamp"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "RIMSamp.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

Procedure BulkCreate

Integer iRecID

Boolean bRefind

Boolean bGetRID

DateTime dtBegin

Datetime dtEnd

TimeSpan tsFirst

TimeSpan tsSecond

Get_Attribute DF_FILE_REFIND_AFTER_SAVE Of RIMSamp.File_number To bRefind

Get_Attribute DF_FILE_GET_RID_AFTER_CREATE Of RIMSamp.File_number To bGetRID

Set_Attribute DF_FILE_REFIND_AFTER_SAVE Of RIMSamp.File_number To False

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE Of RIMSamp.File_number To False

Move (CurrentDateTime()) To dtBegin

For iRecID From 1 To 1000

Begin_Transaction

Clear RIMSamp

Move iRecID To RIMSamp.Id

Move ("Name" - String(iRecID)) To RIMSamp.Name

SaveRecord RIMSamp

End_Transaction

Loop

Move (CurrentDateTime()) To dtEnd

Move (dtEnd - dtBegin) To tsFirst

Set_Attribute DF_FILE_REFIND_AFTER_SAVE Of RIMSamp.File_number To True

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE Of RIMSamp.File_number To True

Move (CurrentDateTime()) To dtBegin

For iRecID From 1001 To 2000

Begin_Transaction

Clear RIMSamp

Move iRecID To RIMSamp.Id

Move ("Name" - String(iRecID)) To RIMSamp.Name

SaveRecord RIMSamp

End_Transaction

Loop

Move (CurrentDateTime()) To dtEnd

Move (dtEnd - dtBegin) To tsSecond

Set_Attribute DF_FILE_REFIND_AFTER_SAVE Of RIMSamp.File_number To bRefind

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE Of RIMSamp.File_number To bGetRID

Showln "Creating 1000 records with attributes off takes " tsFirst

Showln "Creating 1000 records with attributes on takes " tsSecond

End_Procedure // BulkCreate

The sample procedure above creates 1000 records in the RIMSamp table with the "refind after save" and "get rid after create" settings off. After that it creates 1000 records with the settings on. At the end it displays the time both loops take. The procedure to create the RIMSamp table is also part of the sample code.


DF_FILE_RESTRUCTURE

See Also: Get_Attribute, Set_Attribute

The status of the restructure on a table.

Level

Table

Supported by

All Connectivity Kits

Type

Flag of bits, temporary

Access

Read Only

Values

DF_NO_RESTRUCTURE, DF_RESTRUCTURE_FILE, DF_RESTRUCTURE_INDEX, DF_RESTRUCTURE_BOTH

Remarks

When data-table-structure maintenance is performed, it may be necessary to restructure the data to fit the new structure of the table. The DF_FILE_RESTRUCTURE attribute will be DF_NO_RESTRUCTURE if no restructuring is needed, DF_RESTRUCTURE_FILE if data restructure is needed, DF_RESTRUCTURE_INDEX if the indexes need to be rebuilt or DF_RESTRUCTURE_BOTH if data restructure and index rebuild are both needed. DF_RESTRUCTURE_BOTH combines DF_RESTRUCTURE_FILE and DF_RESTRUCTURE_INDEX.

This attribute is often used to inform the user of the actions that are going to take place.

Function Proceed Handle hTable Returns Boolean

Integer iRestruct

String sMessage

String sTitle

String sTable

Integer iAnswer

Get_Attribute DF_FILE_RESTRUCTURE Of hTable To iRestruct

Get_Attribute DF_FILE_PHYSICAL_NAME Of hTable To sTable

Move ("Saving structure change to" * sTable) To sTitle

If (iRestruct = DF_NO_RESTRUCTURE) ;

Move ("No restructure operation required.\n") To sMessage

Else Begin

Move "" To sMessage

If (iRestruct iAnd DF_RESTRUCTURE_FILE) ;

Move (sMessage - "Table must be restructured.\n") To sMessage

If (iRestruct iAnd DF_RESTRUCTURE_INDEX) ;

Move (sMessage - "Indices must be rebuild.\n") To sMessage

End

Move (sMessage - "Do you want to proceed?") To sMessage

Get YesNo_Box sMessage sTitle MB_DEFBUTTON1 To iAnswer

Function_Return (iAnswer = MBR_YES)

End_Function // Proceed

Procedure RestructTest

Handle hStruct

Integer iColumn

Integer iIndex

Boolean bSave

//*** Add a column

Open Customer Mode DF_EXCLUSIVE

Move Customer.File_Number To hStruct

Structure_Start hStruct

Move 0 To iColumn

Create_Field hStruct At iColumn

Set_Attribute DF_FIELD_NAME Of hStruct iColumn To "NewColumn"

Set_Attribute DF_FIELD_TYPE Of hStruct iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hStruct iColumn To 20

Get Proceed hStruct To bSave

If (bSave) ;

Structure_End hStruct

Else ;

Structure_Abort hStruct

//*** Add an Index (City, Customer_Number)

Open Customer Mode DF_EXCLUSIVE

Move Customer.File_Number To hStruct

Structure_Start hStruct

Move 0 To iIndex

Create_Index hStruct At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hStruct iIndex To 2

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hStruct iIndex 1 To 4

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hStruct iIndex 2 To 1

Get Proceed hStruct To bSave

If (bSave) ;

Structure_End hStruct

Else ;

Structure_Abort hStruct

//*** Add a column and an index (State, Customer_Number)

Open Customer Mode DF_EXCLUSIVE

Move Customer.File_Number To hStruct

Structure_Start hStruct

Move 0 To iColumn

Create_Field hStruct At iColumn

Set_Attribute DF_FIELD_NAME Of hStruct iColumn To "NewColumn2"

Set_Attribute DF_FIELD_TYPE Of hStruct iColumn To DF_ASCII

Set_Attribute DF_FIELD_LENGTH Of hStruct iColumn To 20

Move 0 To iIndex

Create_Index hStruct At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hStruct iIndex To 2

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hStruct iIndex 1 To 5

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hStruct iIndex 2 To 1

Get Proceed hStruct To bSave

If (bSave) ;

Structure_End hStruct

Else ;

Structure_Abort hStruct

End_Procedure // RestructTest

The sample function above shows a message box in which the user is informed on the action. The procedure calls the function to determine if the save should proceed.


DF_FILE_REUSE_DELETED

See Also: Get_Attribute, Set_Attribute

Controls the re use or non re use of space occupied by deleted records in a table.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_FILE_DELETED_NOREUSE, DF_FILE_DELETED_REUSE

Remarks

When a record is deleted from an Embedded Database table, the space it occupied is not released. Instead, the record is marked as deleted. The DF_FILE_REUSE_DELETED attribute indicates how this space is treated when new records are added to the table. A value of DF_FILE_DELETED_NOREUSE indicates deleted space will never be reused. A value of DF_FILE_DELETED_REUSE indicates the space will be reused.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. That is why the Pervasive.SQL and SQL based Connectivity Kits will return DF_FILE_DELETED_REUSE for every table accessed.

This attribute can only be set inside a Structure_Start ... Structure_End operation.

In order to be able to reclaim the space occupied by deleted records, an Embedded Database table maintains a so called free list. This is a single linked list. When a table has its reuse attribute set to "no reuse", the list will not be maintained. When the attribute value is changed from "no reuse" to reuse on a table that has deleted space, this space will not be added to the free list. The free list will be maintained from that point on. Deleted space can be added to the free list by the repair wizard.

It is expected this attribute will always be set to reuse the deleted space. The only reason not to reuse the deleted space is if the record number has a meaning and should never be assigned twice. Having record numbers that have a meaning, such as using Recnum relations, is a strongly discouraged technique.

Procedure ShowNoReuse

Handle hTable

String sTable

Integer iReuse

Integer iNumTables

Move 0 To hTable

Move 0 To iNumTables

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_REUSE_DELETED Of hTable To iReuse

If (iReuse = DF_FILE_DELETED_NOREUSE) Begin

Increment iNumTables

If (iNumTables = 1) ;

Showln "List of tables that do not reuse delete space:"

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln " " sTable

End

Close hTable

End

Until (hTable = 0)

If (iNumTables = 0) ;

Showln "All tables reuse deleted space."

Else Begin

Showln "You may want to switch the reuse deleted space setting for ;

" (If(iNumTables > 1, "these tables.", "this table."))

Showln "To reclaim already deleted space run the repair wizard."

End

End_Procedure // ShowNoReuse

The sample procedure above checks all tables in the filelist. If a table is not reusing deleted space this is reported.


DF_FILE_REVISION

See Also: Get_Attribute, Set_Attribute, Structure_Start

Returns the revision of the table.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read Only

Values

A string containing the version of the table.

Remarks

The attribute holds the table’s revision.

The Pervasive.SQL Connectivity Kit returns the version of Pervasive.SQL.

The SQL Based Connectivity Kits return the database name plus its version.

The Embedded Database supports three table revisions, 2.3, 3.0 and 4.0. When a table is opened, its revision is checked and if the revision is not supported, the table is not opened and an error (DFERR_DATA_FILE_NOT_COMPATIBLE) is generated.

Revision | Capabilities | Introduced
2.3 | Support for ASCII, Numeric, Date and Overlap columns Support for 10 indices that can hold 6 segments each | DataFlex 2.3
3.0 | Same as 2.3 with additional features: Support for text and binary columns Support for 15 indices that can hold 16 segments each Support for header integrity checking Support for restructuring tables by improved tools/API | DataFlex 3.0
4.0 | Same as 3.0. A table will change to version 4.0 if one (or more) of its columns relate to another table with a number higher then 255. If the table’s definition is adjusted so that there are no more columns that relate to tables with a number above 255, the revision will fall back to 3.0. | Visual DataFlex 7 and DataFlex 3.2

When the definition of a table with revision 2.3 is changed, it will be saved as (at least) a 3.0 table. After this, the table cannot be opened by 2.3 DataFlex applications. Revision 4.0 tables cannot be opened by versions of Visual DataFlex prior to 7 and versions of DataFlex prior to 3.2.

Procedure ShowRevision

Handle hTable

String sTable

String sRevision

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_REVISION Of hTable To sRevision

Showln sTable " -- " sRevision

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowRevision

The sample procedure above shows the revision of every table in the filelist.


DF_FILE_ROOT_NAME

See Also: Get_Attribute, Set_Attribute

The table name (including an optional path) stored in the file list.

Level

Table

Supported by

All Connectivity Kits

Type

String, permanent

Access

Read / Write

Values

A string that points to a physical table

Remarks

The root name can contain any characters that are legal in a table name on the operating system where the table is located and can be up to 40 characters long.

The rootname of a database file is the name of the table including an optional directory path. If the table is a non-Embedded Database table, driver_name and/or filename_suffix must be present. This is how DataFlex determines which database driver should get the open request. The actual driver name and/or filename suffix that must be used with a particular database type is defined in the database-driver documentation.

If the filename suffix is .INT, then an intermediate file is being used. Many non-Embedded Database drivers support an intermediate file as a storage place for attributes that are not supported in the native database.

An intermediate file is an ASCII file that contains lines of keyword/value pairs that describe the attributes of the non-Embedded Database table. The first line in an intermediate file always contains the driver name and is used to determine which database driver should get the open request.

Unlike other permanent table level attributes, the filelist attributes (DF_FILE_DISPLAY_NAME, DF_FILE_ROOT_NAME and DF_FILE_LOGICAL_NAME) can be set outside of a Structure_Start ... Structure_End operation. These attributes are actually stored in the filelist and not in the database or table.

To add a table to an existing filelist, the 3 filelist attributes must be set at the same time. To remove a table from the filelist, the 3 filelist attributes must be set to an empty string.

Procedure ShowFilelistNames

Handle htable

String sRoot

String sDisplay

String sTable

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Get_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln hTable ", " sRoot ", " sDisplay ", " sTable

End

Until (hTable = 0)

End_Procedure // ShowFilelistNames

The sample procedure above show all the filelist attributes.

Procedure NewEntry Handle hTable String sRoot String sDisplay String sTable

Set_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

End_Procedure // ShowFilelistNames

The sample procedure above creates a new filelist entry at a given slot. It can also be used to remove a filelist entry by passing empty strings for the three filelist attributes.

Procedure CreateNewFilelist String sNewList

Handle hoWorkspace

String sPath

Integer iMaxSlots

//*** Make sure new filelist comes in first directory of datapath

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - sNewList) To sPath

//*** Create the disk file

Direct_Output sPath

Write "filelist.cfg"

Close_output

//*** Use the disk file as fileist

Set_attribute DF_FILELIST_NAME To sPath

//*** Create all the slots

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iMaxSlots

Send NewEntry iMaxSlots "" "" ""

End_Procedure // CreateNewFilelist

The sample procedure above uses the filelist attributes to create a new empty filelist. It calls the NewEntry procedure defined above.


DF_FILE_SQL_FILTER

A filter to apply to select statements generated for find operations on the table.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, temporary

Access

Read / Write

Values

A filter expression.

Remarks

This attribute allows the programmer to define a filter that is applied to find operations. It can be used to speed up find operations. The filter value in the attribute is added to the beginning of the where clause of statements generated for find operations but it will not be added for find eq operations. You must use SQL syntax in the filter string. The filter is applied when the DF_FILE_SQL_FILTER_ACTIVE attribute is set to true.

For more information about SQL filters, see Using SQL Filters (Constraints).


DF_FILE_SQL_FILTER_ACTIVE

Indicates if the SQL filter is applied on find operations.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

This attribute controls if the filter in DF_FILE_SQL_FILTER is applied or not. When set to true, the filter is applied, when set to false the filter is not applied.

For more information about SQL filters, see Using SQL Filters (Constraints).


DF_FILE_STATUS

See Also: Get_Attribute, Set_Attribute

The status of the table’s record buffer.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, temporary

Access

Read / Write

Values

DF_FILE_INACTIVE, DF_FILE_ACTIVE, DF_FILE_ACTIVE_CHANGED

Remarks

When a table is opened, a global table buffer is allocated. This buffer can hold one record at a time. The DF_FILE_STATUS attribute returns the status of the global table buffer. A buffer status will remain the same until an operation changes the status. The table below shows the meaning of the possible values and the operations that cause the buffer to get that status.

Value

Meaning

DF_FILE_INACTIVE

The record buffer does not hold an active record. The next save operation on the buffer will create a new record. Record buffers become inactive by issuing a clear.

If the table is a recnum table, an alternative way for the buffer to become inactive is by moving a value (any value) to the recnum column. This was often used to create copies of existing records. This technique is considered obsolete, instead set the DF_FILE_STATUS attribute.

DF_FILE_ACTIVE

The record buffer holds an active record. The buffer becomes active when a record is found or after a successful save.

DF_FILE_ACTIVE_CHANGED

The record buffer holds an active record of which at least one column has changed. The buffer becomes active changed after moving a value to a column in an active buffer. Moving a value to a column that is already in the buffer is not considered a change.

It is possible to set this attribute directly, but the only value that you can set it to is DF_FILE_INACTIVE.

Note that DataDictionaries use local buffers. See Understanding File Buffers and DDO Field Buffers on when to use the global or local buffer.

The DF_FILE_STATUS attribute can be used to determine if a find or save operation was successful. When a find operation is successful the global variable found is also set. The problem with found is that is used by many of the commands and cannot be relied upon unless tested directly after the find operation. The status of the buffer on the other hand is only changed by certain operations and can be relied upon even if there are several other operations between the find and the test of the status.

Procedure CreateCustomerCopy Integer iOrgCustomer Integer iNewCustomer

Clear Customer

Move iOrgCustomer To Customer.Customer_Number

Find Eq Customer.Customer_Number

If (Found) Begin

Begin_Transaction

Set_Attribute DF_FILE_STATUS Of Customer.File_Number To DF_FILE_INACTIVE

Move iNewCustomer To Customer.Customer_number

Saverecord Customer

End_Transaction

End

End_Procedure // CreateCustomerCopy

The sample procedure above show how the create a low level copy of a record.

Function PendingChanges Returns Boolean

Handle hTable

Integer iStatus

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_STATUS Of hTable To iStatus

If (iStatus = DF_FILE_ACTIVE_CHANGED) ;

Function_return True

End

Until (hTable = 0)

Function_Return False

End_Function // PendingChanges

The sample function above returns true is there is at least one open table for which the buffer has the DF_FILE_ACTIVE_CHANGED status, it returns false otherwise. It can be used to see if there are pending changes to existing records.


DF_FILE_TABLE_CHARACTER_FORMAT

The format of the ASCII data in the table.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read / Write

Values

"OEM", "ANSI"

Remarks

DataFlex programs use data in OEM format. Most Windows applications expect data to be in ANSI format. If you want to access data from DataFlex and some other Windows tool, it may be required that you have the data stored in ANSI format.

When this attribute is set to "OEM", the Connectivity Kit will store and retrieve data unchanged. When this attribute is set to "ANSI", the Connectivity Kit will convert any data it store and retrieves. Stored data is converted from OEM to Ansi before it is passed on to the back end. Retrieved data is converted from Ansi to OEM before it is passed on to Visual DataFlex. In Visual DataFlex there is no need to worry about the format of the data, it is always OEM.

Be aware that setting this attribute’s value will only change the way data is presented and new data is stored. Existing data will not be converted from OEM to ANSI or vice versa. You need to run a conversion utility to convert existing data.

Character formats apply to ASCII and Text columns. If such a column uses an ASCII value above 127 like ë, ä, è, à they will need to be converted. These characters are also known as diacritical characters.

This attribute can be set both inside and outside of a Structure_Start ... Structure_End operation. The value of the attribute is stored in the intermediate file using the keyword Table_Character_Format.

See Character Formats (OEM or Ansi) for more information.

Procedure ConvertRow Handle hTable String sOrgFormat String sNewFormat

String sValue

Integer iNumColumns

Integer iType

Integer iColumn

//*** Loop through the fields and convert ASCII and text fields

Get_Attribute DF_FILE_NUMBER_FIELDS Of hTable To iNumColumns

For iColumn From 1 To iNumColumns

Get_Attribute DF_FIELD_TYPE Of hTable iColumn To iType

If ((iType = DF_ASCII) Or (iType = DF_TEXT)) Begin

Set_Attribute DF_FILE_TABLE_CHARACTER_FORMAT Of hTable To sOrgFormat

Get_Field_Value hTable iColumn To sValue

Set_Attribute DF_FILE_TABLE_CHARACTER_FORMAT Of hTable To sNewFormat

Set_Field_Value hTable iColumn To sValue

End

Loop

End_Procedure // ConvertRow

Procedure ConvertTableCharacterFormat Handle hTable Integer iIndex String sNewFormat

String sFormat

Boolean bFound

String sOrgFormat

Get_Attribute DF_FILE_TABLE_CHARACTER_FORMAT Of hTable To sFormat

If (Uppercase(sFormat) <> Uppercase(sNewFormat)) Begin

If (Uppercase(sNewFormat) = "ANSI") ;

Move "OEM" To sOrgFormat

Else If (Uppercase(sNewFormat) = "OEM") ;

Move "ANSI" To sOrgFormat

Else ;

Procedure_Return

Begin_Transaction

Clear hTable

vFind hTable iIndex Gt

While (Found)

Send ConvertRow hTable sOrgFormat sNewFormat

Get_Attribute DF_FILE_STATUS Of hTable To iStatus

If (iStatus = DF_FILE_ACTIVE_CHANGED) ;

SaveRecord hTable

vFind hTable iIndex Gt

End

End_Transaction

End

End_Procedure // ConvertTableCharacterFormat

The sample procedure above converts a table from one format to the other. It does this in one big transaction. To run this procedure the transaction log of the database must be big enough to hold this size of transaction. Note that the procedure uses the feature that moving a value to a column that already has that value is not seen as a change. This decreases the transaction size to those records that actually do change.


DF_FILE_TABLE_NAME

The name of the table.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read / Write

Values

A valid table name.

Remarks

This attribute holds the name of the table in the back end. Depending on the back end, table names may be case sensitive, contain spaces or other special characters. This attribute is used to determine a table’s back end name when using Embedded SQL. Since Embedded SQL works on the back end directly, the back end’s name must be used. In most cases the back end name will be the same as the table name used in Visual DataFlex.

This attribute can also be set through the intermediate file keyword Database_Name.

Procedure ShowRow Handle hstmt

Integer iNumCols

Integer iCol

String sValue

Get SQLStmtAttribute Of hstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumCols

For iCol From 1 To iNumCols

If (iCol > 1) ;

Show ", "

Get SQLColumnValue Of hstmt iCol To sValue

Show sValue

Loop

Showln

End_Procedure // ShowRow

Procedure ShowContents Handle hTable

String sTable

Handle hoSQL

Handle hdbc

Handle hstmt

Integer iFetchResult

Get_Attribute DF_FILE_TABLE_NAME Of hTable To sTable

Get Create U_cSQLHandleManager To hoSQL

If (hoSQL > 0) Begin

Get SQLFileConnect Of hoSQL hTable To hdbc

If (hdbc > 0) Begin

Get SQLOpen Of hdbc To hstmt

If (hstmt > 0) Begin

Send SQLExecDirect Of hstmt ("select * from" * sTable)

Repeat

Get SQLFetch Of hstmt To iFetchResult

If (iFetchResult <> 0) ;

Send ShowRow hstmt

Until (iFetchResult = 0)

Send SQLClose Of hstmt

End

Send SQLDisconnect Of hdbc

End

Send Destroy Of hoSQL

End

End_Procedure // ShowContents

The sample procedure above show the use of the DF_FILE_TABLE_NAME attribute for an Embedded SQL Statement.


DF_FILE_TOUCHED

See Also: Get_Attribute, Set_Attribute

Indicates whether the table has been affected by the last relate or reread.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, temporary

Access

Read Only

Values

DF_FILE_NOT_TOUCHED, DF_FILE_TOUCHED_INACTIVE, DF_FILE_TOUCHED_ACTIVE

Remarks

DF_FILE_TOUCHED is DF_FILE_NOT_TOUCHED if the table was not involved in the last reread or relate, DF_FILE_TOUCHED_INACTIVE if the table was involved in the last reread or relate, and its record buffer is inactive, and DF_FILE_TOUCHED_ACTIVE if a table was involved in the last reread or relate and its record buffer is active.

The DF_FILE_TOUCHED attributes of open tables are updated when a relate or reread operation occurs. This update does not take place when using the reread command with arguments! There are two ways to use the reread command. Without arguments and with arguments. Although it is the same command that is used its implementation is different.

Procedure ShowTouched

Handle hTable

String sTable

Integer iTouched

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_TOUCHED Of hTable To iTouched

Case Begin

Case (iTouched = DF_FILE_NOT_TOUCHED)

Showln sTable " NOT touched."

Case Break

Case (iTouched = DF_FILE_TOUCHED_INACTIVE)

Showln sTable " touched INACTIVE."

Case Break

Case (iTouched = DF_FILE_TOUCHED_ACTIVE)

Showln sTable " touched ACTIVE."

Case Break

Case End

End

Until (hTable = 0)

End_Procedure // ShowTouched

Procedure ManipulateTouched

Open Salesp

Open Customer

Open Invt

Open Vendor

Open OrderHea

Open OrderDtl

Clear OrderHea

Find Gt OrderHea By 1

If (Found) Begin

Relate OrderHea

Showln "The touched status of the open buffers after Relate OrderHea:"

Send ShowTouched

End

Find Gt OrderDtl By 1

Reread OrderDtl

Unlock

Showln

Showln "The touched status of the open buffers after Relate OrderHea,"

Showln "a find on OrderDtl and then a reread with argument:"

Send ShowTouched

Reread

Unlock

Showln

Showln "The touched status of the open buffers after Relate OrderHea,"

Showln "a find on OrderDtl and then a reread without argument:"

Send ShowTouched

End_Procedure // ManipulateTouched

The procedure above shows the touched status after a relate, a reread with and a reread without arguments.


DF_FILE_TRANSACTION

See Also: Get_Attribute, Set_Attribute

Indicates the type of transaction processing for the table.

Level

Table

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_FILE_TRANSACTION_NONE, DF_FILE_TRANSACTION_CLIENT_ATOMIC, DF_FILE_TRANSACTION_SERVER_ATOMIC, DF_FILE_TRANSACTION_SERVER_LOGGED

Remarks

DF_FILE_TRANSACTION_NONE indicates this table is not eligible for transaction processing. DF_FILE_TRANSACTION_CLIENT_ATOMIC, DF_FILE_TRANSACTION_SERVER_ATOMIC, and DF_FILE_TRANSACTION_SERVER_LOGGED indicate the level of transaction processing that will be applied to the table. The availability and functionality of these levels are driver dependent.

Client-atomic transactions can be aborted by the program and, under some circumstances (e.g., deadlock) they will be aborted automatically by Visual DataFlex. Client-atomic transactions do not provide protection from workstation crashes. If the workstation (whether from program failure or system failure) crashes while a client-atomic transaction is outstanding, part of the transaction may have already been written to the database and cannot be automatically backed out.

Server-atomic transactions offer the same benefits as client-atomic transactions and, in addition, offer protection from workstation crashes. If a program (or the system) crashes while a server-atomic transaction is outstanding, the full transaction can be automatically backed out.

Server-logged transaction control offers the same benefits as server-atomic transaction control and, in addition, offer a rollback capability. System rollback restores the system to its status as of a specified point in time. For example, if your company payroll processing was started at 1 p.m. and then something went badly awry later in the afternoon, you could use this functionality to roll back the state of your system to the way it was at 1 p.m., so you could start again. Note that all transaction processing done after 1 p.m. would be affected, not just the payroll.

This attribute can only be set inside a Structure_Start ... Structure_End operation.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. It however does not make any sense in some back ends. That is why the Pervasive.SQL will return DF_FILE_TRANSACTION_SERVER_ATOMIC and SQL Based Connectivity Kits will return DF_FILE_TRANSACTION_SERVER_LOGGED for every table accessed. Trying to set the attribute will be ignored.

The Embedded Database supports the values DF_FILE_TRANSACTION_NONE, DF_FILE_TRANSACTION_CLIENT_ATOMIC and DF_FILE_TRANSACTION_SERVER_ATOMIC.

Client atomic transactions in the Embedded Database

Once Begin_Transaction has been executed, all database changes are written to a virtual transaction file. There are actually only three operations that have to be saved in the transaction file. When you edit a record, the old contents of the changed fields, the record number, and the file number are saved. When you delete a record, the whole record, the record number and the file number are saved. When you write a new record, the record number of the new record and the file number are saved.

When the transaction is committed, the current contents of the transaction file are discarded. The transaction-abort process is more complicated, but basically the transaction file is read backwards sequentially. As each table change is encountered, the appropriate action is taken to back out the change. New records are deleted; deleted records are restored (with the original record numbers), and edited records are changed back to their original contents. Therefore, the tables are put back into the exact state they were in prior to the transaction. This works even for tables that do not allow reuse of deleted records. Once the transaction is backed out, the contents of the transaction file are discarded. If you terminate your program with a transaction in progress, an automatic transaction abort will occur.

Since we are writing to a "virtual transaction file", the file will use extended and/or expanded memory with only the overflow actually being written to disk. Since the transaction file will never contain more than one transaction’s data, it is most likely that memory will not be overflowed and no actual disk I/O will ever occur.

Client-atomic transaction processing does not protect a database from a crash. This means that if a transaction was in progress and the system crashes (maybe because of a power failure), or your program terminates abnormally, the transaction will be partially completed. You would then have to either manually fix up the files or restore the files from backup.

There is also no protection from I/O errors. If you get an I/O error during a database operation that is part of a transaction, you can attempt to abort the transaction. However, there is no guarantee that the abort will work correctly. It is also possible to get an error during the abort process itself. In either case, Abort_Transaction would return an error and you would probably want to restore the files from backup.

A lock is in effect during a transaction. While this prevents other processes from writing to the files, it does not prevent them from reading. This means that, just as when not using transaction processing, another process can read a partially complete transaction.

Server atomic transactions in the Embedded Database

The Embedded Database driver uses NetWare’s Transaction Tracking System to support transaction control at the server. You must use a NetWare shell in order to make use of this feature, and TTS must be enabled in your installation of the shell.

Server-based transaction control permits complete backing-out of an incomplete transaction upon failure of the program or the workstation from which the transaction is being entered. This occurs automatically upon such failure. If this feature is in use, no reindexing should be required after such a failure. In fact, other workstations, even those with incomplete transactions at the time, can continue normal operations through such an event.

Use of this feature entails no special provisions in the source code of the program being run other than those required for transaction control generally. It is, however, necessary to set the DF_FILE_TRANSACTION attribute of every table involved to DF_FILE_TRANSACTION_SERVER_ATOMIC to use it.

Setting a table server-atomic causes the NetWare "transaction flag" to be set on the .DAT, .VLD, and .K?? files. When a DataFlex transaction is started, a NetWare TTS transaction-start is sent to every NetWare server on which any of these tables resides. At the end of the transaction, a TTS transaction-end is sent to the same servers.

If a Visual DataFlex transaction exceeds the size limits imposed by your local version of TTS, the network administrator will receive a NetWare error report of it. The Visual DataFlex program itself, however, will function normally, but without TTS protection for such transaction.

If you try to delete a TTS-flagged file through the operating system, it will stop you. You would have to reset the flag with the NetWare FLAG command before you would be able to do the deletion. If you perform such manipulations through Visual DataFlex, however, the flag will be reset as necessary to permit the desired operations.

If you attempt to set a file to server-atomic that is not on a TTS capable NetWare volume, the DFERR_FILE_NOT_ON_TTS_VOLUME error will be reported. If a Visual DataFlex program opens a table flagged for TTS that is not on a TTS-capable volume, the same error will be reported at that time.

Procedure ShowTransaction

Handle hTable

String sTable

Integer iTransaction

String sTransaction

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_TRANSACTION Of hTable To iTransaction

Case Begin

Case (iTransaction = DF_FILE_TRANSACTION_NONE)

Move "NO Transaction" To sTransaction

Case Break

Case (iTransaction = DF_FILE_TRANSACTION_CLIENT_ATOMIC)

Move "Client Atomic Transaction" To sTransaction

Case Break

Case (iTransaction = DF_FILE_TRANSACTION_SERVER_ATOMIC)

Move "Server Atomic Transaction" To sTransaction

Case Break

Case (iTransaction = DF_FILE_TRANSACTION_SERVER_LOGGED)

Move "Server Logged Transaction" To sTransaction

Case Break

Case End

Showln sTable " -- " sTransaction

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowTransaction

The sample procedure above show the transaction type of every table in the filelist.

Procedure ChangeTransaction Integer iOrgTransaction Integer iNewTransaction

Handle hTable

Handle hStruct

Integer iTransaction

If (iOrgTransaction = iNewTransaction) ;

Procedure_Return

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_TRANSACTION Of hTable To iTransaction

If (iTransaction = iOrgTransaction) Begin

Move hTable To hStruct

Structure_Start hStruct

Set_Attribute DF_FILE_TRANSACTION Of hStruct To iNewTransaction

Structure_End hStruct

End

Else ;

Close hTable

End

Until (hTable = 0)

End_Procedure // ChangeTransaction

The sample procedure above changes every table in the filelist that uses a given transaction type to another transaction type.


DF_FILE_TYPE

See Also: Get_Attribute, Set_Attribute

The type identifier of the database Connectivity Kit used to open the table.

Level

Table

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read Only

Values

0, 1, 9, 10, 11 ..

Remarks

Every database Connectivity Kit has a numeric identifier. This identifier can be queried by using the DF_FILE_TYPE attribute. You can also use the DF_FILE_DRIVER attribute to check the type of a table.

We recommend using the DF_FILE_DRIVER attribute to determine a table’s Connectivity Kit.

The table below shows the possible Connectivity Kits and their identifiers.

Connectivity Kit | Value
Embedded Database | 0
ODBC | 1
Pervasive.SQL | 9
DB2 | 10
SQL Server | 11

Procedure ShowTableType

Handle hTable

String sTable

String sDriver

Integer iType

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

Get_Attribute DF_FILE_TYPE Of hTable To iType

Showln sTable " -- " sDriver " (" iType ")"

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowTableType

The sample procedure above shows the type of every table in the filelist.


DF_FILE_USE_DUMMY_ZERO_DATE

Indicates if dummy zero dates should be used for the table.

Level

Table

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, permanent

Access

Read Only

Values

True, False

Remarks

Visual DataFlex supports zero dates, SQL databases generally do not. The only way to store a zero date in a column in a table in a SQL database is to store is as NULL. NULL values, when used in indexed columns, slow down finding considerably. Using dummy zero dates will let the Connectivity Kit will interpret a constant date value as if it was the zero date. If that value is in a date column, it will be reported to Visual DataFlex as the zero date. If Visual DataFlex moves a zero date to the column, it will be translated into this value. The constant values are:

Connectivity Kit | Value
SQL Server | 1753-01-01
DB2 | 0001-01-01
ODBC | 0001-01-01

This attribute can only be set inside a Structure_Start ... Structure_End operation. The value of this attribute is stored in the intermediate file using the keyword Use_Dummy_Zero_Date.

Procedure ShowDummyDates

Boolean bFound

Handle hoSQL

Handle hdbc

Handle hstmt

Integer iFetchResult

String sZeroDate

Open OrderHea

Clear OrderHea

Repeat

Find Gt OrderHea By 3

if (Found) move (OrderHea.Order_Date = 0) to Found

Move (Found) To bFound

If (bFound) Begin

Get Create U_cSQLHandleManager To hoSQL

If (hoSQL <> 0) Begin

Get SQLFileConnect Of hoSQL OrderHea.File_Number To hdbc

If (hdbc <> 0) Begin

Get SQLOpen Of hdbc To hstmt

If (hstmt <> 0) Begin

Send SQLExecDirect Of hstmt ("Select Order_Date From OrderHea Where Order_Number =" * String(OrderHea.Order_number))

Get SQLFetch Of hstmt To iFetchResult

If (iFetchResult <> 0) ;

Get SQLColumnValue Of hstmt 1 To sZeroDate

Else ;

Move "" To sZeroDate

Showln "Order " OrderHea.Order_Number " has a zero date in SQL it is stored as: " sZeroDate

Send SQLClose Of hstmt

End

Send SQLDisconnect Of hdbc

End

Send Destroy Of hoSQL

End

End

Until (Not(bFound))

End_Procedure // ShowDummyDates

The sample procedure above loops through the OrderHea records and finds all the order header that have a zero date. It then uses Embedded SQL to get the value actually stored in the back end and shows this.


DF_FILELIST_NAME

See Also: Get_Attribute, Set_Attribute

The name of the file-list file currently in use.

Level

Global

Type

String, temporary

Access

Read / Write

Values

The path (optional) and filename for a file list

Remarks

This attribute may be used to dynamically change the name of the filelist in use. This allows your programs to open files from multiple filelists in the same session. The default filelist name used in Visual DataFlex applications and all Visual DataFlex tools is "filelist.cfg".

The use of multiple filelists was needed in some applications in revisions of Visual DataFlex prior to VDF 7 and revisions of character-mode DataFlex prior to DataFlex 3.2, because each filelist only supported 255 files. As of VDF 7 and DataFlex 3.2, each filelist supports 4095 files, drastically reducing the need for multiple filelists. However, this attribute may still be required for maintaining and upgrading legacy applications.

Procedure ShowFilelistName

String sName

Get_Attribute DF_FILELIST_NAME To sName

Showln "The current filelist name is: " sName

End_Procedure // ShowFilelistName

The sample procedure above shows the name of the file currently used as filelist.

Procedure NewEntry Handle hTable String sRoot String sDisplay String sTable

Set_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

End_Procedure // ShowFilelistNames

Procedure CreateNewFilelist String sNewList

Handle hoWorkspace

String sPath

Integer iMaxSlots

//*** Make sure new filelist comes in first directory of datapath

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - sNewList) To sPath

//*** Create the disk file

Direct_Output sPath

Write "filelist.cfg"

Close_output

//*** Use the disk file as filelist

Set_attribute DF_FILELIST_NAME To sPath

//*** Create all the slots

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iMaxSlots

Send NewEntry iMaxSlots "" "" ""

End_Procedure // CreateNewFilelist

The sample procedure above creates a new, empty, filelist and then set the DF_FILELIST_NAME attribute to use that new filelist.


DF_HIGH_DATA_INTEGRITY

See Also: Get_Attribute, Set_Attribute, DF_FILE_INTEGRITY_CHECK

Sets or disables high data-integrity mode for tables.

Level

Global

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

If DF_HIGH_DATA_INTEGRITY is True, all disk writes (save, delete, etc.) are immediately followed by a low level file close. This forces the O/S to write the table’s buffers to disk and to update the table's directory entry, while this offers some protection from power failures and system crashes, it also degrades performance.

This setting only applies to Embedded Database tables.

The attribute is set to false by default. When this attribute is set, it is usually set once at the beginning of a program.

Procedure ShowHighIntegrity

Boolean bIntegrity

Get_Attribute DF_HIGH_DATA_INTEGRITY To bIntegrity

Showln "High data integrity is " (If(bIntegrity, "ON", "OFF"))

End_Procedure // ShowHighIntegrity

The sample procedure above shows the current setting of the attribute.


DF_INDEX_KEY_LENGTH

See Also: Get_Attribute, Set_Attribute

The length of the key for the index.

Level

Index

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read only

Values

1 ~ maximum length supported in the database

Remarks

Since the value of DF_INDEX_KEY_LENGTH is dependent on how the database stores its data, it may not equal the sum of the values of the DF_FIELD_LENGTH attributes for the fields that make up the index.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. SQL Based Connectivity Kits will return 0 (zero) for every table accessed. Trying to set the attribute will be ignored.

The Embedded Database and Pervasive.SQL Connectivity Kit support this attribute. For the Embedded Database the attribute can be used to calculate the “real” maximum number of records in a table, see DF_FILE_MAX_RECORDS for a discussion of the “real” maximum.

Define C_MAXINDEXCAPACITY For |CI$00feffff

Function IndexCapacity Integer iKeylength Integer iLevels Returns Integer

Integer iCapacity

Integer iBlocking

Move (1024.0 / (iKeylength + 3)) To iBlocking

Move (((iBlocking ^ iLevels) - 1) Min C_MAXINDEXCAPACITY) To iCapacity

Function_Return iCapacity

End_Function // IndexCapacity

Function RealMaximum Handle hTable Returns Integer

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iKeyLength

Integer iLevels

Integer iIndexCapacity

Integer iTableCapacity

Move 0 To iTableCapacity

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_KEY_LENGTH Of hTable iIndex To iKeyLength

Get_Attribute DF_INDEX_LEVELS Of hTable iIndex To iLevels

Get IndexCapacity iKeyLength iLevels To iIndexCapacity

If (iTableCapacity = 0 Or iTableCapacity > iIndexCapacity) ;

Move iIndexCapacity To iTableCapacity

End

Loop

Function_Return iTableCapacity

End_Function // RealMaximum

The sample function above returns the real maximum number of records in an Embedded Database table.


DF_INDEX_LEVELS

See Also: Get_Attribute, Set_Attribute

The number of levels in the index.

Level

Index

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read only

Values

0 ~ maximum levels allowed per index for the database

Remarks

An index on a table is stored in a tree like structure, the DF_INDEX_LEVELS attribute returns the number of levels in this tree.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. SQL Based Connectivity Kits will return 0 (zero) for every table accessed; the Pervasive.SQL Connectivity Kit will return -1 for every table accessed. Trying to set the attribute will be ignored.

The Embedded Database supports this attribute. For the Embedded Database the attribute can be used to calculate the “real” maximum number of records in a table, see DF_FILE_MAX_RECORDS for a discussion of the “real” maximum.

Define C_MAXINDEXCAPACITY For |CI$00feffff

Function IndexCapacity Integer iKeylength Integer iLevels Returns Integer

Integer iCapacity

Integer iBlocking

Move (1024.0 / (iKeylength + 3)) To iBlocking

Move (((iBlocking ^ iLevels) - 1) Min C_MAXINDEXCAPACITY) To iCapacity

Function_Return iCapacity

End_Function // IndexCapacity

Function RealMaximum Handle hTable Returns Integer

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iKeyLength

Integer iLevels

Integer iIndexCapacity

Integer iTableCapacity

Move 0 To iTableCapacity

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_KEY_LENGTH Of hTable iIndex To iKeyLength

Get_Attribute DF_INDEX_LEVELS Of hTable iIndex To iLevels

Get IndexCapacity iKeyLength iLevels To iIndexCapacity

If (iTableCapacity = 0 Or iTableCapacity > iIndexCapacity) ;

Move iIndexCapacity To iTableCapacity

End

Loop

Function_Return iTableCapacity

End_Function // RealMaximum

The sample function above returns the real maximum number of records in an Embedded Database table.


DF_INDEX_NAME

The name of the index.

Level

Index

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read / Write

Values

Any valid index name

Remarks

In SQL databases an index is identified by a name. Often index names are assigned as tables are designed. In some cases, the back end will automatically create an index to enforce certain constraints. The name of indices created this way will often be the same as the constrain name.

This attribute can only be set inside a Structure_Start ... Structure_End operation. The value of this attribute is stored in the intermediate file under the keyword Index_Name.

Procedure ShowTableIndexNames Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

String sIndex

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_NAME Of hTable iIndex To sIndex

Showln " Index " iIndex ": " sIndex

End

Loop

End_Procedure // ShowTableIndexNames

Procedure ShowIndexNames

Handle hTable

String sTable

String sRevision

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Index name sfor " sTable

Send ShowTableIndexNames hTable

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowIndexNames

The sample procedure above show all index names of all tables in the filelist.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The procedure above creates a new table in the SQL Server Northwind database. It is used to store clock in and clock out information of employees. One index called ClockPK is created on this table.


DF_INDEX_NUMBER_BUFFERS

See Also: Get_Attribute, Set_Attribute

The number of levels to buffer for the index.

Level

Index

Supported by

All Connectivity Kits

Type

Numeric, temporary

Access

Read / Write

Values

0 ~ maximum number of buffers allowed by the database

Remarks

DF_INDEX_NUMBER_BUFFERS allows an Embedded Database index to be buffered in memory. This may increase performance on disk read operations. This feature must not be used at any time when the file may be written to. If indices are buffered while another program is writing to the table, records may not be found correctly, save errors may occur, and file relationships may not work.

Next to setting this attribute explicitly, an index can be buffered via the open command, specifying an index in the open statement (e.g. Open Customer 2) will use buffering on the specified index.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. SQL Based Connectivity Kits will return 0 (zero) for every table accessed; the Pervasive.SQL Connectivity Kit will return -1 for every table accessed. Trying to set the attribute will be ignored.

Procedure ShowBuffers Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iNumBuffers

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_NUMBER_BUFFERS Of hTable iIndex To iNumBuffers

Showln " Index " iIndex ": " iNumBuffers

End

Loop

End_Procedure // ShowBuffers

The sample procedure above shows the number of buffers for every index of the specified table.


DF_INDEX_NUMBER_SEGMENTS

See Also: Get_Attribute, Set_Attribute, Delete_Index , DF_FILE_LAST_INDEX_NUMBER

The number of segments in the index.

Level

Index

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

0 ~ maximum number of segments allowed by the database

Remarks

The DF_INDEX_NUMBER_SEGMENTS attribute values range from 0 to the maximum number of segments in an index for the database in use. The attribute can be set to alter an index definition. It can, however, not be set to 0 (zero). In order to delete an index use the Delete_Index command. To create an index, use the Create_Index command and set the DF_INDEX_NUMBER_SEGMENTS attribute.

The attribute can be used to determine if an index exists at a certain number. If the number of segments is 0 (zero) no index exists, if the number of segments is 1 or greater, the index exists.

There are no Create_IndexSegment or Delete_IndexSegment commands. Segments are created or deleted by setting the DF_INDEX_NUMBER_SEGMENTS attribute to its new value and adjusting the individual index segment attributes.

This attribute can only be set inside a Structure_Start ... Structure_End operation. The value of this attribute may be stored in the intermediate file under the keyword Index_Number_Segments.

Procedure ShowExistingIndices Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) ;

Showln " Index " iIndex

Else;

Showln " Index " iIndex " does NOT exist"

Loop

End_Procedure // ShowExistingIndices

The sample procedure above shows all existing (and non existing) indices of a given table up to the last index number defined for this table.

Procedure DeleteSegment Handle hTable Integer iIndex Integer iSegment

Integer iNumSegments

Integer iCurSegment

Integer iSegmentCase

Integer iSegmentDirection

Integer iSegmentColumn

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iSegment = iNumSegments) ;

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To (iNumSegments - 1)

Else If (iSegment > 0 And iSegment < iNumSegments) Begin

For iCurSegment From iSegment To (iNumSegments - 1)

//*** Move index segment attributes

Get_attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex ;

(iCurSegment + 1) To iSegmentCase

Get_attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex ;

(iCurSegment + 1) To iSegmentDirection

Get_attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex ;

(iCurSegment + 1) To iSegmentColumn

Set_attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex ;

iCurSegment To iSegmentCase

Set_attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex ;

iCurSegment To iSegmentDirection

Set_attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex ;

iCurSegment To iSegmentColumn

Loop

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To (iNumSegments - 1)

End

End_Procedure // DeleteSegment

The sample procedure above deletes an index segment from a given index for a given table. Note that the handle you need to pass must be a structure handle.

Struct IndexSegment

Handle hTable

Integer iIndex

Integer iSegment

Integer iColumn

Integer iCase

Integer iDirection

End_Struct // IndexSegment

Procedure InsertSegment IndexSegment sSegment

Handle hTable

Integer iIndex

Integer iSegment

Integer iNumSegments

Integer iCurSegment

Integer iSegmentCase

Integer iSegmentDirection

Integer iSegmentColumn

//*** Move structure members to locals for shorter code

Move sSegment.hTable To hTable

Move sSegment.iIndex To iIndex

Move sSegment.iSegment To iSegment

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iSegment > iNumSegments) Begin

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To (iNumSegments + 1)

Move (iNumSegments + 1) To iCurSegment

End

Else If (iSegment > 0 And iSegment <= iNumSegments) Begin

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To (iNumSegments + 1)

Move iNumSegments To iCurSegment

While (iCurSegment > sSegment.iSegment)

//*** Move index segment attributes

Get_attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex ;

(iCurSegment - 1) To iSegmentCase

Get_attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex ;

(iCurSegment - 1) To iSegmentDirection

Get_attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex ;

(iCurSegment - 1) To iSegmentColumn

Set_attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex ;

iCurSegment To iSegmentCase

Set_attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex ;

iCurSegment To iSegmentDirection

Set_attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex ;

iCurSegment To iSegmentColumn

Decrement iCurSegment

End

//*** Now set new segment attributes

Set_attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iCurSegment To sSegment.iCase

Set_attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iCurSegment To sSegment.iDirection

Set_attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iCurSegment To sSegment.iColumn

End

End_Procedure // InsertSegment

The sample procedure above inserts an index segment into a given index for a given table. Note that the handle you need to pass must be a structure handle.


DF_INDEX_ON_BACKEND

Indicates if the index is defined on the back end or not.

Level

Index

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, permanent

Access

Read only

Values

True, False

Remarks

This attribute indicates whether the index is defined on the back end or not. It is possible to define indices on the “DataFlex side” that do not exist on the back end. Defining such an index is required when accessing a database view. Visual DataFlex requires at least one unique index for every table it accesses. Since indices cannot be defined on views, they must be defined on the DataFlex side.

DataFlex side indices are defined in the intermediate file.

Procedure ShowBackendIndices Handle hTable

Integer iLastIndex

Integer iIndex

String sIndex

String sName

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

Integer iCase

Integer iDirection

Boolean bOnBackEnd

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_NAME Of hTable iIndex To sName

Get_Attribute DF_INDEX_ON_BACKEND Of hTable iIndex To bOnBackend

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index " sName " (" sIndex ")" (If(bOnBackend, "", " on DataFlex side"))

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowBackendIndices

The sample procedure above shows all indices defined on the given table if the index is defined on the DataFlex side this is displayed.


DF_INDEX_SEGMENT_DIRECTION

See Also: Get_Attribute, Set_Attribute

The sort direction of the index segment.

Level

Index segment

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_ASCENDING, DF_DESCENDING

Remarks

If DF_INDEX_SEGMENT_DIRECTION is set to DF_DESCENDING, the index segment will rank from high to low rather than the default low to high. Individual segments (columns) of an index can be designated as descending or ascending. Index segments designated descending can be very useful, but can impose certain requirements on programming. For example, when a find gt (greater than) function is executed on an index containing descending segments, the gt operates as an lt (less than).

This attribute can only be set inside a Structure_Start ... Structure_End operation. The value of this attribute may be stored in the intermediate file under the keyword Index_Segment_Direction.

Procedure ShowIndices Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

String sIndex

Integer iCase

Integer iDirection

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index number: " iIndex " (" sIndex ")"

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowIndices

The sample procedure above shows all segments of all indices of a table. If a segment is “uppercased” and/or descending, this is added to the segment description.

Procedure FillIndexForFindFirst Handle hTable Integer iIndex Integer iFindDirection

Integer iNumSegments

Integer iSegment

Integer iColumn

Integer iExtreme

Integer iSegmentDirection

If (iFindDirection = EQ) ;

Procedure_Return

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iSegmentDirection

If (iSegmentDirection = DF_ASCENDING) Begin

If (iFindDirection = GT Or iFindDirection = GE) ;

Move DF_LOW To iExtreme

Else ;

Move DF_HIGH To iExtreme

End

Else Begin

If (iFindDirection = GT Or iFindDirection = GE) ;

Move DF_HIGH To iExtreme

Else ;

Move DF_LOW To iExtreme

End

Fill_Field hTable iColumn With iExtreme

Loop

End

End_Procedure // FillIndexForFindFirst

The sample procedure above fills the segments of a given index for an upcoming find operation. It looks at the segment direction and the intended find operation to determine if it should place the maximum or minimum value in the segment column.

Procedure CreateTable

Handle hTable

Integer iColumn

Integer iIndex

Handle hoWorkspace

String sPath

String sOrgDirectory

//*** Make sure table comes in first directory of datapath by making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create physical table contacts

Move 0 To hTable

Structure_Start hTable "DATAFLEX"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_MAX_RECORDS Of hTable To 150000

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Customer_Number"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 6

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ContactDate"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "Comment"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_TEXT

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To (8 * 1024)

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 2

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Structure_End hTable

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "Contact"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Contact sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Contact"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Contact.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateTable

In this sample a new table called Contact is created. It has the columns: Customer_Number of type Numeric(6), ContactDate of type Date and Comment of type Text(8192) with an index on Customer_Number and ContactDate (descending). The table will be created in the first directory of the data path of the current workspace; an fd file will be created in the first directory of the DDSrc path of the current workspace.


DF_INDEX_SEGMENT_CASE

See Also: Get_Attribute, Set_Attribute

The case sensitivity of the index segment.

Level

Index segment

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_CASE_USED, DF_CASE_IGNORED

Remarks

DF_CASE_IGNORED makes an index segment case insensitive. DF_CASE_USED makes an index segment case sensitive. Case insensitive segments are of special value where material such as names may contain variations in capitalization. In indexes containing case insensitive segments, capitalization in the column used for that segment does not affect the sequencing of records.

This attribute can only be set inside a Structure_Start ... Structure_End operation. The value of this attribute may be stored in the intermediate file under the keyword Index_Segment_Case.

Procedure ShowIndices Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

String sIndex

Integer iCase

Integer iDirection

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index number: " iIndex " (" sIndex ")"

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowIndices

The sample procedure above shows all segments of all indices of a table. If a segment is “uppercased” and/or descending, this is added to the segment description.


DF_INDEX_SEGMENT_FIELD

See Also: Get_Attribute, Set_Attribute

The number of the column used for the index segment.

Level

Index segment

Supported by

All Connectivity Kits

Type

Numeric, permanent

Access

Read / Write

Values

1 ~ maximum number of columns allowed by the database

Remarks

Each index segment uses one column. Use this attribute to set or retrieve the column number of the index segment. The column the segment is using must exist at the time the attribute is set.

Procedure ShowIndices Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

String sIndex

Integer iCase

Integer iDirection

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index number: " iIndex " (" sIndex ")"

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowIndices

The sample procedure above shows all segments of all indices of a table. If a segment is “uppercased” and/or descending, this is added to the segment description.

Procedure CreateClockTable

Handle hTable

Handle hoWorkspace

String sPath

String sOrgDirectory

Integer iColumn

Integer iIndex

//*** Make sure int file comes in first directory of datapath by

//*** making that directory current

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

Get_Current_Directory To sOrgDirectory

Set_Directory sPath

//*** Create a SQL Server table to store clock in/out times

//*** of employees

Move 0 To hTable

Structure_Start hTable "MSSQLDRV"

Set_Attribute DF_FILE_PHYSICAL_NAME Of hTable To "Clock.int"

Set_Attribute DF_FILE_RECNUM_TABLE Of hTable To False

Set_Attribute DF_FILE_LOGIN Of hTable To ;

"SERVER=(local);Trusted_Connection=yes;DATABASE=Northwind"

Set_Attribute DF_FILE_TABLE_NAME Of hTable To "Clock"

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of hTable To True

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "EmployeeID"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_BCD

Set_Attribute DF_FIELD_LENGTH Of hTable iColumn To 10

Set_Attribute DF_FIELD_NATIVE_TYPE Of hTable iColumn To SQL_INTEGER

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockInTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iColumn

Create_Field hTable At iColumn

Set_Attribute DF_FIELD_NAME Of hTable iColumn To "ClockOutTime"

Set_Attribute DF_FIELD_TYPE Of hTable iColumn To DF_DATE

Move 0 To iIndex

Create_Index hTable At iIndex

Set_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To 3

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 1 To 1

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 2 To 2

Set_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex 2 To DF_DESCENDING

Set_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex 3 To 3

Set_Attribute DF_FILE_PRIMARY_INDEX Of hTable To iIndex

Set_Attribute DF_INDEX_NAME Of hTable iIndex To "ClockPK"

Structure_End hTable

//*** Reset current working directory to original value

Set_Directory sOrgDirectory

//*** Add to filelist and generate fd

Move 0 To hTable

Get_Attribute DF_FILE_NEXT_EMPTY Of hTable To hTable

If (hTable > 0) Begin

Set_Attribute DF_FILE_ROOT_NAME Of hTable To "MSSQLDRV:Clock"

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To "Clock sample table"

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To "Clock"

Open hTable

Get psDDSRCPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - "Clock.fd") To sPath

Output_Aux_File DF_AUX_FILE_FD For hTable To sPath

Close hTable

End

End_Procedure // CreateClockTable

The procedure above creates a new table in the SQL Server Northwind database. It is used to store clock in and clock out information of employees. One index called ClockPK is created on this table. The index has 3 segments.


DF_INDEX_TYPE

See Also: Get_Attribute, Set_Attribute

The type of the index.

Level

Index

Supported by

All Connectivity Kits

Type

Enumeration list, permanent

Access

Read / Write

Values

DF_INDEX_TYPE_ONLINE, DF_INDEX_TYPE_BATCH

Remarks

Online indices are updated whenever a record is added, deleted, or has an indexed column changed. Batch indices are updated only when the index is rebuild. The idea of having batch indices is that, since they are not updated upon a save or delete, the save and delete are faster. The index update speed is not such a big issue anymore so there is not much need for batch indices anymore.

This attribute is part of the basic set of attributes that must be supported by all Connectivity Kits. However, it does not make any sense in some back ends. The Pervasive.SQL Connectivity Kit and the SQL Based Connectivity Kits will return DF_INDEX_TYPE_ONLINE for every table accessed. Trying to set the attribute will be ignored.

This attribute can only be set inside a Structure_Start ... Structure_End operation.

Procedure SortBatchIndexes

Handle hTable

Integer iLastIndex

Integer iIndex

Integer iNumSegments

Integer iIndexType

String sTable

String sSort

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_ROOT_NAME Of hTable To sTable

If (Uppercase(sTable) <> "FLEXERRS") Begin

Move "" To sSort

Open hTable Mode DF_EXCLUSIVE

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_TYPE Of hTable iIndex To iIndexType

If (iIndexType = DF_INDEX_TYPE_BATCH) ;

Move (sSort * String(iIndex)) To sSort

End

Loop

If (sSort <> "") ;

Sort hTable sSort

Close hTable

End

End

Until (hTable = 0)

End_Procedure // SortBatchIndexes

The sample procedure above opens all tables in the filelist and re-indexes all batch indexes for every table.


DF_INDEX_UNIQUE

Indicates if the index is unique.

Level

Index

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

In the Embedded Database, all indices are (must be) unique. There can be no two records with identical values for all segments in an index. SQL databases treat indices completely different. Indices are not required like they are in the Embedded Database, they are used to tune performance. In SQL databases, indices are also not required to be unique. It is possible to define a non-unique index, two records can exist that have identical values for all segments in an index.

The DataFlex framework is designed with unique indices in mind. It does not gracefully handle non unique indices. The main concept of the DataFlex framework and the Embedded Database is a record oriented approach to data in tables. SQL, on the other hand, uses a set oriented approach. Non unique indices fit very well in a set oriented concept. In a record oriented concept, however, they do not fit well at all. In general, you will see non unique indices working ok when used to traverse a complete set. When the index is used to jump around a table, some side effects may occur.

If you control the indices, we recommend not using non-unique indices.

This attribute can only be set inside a Structure_Start ... Structure_End operation. This attribute may be stored in the intermediate file under the keyword Index_Unique.

Procedure ShowUniqueIndices Handle hTable

Integer iLastIndex

Integer iIndex

String sIndex

String sNAME

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

Integer iCase

Integer iDirection

Boolean bUnique

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_NAME Of hTable iIndex To sName

Get_Attribute DF_INDEX_UNIQUE Of hTable iIndex To bUnique

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index " sName " (" sIndex ")" (If(bUnique, "", " NOT UNIQUE"))

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowUniqueIndices

Procedure ShowAllIndices

Handle hTable

String sTable

String sDriver

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

If (sDriver = "MSSQLDRV" Or sDriver = "DB2_DRV" Or sDriver = "ODBC_DRV") Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Indexes for " sTable

Send ShowUniqueIndices hTable

End

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowIndexNames

The sample procedure above shows all indices of all tables in the filelist that are accessed through an SQL Based Connectivity Kit. If the index is not unique, it will show this.


DF_LOCK_DELAY

See Also: Get_Attribute, Set_Attribute, DF_LOCK_TIMEOUT

The delay time, in milliseconds, between lock attempts.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

milliseconds

Remarks

DF_LOCK_DELAY determines the number of milliseconds the Embedded Database waits between two lock attempts. Not all Connectivity Kits will respect this attribute. The SQL Based Connectivity Kits use whatever the back end has to setup lock time outs and delays.

The Embedded Database and the Pervasive.SQL Connectivity Kit respect this setting. DF_LOCK_DELAY does not influence the total time until a timeout occurs but it does influence what happens during that time.

On slower networks, repeated ungranted lock attempts with little or no delay can contribute to network contention. Adjusting the DF_LOCK_DELAY value to a higher setting will increase the time between lock attempts and relieve some network contention.

The default lock timeout of the Embedded Database is 16 minutes and 16 seconds. The total time is determined by two settings. The DF_LOCK_TIMEOUT attribute and the Transaction_Retry count.

The DF_LOCK_TIMEOUT setting sets the time a lock will wait before generating the DFERR_LOCK_TIMEOUT (4106) error. This setting is in milliseconds rounded up to the nearest full second added to the minimal value of 1 second. So, setting it to 1 will result in a timeout of 2 seconds, setting it to 1500 will result in a timeout of 3 seconds, and so forth. The default value is 60000 (61 seconds).

The Transaction_Retry count is the number of times the transaction will be retried after getting the lock timeout error. It can be manipulated by using Get_Transaction_Retry and Set_Transaction_Retry. Every time a retry occurs, the object that initiated the transaction fires a Verify_Retry (function returns integer) event. This event can stop the retry mechanism by returning a non-zero value.

The default settings are:

DF_LOCK_DELAY = 0

DF_LOCK_TIMEOUT = 60000

Transaction_Retry = 15

You could change these to:

DF_LOCK_DELAY = 100

DF_LOCK_TIMEOUT = 3000

Transaction_Retry = 14

These new defaults would generate a lock timeout error to the user after 1 minute.

Procedure ShowLockAttributes

Integer iLockDelay

Integer iLockTimeout

Integer iLockTimeoutSeconds

Integer iTransactionRetry

Integer iTotal

Integer iHour

Integer iMin

Integer iSec

String sTotal

Get_Attribute DF_LOCK_DELAY To iLockDelay

Get_Attribute DF_LOCK_TIMEOUT To iLockTimeout

Get_Transaction_Retry To iTransactionRetry

Move (((iLockTimeOut + 999) / 1000) + 1) To iLockTimeoutSeconds

Move ((iLockTimeOutSeconds * iTransactionRetry) + iLockTimeOutSeconds) To iTotal

If (iTotal >= 3600) Begin

Move (iTotal / 3600) To iHour

Move (Mod(iTotal, 3600)) To iTotal

End

If (iTotal >= 60) Begin

Move (iTotal / 60) To iMin

Move (Mod(iTotal, 60)) To iTotal

End

Move iTotal To iSec

Move (Right("00" + String(iHour), 2) + ":" + ;

Right("00" + String(iMin), 2) + ":" + ;

Right("00" + String(iSec), 2)) To sTotal

Showln "Current lock settings:"

Showln " Lock delay: " iLockDelay " milliseconds."

Showln " Lock timeout: "iLockTimeoutSeconds " seconds."

Showln " Transaction retry: " iTransactionRetry " times."

Showln " Total time before timeout error occurs: " sTotal

End_Procedure // ShowLockAttributes

The sample procedure above shows the current lock attribute settings and the total time before a lock timeout error occurs.

Procedure SetLockAttributes

Set_Attribute DF_LOCK_DELAY To 100

Set_Attribute DF_LOCK_TIMEOUT To 3000

Set_Transaction_Retry To 14

End_Procedure // SetLockAttributes

The sample procedure above sets the lock attributes to such values that the time before a lock timeout error occurs is one minute.


DF_LOCK_TIMEOUT

See Also: Get_Attribute, Set_Attribute, DF_LOCK_DELAY

The time, in milliseconds, after which an ungranted lock will be considered an error.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

Milliseconds rounded up to the nearest second

Remarks

When a lock request fails, additional lock attempts will be executed until the lock is either granted or DF_LOCK_TIMEOUT time has passed. If a network is slow to grant locks (thus generating premature lock-time out errors), adjust the value of the DF_LOCK_TIMEOUT attribute higher.

The default lock timeout of the Embedded Database is 16 minutes and 16 seconds. The total time is determined by two settings. The DF_LOCK_TIMEOUT attribute and the Transaction_Retry count.

The DF_LOCK_TIMEOUT setting sets the time a lock will wait before generating the DFERR_LOCK_TIMEOUT (4106) error. This setting is in milliseconds rounded up to the nearest full second added to the minimal value of 1 second. So, setting it to 1 will result in a timeout of 2 seconds, setting it to 1500 will result in a timeout of 3 seconds, and so forth. The default value is 60000 (61 seconds).

The Transaction_Retry count is the number of times the transaction will be retried after getting the lock timeout error. It can be manipulated by using Get_Transaction_Retry and Set_Transaction_Retry. Every time a retry occurs, the object that initiated the transaction fires a Verify_Retry (function returns integer) event. This event can stop the retry mechanism by returning a non-zero value.

The default settings are:

DF_LOCK_DELAY = 0

DF_LOCK_TIMEOUT = 60000

Transaction_Retry = 15

You could change these to:

DF_LOCK_DELAY = 100

DF_LOCK_TIMEOUT = 3000

Transaction_Retry = 14

These new defaults would generate a lock timeout error to the user after 1 minute.

Procedure ShowLockAttributes

Integer iLockDelay

Integer iLockTimeout

Integer iLockTimeoutSeconds

Integer iTransactionRetry

Integer iTotal

Integer iHour

Integer iMin

Integer iSec

String sTotal

Get_Attribute DF_LOCK_DELAY To iLockDelay

Get_Attribute DF_LOCK_TIMEOUT To iLockTimeout

Get_Transaction_Retry To iTransactionRetry

Move (((iLockTimeOut + 999) / 1000) + 1) To iLockTimeoutSeconds

Move ((iLockTimeOutSeconds * iTransactionRetry) + iLockTimeOutSeconds) To iTotal

If (iTotal >= 3600) Begin

Move (iTotal / 3600) To iHour

Move (Mod(iTotal, 3600)) To iTotal

End

If (iTotal >= 60) Begin

Move (iTotal / 60) To iMin

Move (Mod(iTotal, 60)) To iTotal

End

Move iTotal To iSec

Move (Right("00" + String(iHour), 2) + ":" + ;

Right("00" + String(iMin), 2) + ":" + ;

Right("00" + String(iSec), 2)) To sTotal

Showln "Current lock settings:"

Showln " Lock delay: " iLockDelay " milliseconds."

Showln " Lock timeout: "iLockTimeoutSeconds " seconds."

Showln " Transaction retry: " iTransactionRetry " times."

Showln " Total time before timeout error occurs: " sTotal

End_Procedure // ShowLockAttributes

The sample procedure above shows the current lock attribute settings and the total time before a lock timeout error occurs.

Procedure SetLockAttributes

Set_Attribute DF_LOCK_DELAY To 100

Set_Attribute DF_LOCK_TIMEOUT To 3000

Set_Transaction_Retry To 14

End_Procedure // SetLockAttributes

The sample procedure above sets the lock attributes to such values that the time before a lock timeout error occurs is one minute.


DF_NUMBER_DRIVERS

See Also: Get_Attribute, Set_Attribute

The number of currently loaded database drivers/Connectivity Kits.

Level

Global

Type

Integer, temporary

Access

Read Only

Values

Positive Integers

Remarks

DF_NUMBER_DRIVERS returns the number of database drivers/Connectivity Kits that are currently loaded. It can be used to enumerate the currently loaded drivers or to determine the index of a specific loaded driver. The index of a specific loaded driver is need for driver level attributes.

Procedure ShowDriverList

Integer iNumDrivers

String sDriver

Integer iDriver

Get_Attribute DF_NUMBER_DRIVERS To iNumDrivers

For iDriver From 1 To iNumDrivers

Get_Attribute DF_DRIVER_NAME Of iDriver To sDriver

Showln "Driver: " sDriver

Loop

Showln

Showln "Done..."

End_Procedure // ShowDriverList

This example enumerates all loaded drivers and lists them.

Function DriverIndex String sDriver Returns Integer

String sCurrentDriver

Integer iNumberOfDrivers

Integer iDriver

Integer iCount

Move 0 To iDriver

Get_attribute DF_NUMBER_DRIVERS To iNumberOfDrivers

For iCount From 1 To iNumberOfDrivers

Get_attribute DF_DRIVER_NAME Of iCount To sCurrentDriver

If (Uppercase(sCurrentDriver)) Eq (Uppercase(sDriver)) ;

Move iCount To iDriver

Loop

Function_Return iDriver

End_Function // DriverIndex

The sample function above returns the index for a specific loaded driver.


DF_NUMBER_FILES_SUPPORTED

See Also: Get_Attribute, Set_Attribute, DF_FILE_REVISION, DF_FILELIST_NAME

The maximum number of slots that will fit in the filelist (either 255 or 4095).

Level

Global

Type

Integer, temporary

Access

Read-only

Values

255, 4095

Remarks

As of Visual DataFlex 7 and DataFlex 3.2, each filelist supports 4095 files, where prior revisions supported only 255.

Procedure NewEntry Handle hTable String sRoot String sDisplay String sTable

Set_Attribute DF_FILE_ROOT_NAME Of hTable To sRoot

Set_Attribute DF_FILE_DISPLAY_NAME Of hTable To sDisplay

Set_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

End_Procedure // NewEntry

Procedure CreateNewFilelist String sNewList

Handle hoWorkspace

String sPath

Integer iMaxSlots

//*** Make sure new filelist comes in first directory of datapath

Get phoWorkspace Of ghoApplication To hoWorkspace

Get psDataPath Of hoWorkspace To sPath

Get PathAtIndex Of hoWorkspace sPath 1 To sPath

If (Right(sPath, 1) <> Sysconf(Sysconf_Dir_Separator)) ;

Move (sPath - Sysconf(Sysconf_Dir_Separator)) To sPath

Move (sPath - sNewList) To sPath

//*** Create the disk file

Direct_Output sPath

Write "filelist.cfg"

Close_output

//*** Use the disk file as filelist

Set_Attribute DF_FILELIST_NAME To sPath

//*** Create all the slots

Get_Attribute DF_NUMBER_FILES_SUPPORTED To iMaxSlots

Send NewEntry iMaxSlots "" "" ""

End_Procedure // CreateNewFilelist

The sample procedure above uses the DF_NUMBER_FILES_SUPPORTED attribute and the filelist attributes to create a new empty filelist.


DF_OPEN_FILE_COUNT

See Also: Get_Attribute, Set_Attribute

Returns the number of currently open tables.

Level

Global

Type

Integer, temporary

Access

Read Only

Values

Positive integer

Remarks

DF_OPEN_FILE_COUNT returns the number of tables that are currently open. This attribute will not return the number of tables open in another application, only the current one. This count does not include any pending structure handles (Structure_Start that has not been ended with a Structure_End or Structure_Abort).

Function NumberOfOpenTables Returns Integer

Integer iOpen

Get_Attribute DF_OPEN_FILE_COUNT To iOpen

Function_Return iOpen

End_Function // NumberOfOpenTables

The sample function above returns the number of tables currently open.


DF_OPEN_PATH

See Also: Get_Attribute, Set_Attribute

The directory paths to use when searching for a disk file.

Level

Global

Type

String, temporary

Access

Read / Write

Values

Valid directory paths

Remarks

DF_OPEN_PATH instructs DataFlex to use the provided directory paths when searching for a file. If DF_OPEN_PATH is NULL, file searches will be limited to the current directory. Note that file searches are not performed for file specifications that contain a path.

In the Visual DataFlex environment, this attribute is rarely set. The workspace object in an application sets the DF_FILE_OPEN_PATH attribute when the application starts.

Procedure ShowOpenPath

String sOpenPath

Get_Attribute DF_OPEN_PATH To sOpenPath

Showln "Open path is: " sOpenPath

Showln "Directory list in search order:"

While (Pos(";", sOpenPath) > 0)

Showln " " (Left(sOpenPath, Pos(";", sOpenPath) - 1))

Move (Right(sOpenPath, Length(sOpenPath) - Pos(";", sOpenPath))) To sOpenPath

End

Showln " " sOpenPath

End_Procedure // ShowOpenPath

The sample procedure above shows the open path currently in use as a whole and split up per search directory.


DF_REPORT_UNSUPPORTED_ATTRIBUTES

See Also: Get_Attribute, Set_Attribute, DF_STRICT_ATTRIBUTES

Controls how unsupported attributes are handled by database drivers/Connectivity Kits.

Level

Global

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

If the value of DF_REPORT_UNSUPPORTED_ATTRIBUTES is False, database drivers/Connectivity Kits will not generate an error when an attribute that is unsupported by that driver is set or retrieved. When getting an unsupported attribute its value will be returned as 0 for numeric attributes and an empty string for string attributes.

If the value of DF_REPORT_UNSUPPORTED_ATTRIBUTES is True, the DFERR_UNSUPPORTED_FUNCTION error will be generated when a driver/Connectivity Kits is requested to get or set an unsupported attribute.

DF_REPORT_UNSUPPORTED_ATTRIBUTES is used in those cases where one or more attributes are used that are not supported by all the used Connectivity Kits and the value of the attribute is of no interest for the logic. In these cases it is set to false, the logic is performed and then the attribute is set back to true. Alternatively, one could test for the Connectivity Kit and decide not to get the attribute if it is not supported.

Procedure ShowIndices Handle hTable

Integer iLastIndex

Integer iIndex

String sIndex

String sNAME

Integer iNumSegments

Integer iSegment

Integer iColumn

String sColumn

Integer iCase

Integer iDirection

Get_Attribute DF_FILE_LAST_INDEX_NUMBER Of hTable To iLastIndex

For iIndex From 1 To iLastIndex

Get_Attribute DF_INDEX_NUMBER_SEGMENTS Of hTable iIndex To iNumSegments

If (iNumSegments > 0) Begin

Get_Attribute DF_INDEX_NAME Of hTable iIndex To sName

Move "" To sIndex

For iSegment From 1 To iNumSegments

Get_Attribute DF_INDEX_SEGMENT_FIELD Of hTable iIndex iSegment To iColumn

Get_Attribute DF_FIELD_NAME Of hTable iColumn To sColumn

Get_Attribute DF_INDEX_SEGMENT_CASE Of hTable iIndex iSegment To iCase

If (iCase = DF_CASE_IGNORED) ;

Move (sColumn * "uppercased") To sColumn

Get_Attribute DF_INDEX_SEGMENT_DIRECTION Of hTable iIndex iSegment To iDirection

If (iDirection = DF_DESCENDING) ;

Move (sColumn * "descending") To sColumn

If (iSegment > 1) ;

Move (sIndex + ",") To sIndex

Move (sIndex * sColumn) To sIndex

Loop

Showln " Index " sName " (" sIndex ")"

End

Loop

If (iLastIndex = 0) ;

Showln " NO index defined."

End_Procedure // ShowIndices

Procedure ShowAllSQLIndices

Handle hTable

String sTable

String sDriver

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

If (sDriver = "MSSQLDRV" Or sDriver = "DB2_DRV" Or sDriver = "ODBC_DRV") Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Indexes for " sTable

Send ShowIndices hTable

End

Close hTable

End

Until (hTable = 0)

End_Procedure // ShowAllSQLIndices

Procedure ShowAllIndices

Handle hTable

String sTable

String sDriver

Boolean bUnSupported

Get_Attribute DF_REPORT_UNSUPPORTED_ATTRIBUTES To bUnSupported

Set_Attribute DF_REPORT_UNSUPPORTED_ATTRIBUTES To False

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED Of hTable To hTable

If (hTable > 0) Begin

Open hTable

Get_Attribute DF_FILE_DRIVER Of hTable To sDriver

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln "Indexes for " sTable

Send ShowIndices hTable

Close hTable

End

Until (hTable = 0)

Set_Attribute DF_REPORT_UNSUPPORTED_ATTRIBUTES To bUnSupported

End_Procedure // ShowAllIndices

The sample procedure ShowIndices above uses the DF_INDEX_NAME attribute, this attribute is only supported by SQL Based Connectivity Kits. The sample procedure ShowAllSQLIndices above only calls the ShowIndices procedure if the table is accessed through a SQL Based Connectivity Kit. The sample procedure ShowAllIndices above turns off reporting unsupported attributes and then calls the ShowIndices procedure regardless of the Connectivity Kit.


DF_REREAD_REQUIRED

See Also: Get_Attribute, Set_Attribute

Indicates whether an error should be generated for multi user unsafe logic.

Level

Global

Type

Boolean, permanent

Access

Read / Write

Values

True, False

Remarks

To make logic multi use safe, a reread of data from disk is required before data in an active record buffer is to be changed. This ensures that no other user or process has changed the data since it was last retrieved from disk. If the value of this attribute is true and a reread is not performed, error DFERR_EDIT_WITHOUT_REREAD will be triggered.

This attribute should be set to true, the error should be generated. When existing code generates the DFERR_EDIT_WITHOUT_REREAD, it is possible to set the attribute to false. Make sure you change the code to follow the rules. Then switch the attribute back on.


DF_RUNTIME_PROGRESS_FREQUENCY

See Also: Call_Driver, Copy_DB, Copy_Records, Get_Attribute, Set_Attribute, Sort, Structure_End, Structure_Start, Execute structure_start

Determines how often the runtime sends a callback message of type DF_MESSAGE_PROGRESS_VALUE.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

1 - 4,000,000,000

Remarks

The callback message is used by several database related functions to inform the calling process of the progress made for time consuming operations. It is up to the programmer to deal with this information. It can be ignored completely or used to inform the user about progress.

The higher the value of this attribute, the less often DF_MESSAGE_PROGRESS_VALUE will be sent. You should try to set this value to provide adequate feedback, without interrupting the processing of the program.

For example, if you are restructuring a file with 500,000 records, setting DF_RUNTIME_PROGRESS_FREQUENCY at 100 (the default) would probably be intrusive — the program would send the DF_MESSAGE_PROGRESS_VALUE message 5,000 times before completing. A value of 10,000 would most likely provide a better balance between feedback and program performance in this case.

Class cSimpleProgress Is A cObject

Function CallBack String sMessage Integer iType Returns Integer

String sType

Case Begin

Case (iType = DF_MESSAGE_TEXT)

Move "(Text)" To sType

Case Break

Case (iType = DF_MESSAGE_HEADING_1)

Move "(Message Heading 1)" To sType

Case Break

Case (iType = DF_MESSAGE_HEADING_2)

Move "(Message Heading 2)" To sType

Case Break

Case (iType = DF_MESSAGE_HEADING_3)

Move "(Message Heading 3)" To sType

Case Break

Case (iType = DF_MESSAGE_HEADING_4)

Move "(Message Heading 4)" To sType

Case Break

Case (iType = DF_MESSAGE_HEADING_5)

Move "(Message Heading 5)" To sType

Case Break

Case (iType = DF_MESSAGE_WARNING)

Move "(Warning)" To sType

Case Break

Case (iType = DF_MESSAGE_PROGRESS_TITLE)

Move "(Progress Title)" To sType

Case Break

Case (iType = DF_MESSAGE_PROGRESS_VALUE)

Move "(Progress value)" To sType

Case Break

Case End

Showln sMessage " -- " sType

End_Function // CallBack

End_Class // cSimpleProgress

The sample class above can be used to give extremely simple feedback on one of the processes that support callback logic. It uses showln to report progress.

Procedure SortCustomer Integer iFrequency

Handle hoProgress

Showln "Sorting table Customer, progress frequency is " iFrequency

Open Customer Mode DF_EXCLUSIVE

Set_Attribute DF_RUNTIME_PROGRESS_FREQUENCY To iFrequency

Get Create U_cSimpleProgress To hoProgress

Sort Customer.File_number "" ;

(DF_SORT_OPTION_NO_DATA_CHECK ior DF_SORT_OPTION_DUP_DATA_FILE) hoProgress

Send Destroy Of hoProgress

Close Customer

End_Procedure // SortCustomer

The sample procedure above uses the simple progress reporting class defined above to report progress on sorting the customer table. The runtime progress frequency is passed as argument to the procedure.


DF_SQL_RELATION_RELATED_COLUMN

The name of the parent column the relation points to.

Level

Table relation

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read Only

Values

Column name

Remarks

When a table is opened, the foreign key information is retrieved from the back end. This information can be used to examine the relationships as they are defined on the back end. The SQL relation attributes can be accessed via the Get_Attribute command in the same way as field attributes.

Procedure ShowSQLRelations Handle hTable

Integer iNumRelations

Integer iFKColumn

String sFkTable

String sFKSchema

String sFKColumn

String sPKSchema

String sPKTable

String sPKColumn

Integer iCurRel

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_NUMBER_SQL_RELATIONS Of hTable To iNumRelations

If (iNumRelations > 0) Begin

Get_Attribute DF_FILE_TABLE_NAME Of hTable To sFKTable

Get_Attribute DF_FILE_OWNER Of hTable To sFKSchema

For iCurRel From 1 To iNumRelations

Get_Attribute DF_SQL_RELATION_COLUMN Of hTable iCurRel To iFKColumn

Get_Attribute DF_SQL_RELATION_RELATED_SCHEMA Of hTable iCurRel To sPKSchema

Get_Attribute DF_SQL_RELATION_RELATED_TABLE Of hTable iCurRel To sPKTable

Get_Attribute DF_SQL_RELATION_RELATED_COLUMN Of hTable iCurRel To sPKColumn

Get_Attribute DF_FIELD_NAME Of hTable iFKColumn To sFKColumn

Showln sFKSchema "." sFKTable "." sFKColumn " relates to " sPKSchema "." sPKTable "." sPKColumn

Loop

End

End

Until (hTable = 0)

End_Procedure // ShowSQLRelations

The sample procedure above shows all columns that are part of a foreign key of the given table.


DF_SQL_RELATION_RELATED_SCHEMA

The name of the parent schema the relation points to.

Level

Table relation

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read Only

Values

Schema name

Remarks

When a table is opened, the foreign key information is retrieved from the back end. This information can be used to examine the relationships as they are defined on the back end. The SQL relation attributes can be accessed via the Get_Attribute command in the same way as field attributes.

Procedure ShowSQLRelations Handle hTable

Integer iNumRelations

Integer iFKColumn

String sFkTable

String sFKSchema

String sFKColumn

String sPKSchema

String sPKTable

String sPKColumn

Integer iCurRel

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_NUMBER_SQL_RELATIONS Of hTable To iNumRelations

If (iNumRelations > 0) Begin

Get_Attribute DF_FILE_TABLE_NAME Of hTable To sFKTable

Get_Attribute DF_FILE_OWNER Of hTable To sFKSchema

For iCurRel From 1 To iNumRelations

Get_Attribute DF_SQL_RELATION_COLUMN Of hTable iCurRel To iFKColumn

Get_Attribute DF_SQL_RELATION_RELATED_SCHEMA Of hTable iCurRel To sPKSchema

Get_Attribute DF_SQL_RELATION_RELATED_TABLE Of hTable iCurRel To sPKTable

Get_Attribute DF_SQL_RELATION_RELATED_COLUMN Of hTable iCurRel To sPKColumn

Get_Attribute DF_FIELD_NAME Of hTable iFKColumn To sFKColumn

Showln sFKSchema "." sFKTable "." sFKColumn " relates to " sPKSchema "." sPKTable "." sPKColumn

Loop

End

End

Until (hTable = 0)

End_Procedure // ShowSQLRelations

The sample procedure above shows all columns that are part of a foreign key of the given table.


DF_SQL_RELATION_RELATED_TABLE

The name of the parent table the relation points to.

Level

Table relation

Supported by

The SQL based Connectivity Kits (SQL Server, DB2 and ODBC)

Type

String, permanent

Access

Read Only

Values

Table name

Remarks

When a table is opened, the foreign key information is retrieved from the back end. This information can be used to examine the relationships as they are defined on the back end. The SQL relation attributes can be accessed via the Get_Attribute command in the same way as field attributes.

Procedure ShowSQLRelations Handle hTable

Integer iNumRelations

Integer iFKColumn

String sFkTable

String sFKSchema

String sFKColumn

String sPKSchema

String sPKTable

String sPKColumn

Integer iCurRel

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable <> 0) Begin

Get_Attribute DF_FILE_NUMBER_SQL_RELATIONS Of hTable To iNumRelations

If (iNumRelations > 0) Begin

Get_Attribute DF_FILE_TABLE_NAME Of hTable To sFKTable

Get_Attribute DF_FILE_OWNER Of hTable To sFKSchema

For iCurRel From 1 To iNumRelations

Get_Attribute DF_SQL_RELATION_COLUMN Of hTable iCurRel To iFKColumn

Get_Attribute DF_SQL_RELATION_RELATED_SCHEMA Of hTable iCurRel To sPKSchema

Get_Attribute DF_SQL_RELATION_RELATED_TABLE Of hTable iCurRel To sPKTable

Get_Attribute DF_SQL_RELATION_RELATED_COLUMN Of hTable iCurRel To sPKColumn

Get_Attribute DF_FIELD_NAME Of hTable iFKColumn To sFKColumn

Showln sFKSchema "." sFKTable "." sFKColumn " relates to " sPKSchema "." sPKTable "." sPKColumn

Loop

End

End

Until (hTable = 0)

End_Procedure // ShowSQLRelations

The sample procedure above shows all columns that are part of a foreign key of the given table.


DF_STRICT_ATTRIBUTES

See Also: Get_Attribute, Set_Attribute, DF_REPORT_UNSUPPORTED_ATTRIBUTES

Determines how attribute values will be interpreted.

Level

Global

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

If the value of DF_STRICT_ATTRIBUTES is True, setting an attribute will be interpreted precisely—attempting to set an attribute to an unsupported value will cause an error.

As an example, the DF_FILE_LOCK_TYPE attribute can be set to DF_LOCK_TYPE_NONE, DF_LOCK_TYPE_FILE, or DF_LOCK_TYPE_RECORD. However, since record locking is not available in the Embedded Database driver, setting DF_FILE_LOCK_TYPE to DF_LOCK_TYPE_RECORD will result in the attribute being set to DF_LOCK_TYPE_FILE, if the value of DF_STRICT_ATTRIBUTES is False. If, on the other hand, DF_STRICT_ATTRIBUTES is True, the above example would cause a DFERR_UNSUPPORTED_ATTRIBUTE_VALUE error.

In most cases, setting an attribute to an unsupported value with strict attributes off, will not change the current value of the attribute.


DF_THOUSANDS_SEPARATOR

See Also: Get_Attribute, Set_Attribute, DF_DATE_SEPARATOR, DF_DECIMAL_SEPARATOR

The decimal ASCII value of the character to use to separate every three integer positions of a number.

Level

Global

Type

Numeric, temporary

Access

Read / Write

Values

0 255

Remarks

DF_THOUSANDS_SEPARATOR allows the character used to separate every three digits in large numbers to be set. By default, the DF_THOUSANDS_SEPARATOR will conform to the regional settings on the machine. Windows visual controls also use the regional settings.

The thousands separator is used when using the print command. The print command is only used with legacy style reports that use screen images for output formatting, such as the BasicReport class; most VDF reports do not use this technique (or this command).

Procedure ShowFormats

Integer iDateFormat

String sDateFormat

Integer iDateSep

Integer iDecimalSep

Integer iThousandSep

Get_Attribute DF_DATE_FORMAT To iDateFormat

Get_Attribute DF_DATE_SEPARATOR To iDateSep

Get_Attribute DF_DECIMAL_SEPARATOR To iDecimalSep

Get_Attribute DF_THOUSANDS_SEPARATOR To iThousandSep

If (iDateFormat = DF_DATE_USA) ;

Move "USA" To sDateFormat

Else If (iDateFormat = DF_DATE_EUROPEAN) ;

Move "European" To sDateFormat

Else If (iDateFormat = DF_DATE_MILITARY) ;

Move "Military" To sDateFormat

Else ;

Move "Unknown" To sDateFormat

Send Info_Box ("Formats:\nDate:" * sDateFormat + ;

"\nDate separator:" * Character(iDateSep) + ;

"\nDecimal separator:" * Character(iDecimalSep) + ;

"\nThousand separator:" * Character(iThousandSep))

End_Procedure // ShowFormats

This example obtains the date and number format in use by Visual DataFlex and then pops up a message box that displays a message showing which format is in use.


DF_TRANABORT_ONERROR

See Also: Get_Attribute, Set_Attribute, Begin_Transaction, End_Transaction, Abort_Transaction, Lock, Reread, Unlock

Indicates whether control should jump to the end of an implicit transaction when an error occurs during a transaction.

Level

Global

Type

Boolean, temporary

Access

Read / Write

Values

True, False

Remarks

Visual DataFlex will not abort an implicit transaction if an error occurs. This behavior is consistent with the behavior that existed when explicit transactions were not supported.

When set to true, Visual DataFlex will abort an implicit transaction if an error occurs. The flow of the program, however, will not jump out of the implicit transaction but continue on the next line. This behaviour will usually not be desired. If, for example, an implicit transaction tries to save 3 records and an error occurs while trying to save the second record, the transaction will be rolled back, but the control will not jump to the end of the implicit transaction. In this case, it will still try to save the third record. The rollback has removed the lock so the DFERR_EDIT_WITHOUT_REREAD (4155) error occurs. This can be avoided by setting the DF_TRANABORT_ONERROR attribute to True.

Because of the behavior of implicit transactions when the attribute is set to true, you will want to use the default value.

The DF_TRANABORT_ONERROR attribute only affects implicit transactions. An implicit transaction is a transaction that is started via the Lock or Reread command and ended via the Unlock command. An explicit transaction is started by the Begin_Transaction command and ended by the End_Transaction command.


DF_TRANSACTION_ABORT

See Also: Get_Attribute, Set_Attribute, Begin_Transaction, End_Transaction, Abort_Transaction, Lock, Reread, Unlock

Indicates whether the last transaction was aborted.

Level

Global

Type

Boolean, temporary

Access

Read only

Values

True, False

Remarks

The attribute indicates if the last transaction was aborted.

Visual DataFlex supports two types of transactions: Explicit and Implicit. An implicit transaction is a transaction that is started via the Lock or Reread command and ended via the Unlock command. An explicit transaction is started by the Begin_Transaction command and ended by the End_Transaction command.

Any error condition inside of an explicit transaction forces the transaction to be rolled back, thus setting the DF_TRANSACTION_ABORT attribute to true. An error condition in an implicit transaction only forces the transaction to be rolled back if DF_TRANABORT_ONERROR is set to true. If that is the case the DF_TRANSACTION_ABORT attribute is set to true.

Procedure ShowUncommitted

Handle hTable

Boolean bCommitted

Boolean bAborted

String sTable

Get_Attribute DF_TRANSACTION_ABORT To bAborted

If (bAborted) Begin

Showln "Tables that are uncommitted are:"

Move 0 To hTable

Repeat

Get_Attribute DF_FILE_NEXT_OPENED Of hTable To hTable

If (hTable > 0) Begin

Get_Attribute DF_FILE_COMMITTED Of hTable To bCommitted

If (Not(bCommitted)) Begin

Get_Attribute DF_FILE_LOGICAL_NAME Of hTable To sTable

Showln " " sTable

End

End

Until (hTable = 0)

End

End_Procedure // ShowUncommitted

The sample procedure above check if the last transaction was successful and shows a list of tables that have not been committed.


DF_TRAN_COUNT

See Also: Get_Attribute, Set_Attribute, Begin_Transaction, End_Transaction, Abort_Transaction, Lock, Reread, Unlock

Indicates the number of nested transactions.

Type

Numeric, temporary

Access

Read only

Values

Positive integer

Remarks

In Visual DataFlex it is allowed to nest transactions. If this happens the outer transaction logic will execute and DF_TRAN_COUNT is incremented, the nested transactions will merely increment the DF_TRAN_COUNT attribute when started and decrement it again when they finish. When the outer transaction finishes, the transaction logic will execute and DF_TRAN_COUNT will be decremented. An execution of Abort_Transaction will set DF_TRAN_COUNT to 0 (zero), as will abortion of a transaction by an error condition.

Visual DataFlex supports two types of transactions: Explicit and Implicit. An implicit transaction is a transaction that is started via the Lock or Reread command and ended via the Unlock command. An explicit transaction is started by the Begin_Transaction command and ended by the End_Transaction command.

Procedure DemoTranCount

Integer iTranCount

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Begin_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Begin_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Begin_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Begin_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Begin_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Lock

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Reread

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Lock

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Unlock

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Unlock

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

Unlock

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Transaction

Get_Attribute DF_TRAN_COUNT To iTranCount

Showln "Current transaction count: " iTranCount

End_Procedure // DemoTranCount

The sample procedure above shows the transaction count when nesting transactions. The output of this procedure will show a transaction count incrementing up to 4 then decrementing to 0, incrementing again up to 4 and decrementing again to 0.


Framework Data Types

Framework Data Types are structured data types declared in the Visual DataFlex framework that are not part of the Visual DataFlex Language itself.

Please consult the Language Guide for documentation of the fundamental data types and structured types in the Visual DataFlex language.

The Framework Data Types are:

  • OLE Data Types

  • tagRECT

  • tSoapParameter

  • tSoapParamDef

  • tValueTree


OLE Data Types

See Also: Variable Declaration Commands

OLE Data Types are types that are used when using COM in Visual DataFlex applications.

These types are mapped to fundamental Visual DataFlex data types, the rules of which apply to the OLE data type in question. Follow the link to the mapped fundamental type to learn how to declare variables of this type and work with that type.

Type | Mapped Fundamental Type
LPOLE_RECT | Pointer
OLE_Handle | Handle
OLE_Color | DWord
OLE_FontSize | Integer
OLE_XPos_Pixels | Integer
OLE_YPos_Pixels | Integer
OLE_XSize_Pixels | Integer
OLE_YSize_Pixels | Integer
OLE_XPos_HiMetric | Integer
OLE_YPos_HiMetric | Integer
OLE_XSize_HiMetric | Integer
OLE_YSize_HiMetric | Integer
OLE_XPos_Container | Float
OLE_YPos_Container | Float
OLE_XSize_Container | Float
OLE_YSize_Container | Float
OLE_OptExclusive | Integer
OLE_CancelBool | Integer
OLE_EnableDefaultBool | Integer


tagRECT

See Also: Integer, Declaring Variables, Struct

Purpose

tagRECT is a structured type used for positioning COM objects. It defines the coordinates of the upper-left and lower-right corners of a rectangle.

Type Declaration

Struct tagRECT

Integer left

Integer top

Integer right

Integer bottom

End_Struct

Struct Members

left

Specifies the x-coordinate of the upper-left corner of the rectangle.

top

Specifies the y-coordinate of the upper-left corner of the rectangle.

right

Specifies the x-coordinate of the lower-right corner of the rectangle.

bottom

Specifies the y-coordinate of the lower-right corner of the rectangle.

Declaring variables

To declare tagRECT variables, use the name of the type (tagRect) followed by the variable name.

tagRECT MyTagRect

See struct variables for more details of instantiating struct types.


tSoapParameter

See Also: Declaring Variables, Struct

Purpose

tSoapParameter is a structured type used in web services.

Type Declaration

Struct tSoapParameter

tSoapParamDef SoapParamDef

tValueTree ValueTree

End_Struct

Struct Members

SoapParamDef

A tSoapParamDef variable.

ValueTree

A tValueTree variable.

Declaring variables

To declare tSoapParameter variables, use the name of the type (tSoapParameter) followed by the variable name.

tSoapParameter MySoapParameter

See struct variables for more details of instantiating struct types.


tSoapParamDef

See Also: Declaring Variables, Struct, Integer, String, Handle

Purpose

tSoapParamDef is a structured type used in web services.

Type Declaration

Struct tSoapParamDef

String sName

String sNamespace

Integer eType

Handle hoStruct

Integer iMin

Integer iMax

End_Struct

Struct Members

sName

The parameter SOAP name used by XML.

sNamespace

The parameter SOAP namespace URI used by XML.

eType

Represents the mapping of SOAP data types to DataFlex data types.

Possible values are:

Constant | Meaning
xsString | String
xsNumber | Number
xsDate | Date
xsInteger | Integer
xsBigInt | BigInt
xsReal | Real
xsBoolean | Boolean
xsTime | Time
xsDatetime | DateTime
xsFloat | Float
xsChar | Char
xsShort | Short
xsUShort | UShort
xsUInteger | UInteger
xsUBigInt | UBigInt
xsCurrency | Currency
xsDecimal | Decimal
xsAnyType | XML parameter without the wrapper
xsXmlElement | XML including the wrapper

hoStruct

If eType=xsStruct, this is a pointer to the cSoapMetaStruct object that defines the struct.

iMin

Minimum number of occurences of the parameter. 0 or 1.

iMax

Maximum number of occurences of the parameter. 1-C_Unbounded.

Declaring variables

To declare tSoapParamDef variables, use the name of the type (tSoapParamDef) followed by the variable name.

tSoapParamDef MySoapParamDef

See struct variables for more details of instantiating struct types.


tValueTree

See Also: Integer, Declaring Variables, Struct

Purpose

tValueTree is a structured type used in web services.

Type Declaration

Struct tValueTree

String sValue

tValueTree[] children

End_Struct

Struct Members

sValue

Only has a value if there are no children. If the type of the tSoapParamDef.eType variable that is in the tSoapParameter with the current tValueTree is a struct or array, the children array will have elements, but sValue will be blank.

children

Array of child value trees, each also of type tValueTree. This array will only have elements in it if the type is a struct or an array.

Declaring variables

To declare tValueTree variables, use the name of the type (tValueTree) followed by the variable name.

tValueTree MyValueTree

See struct variables for more details of instantiating struct types.


Functions

This section describes each member of the Visual DataFlex function library. They are listed by category and alphabetically. The library contains functions for performing a variety of programming operations such as string manipulation and mathematical operations.

Function Categories

Array Functions

Dialog and Message Box Functions

File I/O Functions

FlexCOM Helper Functions

Graphics Functions

Locale Formatting Functions

Math Functions

Memory Management Functions

RowId Helper Functions

String Functions

Time and Date Functions

Type Conversion Functions

Web Application Helper Functions

Miscellaneous Functions


Array Functions

See Also: Array Types

Function | Returns
BinarySearchArray | Returns the index of the first element in the array (or indicated element range) equal to a particular value. Very efficient for large arrays.
CopyArray | Returns array representing a range of elements from the existing array.
CountArray | Returns the number of array elements whose value is equal to a test value.
FillArray | Fills an array element range with a specified value.
MaxArray | Returns index of array element with the highest (maximum) value.
MinArray | Returns index of array element with the lowest (minimum) value.
ResizeArray | Adds new elements or removes elements from a dynamic array.
ReverseArray | Returns array with elements in reverse order of original array.
SearchArray | Returns the index of the first element in the array (or indicated element range) equal to a particular value.
ShuffleArray | Returns array with elements in shuffled (random) order of original array.
SizeOfArray | Returns the number of elements in an array or an array dimension.
SortArray | Returns array with sorted elements.


Dialog and Message Box Functions

Function | Returns
Info_Box | Displays an information dialog box.
Message_Box | Displays a generic message dialog box.
Stop_Box | Displays an error dialog box.
YesNo_Box | Displays a dialog box with Yes & No buttons.
YesNoCancel_Box | Displays a dialog box with Yes, No & Cancel buttons.


File I/O Functions

See Also: File I/O Commands

Function | Returns
Seq_New_Channel | Retrieves the next available sequential input/output (I/O) channel.
Seq_Release_Channel | Releases specified sequential input/output (I/O) channel for reuse.


FlexCOM Helper Functions

Function | Returns
IsNullComObject | Returns True if the passed parameter is of type variant Idispatch* and is set to NULL. It will return False if the passed value is a non-NULL IDispatch* value.
IsSameComObject | Compares two variant IDispatch* parameters and returns True if they point to the same COM object.
NullComObject | Returns a NULL value of variant type IDispatch*.


Graphics Functions

Function | Returns
B_From_RGB | Returns a byte value representing the Blue color intensity value of an RGB integer.
G_From_RGB | Returns a byte value representing the Green color intensity value of an RGB integer.
R_From_RGB | Returns a byte value representing the Red color intensity value of an RGB integer.
RGB | Returns a RGB value for GDI functions from byte values representing Red, Green & Blue color intensity.


Locale Formatting Functions

Function | Returns
Default_Currency_Symbol | Returns the Windows locale currency symbol.
FormatCurrency | Formats a number and returns it as a string formatted as a currency value.
FormatNumber | Formats a number and returns it as a string formatted as a number using locale number settings.
FormatValue | Formats a number with a custom formatting mask.
SetCurrencyFormat | Sets the global currency format-string.
SetNumberFormat | Sets the global number format-string.
SysConf | Retrieves environment-specific information to running programs.


Math Functions

Function | Returns
Abs | The absolute value of a passed value.
Acos | The arc cosine of a passed value.
Asin | The arc sine of a passed value.
Atan | The arc tangent of a passed value.
Cos | The cosine of a passed value.
Exp | The antilogarithm of a passed value.
Log | The logarithm of a passed value.
Mod | The remainder of the integer division of two passed values.
Random | A random number.
Round | An integer value from a decimal value by rounding the decimal portion.
Sin | The sine of a passed value.
Sqrt | The square root of a passed value.
Tan | The tangent of a passed value.


Memory Management Functions

Function | Returns
AddressOf | Returns the address of an argument.
Alloc | Allocates a block of memory.
DeRefC | Retrieves the contents of one byte of memory using its address.
DeRefDW | Retrieves the contents of one double word (four bytes) of memory using its address.
DeRefW | Retrieves the contents of one word (two bytes) of memory using its address.
Free | Frees a block of dynamically allocated memory.
MemCompare | Compares the contents of two memory blocks.
MemCopy | Copies data from one memory address to another.
MemSet | Stores a given byte value in a memory block of a given size.
ReAlloc | Changes the size of a block of memory.
StoreC | Places a one byte value in memory using its address and an offset.
StoreDW | Places a one double-word (4-byte) value in memory using its address and an offset.
StoreW | Places a one word (2-byte) value in memory using its address and an offset.


RowId Helper Functions

RowIds are assigned and manipulated using functions that were created to handle RowId values. These functions provide a simple, yet complete, syntax for using RowIds in any program.

Function | Returns
GetRowID | The RowId of the currently buffered row of the passed table.
DeserializeRowID | Returns a RowId value that is representative of the passed string. This string should contain a serialized RowId.
FindByRowID | Allows you to specify a RowId to find a row in a table and load it into the buffer. Returns true if the row was located otherwise returns false.
IsNullRowID | Returns true if the passed RowId value is null, otherwise returns false.
IsSameRowID | Returns true if the two RowId parameters are equivalent, otherwise returns false.
NullRowID | Returns the null RowId value.
SerializeRowID | Returns a string value representing a serialization of the passed RowId value.


String Functions

Function | Returns
Append | The concatenation of two strings.
ASCII | The ASCII value of a character.
Center | A string of specified length with spaces added to, or characters truncated from, both sides so that the content is centered.
Character | The character corresponding to a specified ASCII number.
Cstring | Returns a null terminated string.
Eval | Calls an evaluation engine to evaluate an expression that is passed as a string. The result of this evaluation is returned.
FormatCurrency | Formats a number and returns it as a string formatted as a currency value.
FormatNumber | Formats a number and returns it as a string formatted as a number using locale number settings.
FormatValue | Formats a number with a custom formatting mask.
Insert | A string made up of one string inserted into another at a specified point.
Left | The leftmost characters of a passed string up to a specified length.
Length | The length of a string.
Lowercase | The passed string with all letters converted to lower case.
Ltrim | The passed string with all leading spaces removed.
Mid | A substring derived from the passed value starting at a specified position and of specified length.
Overstrike | A string whose value contains a passed substring at a specified location. The substring will overwrite any characters in the original string at the specified location.
Pad | A string of specified length with spaces added to, or truncated from, the right of a passes string.
Pos | The position of the first occurrence of one passed string within another.
Remove | A string consisting of the passed string with a specified number of characters removed at a specified location in the string.
Repeat | A string made up of a specified number of repetitions of the passed string.
Replace | A string with the first occurrence of one passed substring replaced with another.
Replaces | A string with all occurrences of one passed substring replaced with another.
Right | The rightmost characters of a passed string up to a specified length.
Rtrim | The passed string with all trailing spaces removed.
SFormat | Creates a formatted string by replacing markers in a host string (%1, %2, etc.) with sub-string values.
ToANSI | Converts a string from the OEM character set to the ANSI character set.
ToOEM | Converts a string from the ANSI character set to the OEM character set.
Trim | The passed string with all leading and trailing spaces removed.
Uppercase | The passed string with all letters converted to upper case.


Time and Date Functions

Function | Returns
CurrentDateTime | Returns a DateTime variable or Time variable that contains the current local time.
Date | Returns the passed value as a date.
DateGetDay | Returns the day of the month component of the given DateTime variable dtVar.
DateGetDayOfWeek | Returns the day of the week of the given DateTime variable.
DateGetDayOfYear | Returns the day of the year of the given DateTime variable.
DateGetHour | Returns the hour component of the given DateTime variable.
DateGetMinute | Returns the Minute component of the given DateTime variable.
DateGetMonth | Returns the Month component of the given DateTime variable.
DateGetSecond | Returns the Second component of the given DateTime variable.
DateGetYear | The DateGetYear function returns the Year component of the given DateTime variable.
DateSetDay | Returns a new DateTime value equal to the passed DateTime with its day adjusted to the passed Day value.
DateSetHour | Returns a new DateTime value equal to the passed DateTime with its hour adjusted to the passed Hour value.
DateSetMinute | Returns a new DateTime value equal to the passed DateTime with its minute adjusted to the passed Minute value.
DateSetMonth | Returns a new DateTime value equal to the passed DateTime with its month adjusted to the passed Month value.
DateSetSecond | Returns a new DateTime value equal to the passed DateTime with its seconds adjusted to the passed Seconds value.
DateSetYear | Returns a new DateTime value equal to the passed DateTime with its year adjusted to the passed Year value.
IsDateValid | Returns a Boolean value of 0 if the date is invalid, or 1 if the date is a valid date.
SpanDays | Returns the Days component of the given TimeSpan variable.
SpanHours | Returns the Hours component of the given TimeSpan variable.
SpanMinutes | Returns the Minutes component of the given TimeSpan variable.
SpanSeconds | The SpanSeconds function returns the Seconds component of the given TimeSpan variable.
SpanTotalDays | Calculates the total number of days in the time span and returns a double precision real number of that amount.
SpanTotalHours | Calculates the total number of Hours in the time span and returns a double precision real number of that amount.
SpanTotalMinutes | Calculates the total number of Minutes in the time span and returns a double precision real number of that amount.
SpanTotalSeconds | Calculates the total number of Seconds in the time span and returns a double precision real number of that amount.


Type Conversion Functions

Function | Returns
Cast | Returns a variable of the specified type that is the best conversion from the original variable.
Convert | Returns a variable of the specified type that is the best conversion from the original variable.
Cstring | Returns a null terminated string.
Date | The passed value as a date.
Integer | The passed value as an integer.
Number | The passed value as a number type.
Real | The passed value as a real number.
String | The passed value as a string.


Web Application Helper Functions

Function | Returns
HTMLEncode | Returns a string encoded so that it content will not be interpreted by a web browser as special HTML formatting characters.
HTMLEncodeNoCRLF | Returns a string encoded so that it content will not be interpreted by a web browser as special HTML formatting characters. This function also filters out carriage return and line feed characters.
WMLEncode | Returns a string encoded so that it content will not be interpreted by a WAP browser as special WML formatting characters.
WMLEncodeNoCrLf | Returns a string encoded so that it content will not be interpreted by a WAP browser as special WML formatting characters. This function also filters out carriage return and line feed characters.


Miscellaneous Functions

Function | Returns
AddBitValue | Returns an integer value binary or'ed with another integer value.
Eval | Calls an evaluation engine to evaluate an expression that is passed as a string. The result of this evaluation is returned.
Field_Number_Default_Mask | Returns a number or currency mask for a specific database file and field..
GUIScreen_Size | Returns the height and width of the screen in pixels.
Hi | The upper 2-bytes (16-bits) of a 4-byte integer.
If | One of two passed values depending on the outcome of a binary expression.
IsFlagIn | Returns a value of True, if a bit pattern is set in an integer value.
Low | The lower 2-bytes (16-bits) of a 4-byte integer.
Number_Default_Mask | Returns a mask for formatting number stings.
OemToUtf8Buffer | Converts an OEM string to UTF-8.
RemoveBitValue | Zeros (clears) the bit pattern of one integer in another.
Sysconf | Retrieves environment-specific information to running programs.
Utf8ToOemBuffer | Converts a UTF-8 string to OEM.
WindowsMessage | Send a message to the Windows message queue for the current object.


Abs

See Also: Math Functions

Purpose

Abs returns an absolute value.

Syntax

(Abs( {value} ))

What It Does

Abs returns the absolute value of {value}.

number nTabulation

Move (Abs(-8.3782)) To nTabulation

In this example, the absolute value of -8.3782 (8.3782) is moved to the variable nTabulation.


Acos

See Also: Math Functions, Asin, Atan, Cos

Purpose

Acos returns the arc cosine of a value.

Syntax

(Acos( {expression} ))

What It Does

Acos returns the value in radians of the arc cosine of the value of {expression}. The expression is an angle stated in radians.

Real rArcCos

Move (Acos(.70711)) To rArcCos

If the absolute value of {expression} exceeds 1, Visual DataFlex Error 59 "Floating point exception error" will be triggered, and the function will evaluate to zero.

Notes

  • The value of an acos expression is a number of radians. To convert radians to degrees, multiply them by 180 and divide them by the value of pi.

  • Acos converts {expression} to a real value, and outputs a real value.


AddBitValue

See Also: Miscellaneous Functions, IsFlagIn, RemoveBitValue, IAND operator, IOR operator

Purpose

Returns an integer value bitwise or'ed with another integer value.

Syntax

Use GlobalFunctionsProcedures.pkg

(AddBitValue( {iBitValue}, {iSource} ))

What It Does

AddBitValue performs a bitwise or operation on the two parameters {iBitValue} and {iSource} returning the result as an integer.

The following truth table displays the possible outputs of a binary or operation between two binary digits.

Ior | 0 | 1
0 | 0 | 1
1 | 1 | 1

If two integer values are bitwise or'ed together, then the resulting integer value is calculated by performing a binary or for each binary digit in the integer operands.

For example 2704 ior 255 = 2815

We can see this by inspecting the binary values of each integer…

1010 1001 0000 = 2704

0000 1111 1111 = 255

1010 1111 1111 = 2815

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Test

Integer iResult

Move (AddBitValue(2704 , 255 )) to iResult

Send Info_Box ("Result = " + string(iResult)) "Test"

End_Procedure

Notes

AddBitValue is useful for binary encoding information into a single integer value.


AddressOf

See Also: Memory Management Functions

Purpose

The AddressOf function returns the address of an argument.

Syntax

AddressOf( {var} )

Where:

  • {var} can be any variable, but not an expression or a constant value

Example

Procedure TestAddressOf

Integer i // Test Data.

Address addrOfI // Pointer

Integer iVal // Throwaway Variable.

Move 50 To i

Showln "i = " (string(i)) // This will show i = 50

Move (AddressOf(i)) to addrOfI

// Store 100 in i using the pointer addrOfI

Move (storedw(addrOfI, 0, 100)) to iVal

Showln "i = " (string(i) // Shows i = 100

End_Procedure

Important: When obtaining the address of a local variable you must first initialize the variable by assigning it a value. If you do not do this, the address returned will not be valid. In the above, example the "Move 50 to I" properly initialized the variable.


Alloc

See Also: Memory Management Functions

Purpose

Allocates a block of memory.

Syntax

Alloc( {iBytesAllocated} )

Where:

  • {iBytesAllocated} is the number of bytes requested

What It Does

Alloc returns either a pointer to the allocated memory block or zero, if the memory cannot be allocated. The memory is allocated on the process heap in Visual DataFlex.

Example

Move (Alloc(128)) To aPointer // get 128 byte memory block.


Append

See Also: String Functions, Set_Argument_Size, String Command, Expression Syntax

Purpose

Append returns the concatenation of two strings.

Syntax

(Append( {string1}, {string2} ))

What It Does

The append function returns a string made up of the concatenation of {string1} and {string2}.

String sMagicWord

Move "abraca" To sMagicWord

Move (Append(sMagicWord, "dabra")) To sMagicWord

Notes

  • The plus sign (+) performs string concatenation in expressions exactly as the append function does. Under the same circumstances, the minus sign (-) performs concatenation with trim (stripping of trailing spaces from the first value). The asterisk (*) performs concatenation with trim and inserts a single space between the trimmed values.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.


Ascii

See Also: String Functions, Character

Purpose

Ascii returns the ASCII value of a specified character.

Syntax

(Ascii( {character} ))

What It Does

Ascii returns the number that in the American Standard Code for Information Interchange (ASCII) represents the value of {character}.

char sInChar

If (Ascii(sInChar) > 127) Move "" To sInChar

In this example, the variable sInchar is cleared if its ASCII value is greater than 127.

The Ascii function returns values in decimal (10 based) numbers, not hexadecimal.

Notes

  • This function returns a value of Type Integer. If {character} is not a string, its value will be converted to that type for use in this function. If the result of this function is moved to a variable of type other than integer, its value will be converted to the destination type.

  • If {character} is a string of more than one character, the Ascii function returns the value of just the first character.


Asin

See Also: Math Functions, Acos, Atan, Sin

Purpose

Asin returns the arc sine of a value.

Syntax

(Asin( {expression} ))

What It Does

Asin returns the value in radians of the arc sine of the value of {expression}. The expression is an angle stated in radians.

Real rArcSine

Move (Asin(.70711)) To rArcSine

Notes

  • The value of an asin expression is a number of radians. To convert radians to degrees, multiply them by 180 and divide them by the value of p.

  • The domain for Asin is [-1,1]. Value for values other than |x|>1 is UNDEFINED.

  • Asin converts {expression} to a real value, and outputs a real value.


Atan

See Also: Math Functions, Acos, Asin, Tan

Purpose

Atan returns the arc tangent of a value.

Syntax

(Atan( {expression} ))

What It Does

Atan returns the value in radians of the arc tangent of the value of {expression}. The expression is an angle stated in radians.

Real rArcTangent

Move (Atan(.70711)) To rArcTangent

Notes

  • The value of an atan expression is a number of radians. To convert radians to degrees, multiply them by 180 and divide them by the value of p.

  • The domain for atan is [-1,1]. Value for values other than |x|>1 is UNDEFINED.

  • Atan converts {expression} to a real value, and outputs a real value.


B_From_RGB

See Also: Graphics Functions, Understanding RGB Colors, G_From_RGB, R_From_RGB, RGB

Purpose

Returns a byte value representing the Blue color intensity value of an RGB integer.

Syntax

Use RGB.pkg

(B_From_RGB( {rgbColor} ))

Where:

  • {rgbColor} is an RGB color value

Examples

Use RGB.pkg

Procedure OnClick

Integer rgbColor

Integer iRed iGreen iBlue

Get Value of oColor to rgbColor

Set TextColor of oText to rgbColor

Move (R_From_RGB(rgbColor)) to iRed

Move (G_From_RGB(rgbColor)) to iGreen

Move (B_From_RGB(rgbColor)) to iBlue

Set Value of oText to ("Red = " + string(iRed) + ", " + ;

"Green = " + string(iGreen) + ", " + ;

"Blue = " + string(iBlue))

End_Procedure


BinarySearchArray

See Also: Array Functions, CountArray, SearchArray

Purpose

Returns the index of the first element in the array (or indicated element range) equal to a particular value. BinarySearchArray is very efficient for large arrays.

Syntax

(BinarySearchArray( {SearchVal}, {ArrayId} [, {ObjectId} , {MessageId} ])

Where:

  • {SearchVal} is the value to compare array elements' values to. The index of the first element whose value is equal to {SearchVal} is returned.

  • {ArrayId} is the id of the array being searched. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare 2 array elements.

What it Does

Iterates from the first to the last element in an array and compares each element to the passed in value {SearchVal} or uses a custom function for the comparison. The index of the first element whose value is equal to {SearchVal} is returned. If no element with a value equal to {SearchVal} is found, -1 is returned.

The array must be sorted prior to calling BinarySearchArray.

To determine the number of times a value occurs in array, use CountArray.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient comparison method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal comparison algorithms, simply do not pass the {ObjectId} and {MessageId} parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to compare an array of elements that are of a type that cannot be compared using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom comparison function for the comparison process if a custom function is desired or required (for arrays of data types that cannot be compared using the internal algorithms: struct, RowId, variant).

It is important to return EQ in the user defined function if the two parameters passed are equal. This can be used to count array elements that meet certain conditions. The array element is passed as first parameter and the comparison value as the second parameter to a message {MessageId} of object {ObjectId}.

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

String array search:

This sample populates a dynamic array of strings (sCustomers), then searches it for the string "Jones". If the string is found, it displays the element in which the search term was found to the screen, otherwise a message stating that the string was not found is displayed. Last, the values of each array element is displayed to the screen.

This is really not a representative sample, since for an array of only 7 elements, you would use SearchArray rather than BinarySearchArray, but the sample shows you the proper syntax for this function.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

string sSearchTerm

integer iSearchIndex i iArraySize

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

// array MUST BE SORTED prior to calling BinarySearchArray

move (SortArray(sCustomers)) to sCustomers

// search for "Jones" in array

move "Jones" to sSearchTerm

move (BinarySearchArray(sSearchTerm, sCustomers)) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// display array values

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Case-insensitive string array search:

Searching a string array in a case-insensitive manner is a common task, so the virtual machine provides a predefined function for case-insensitive string comparison: get_DFSTRICMP, defined in the Desktop object.

Syntax

(BinarySearchArray( {SearchVal}, {ArrayId} , Desktop , get_DFSTRICMP))

This sample populates a dynamic array of strings (sCustomers), then searches it for the string "jones", no matter what the casing of any occurrence of "jones", in the sCustomers array. If the string is found, it displays the element in which the search term was found to the screen, otherwise a message stating that the string was not found is displayed. Last, the values of each array element is displayed to the screen.

This is really not a representative sample, since for an array of only 7 elements, you would use SearchArray rather than BinarySearchArray, but the sample shows you the proper syntax for this function.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

string sSearchTerm

integer iSearchIndex i iArraySize

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "JOnes" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

// array MUST BE SORTED prior to calling BinarySearchArray

move (SortArray(sCustomers)) to sCustomers

// search for "jones", in any casing, in array

move "jones" to sSearchTerm

move (BinarySearchArray(sSearchTerm, sCustomers, Desktop, get_DFSTRICMP)) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// display array values

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Struct array search:

This sample uses a custom comparison function to find the first friend with last name "Jones" are in an array of 10 tFriend structs.

The custom comparison function (MyComparison) returns EQ whenever the Last member of the tFriend struct passed in as the first parameter to the function is equal to the Last member of the tFriend struct passed in as the second parameter. If these values are not equal, the function returns GT or LT, if the first parameter is greater than or less than the second, respectively.

In Procedure OnClick, MyFriends is declared as an array of 10 elements of type tFriend and populated with friends' names. Another struct of type tFriend is declared to store the search value. Since our comparison function only compares the Last member (last name) of each struct in the array, the First struct member is not filled with any value.

Struct tFriend

String First

String Last

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tFriend MyFriend tFriend SearchFriend Returns Integer

integer iRetVal

if (MyFriend.Last > SearchFriend.Last) ;

Function_Return (GT)

if (MyFriend.Last < SearchFriend.Last) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

// declare array of 10 tFriend structs

tFriend[10] MyFriends

// declare tFriend struct that will hold search value(s)

tFriend SearchFriend

integer iSearchIndex i iArraySize

// move value to compare array values to the Comparison struct

move "Jones" to SearchFriend.Last

// fill MyFriends array

move "Janet" to MyFriends[0].First

move "Smith" to MyFriends[0].Last

move "Pedro" to MyFriends[1].First

move "Rodriguez" to MyFriends[1].Last

move "Judy" to MyFriends[2].First

move "Smith" to MyFriends[2].Last

move "Fred" to MyFriends[3].First

move "Jones" to MyFriends[3].Last

move "Martin" to MyFriends[4].First

move "Anderson" to MyFriends[4].Last

move "Michael" to MyFriends[5].First

move "Schmidt" to MyFriends[5].Last

move "Jacques" to MyFriends[6].First

move "Verne" to MyFriends[6].Last

move "Enrico" to MyFriends[7].First

move "Ricci" to MyFriends[7].Last

move "Karl" to MyFriends[8].First

move "Sorensen" to MyFriends[8].Last

move "Juan" to MyFriends[9].First

move "Garcia" to MyFriends[9].Last

// array MUST BE SORTED prior to calling BinarySearchArray

// call MySortComparison function to sort array elements

move (SortArray(MyFriends, Self, get_MySortComparison)) to MyFriends

// call MySortComparison function to search array elements for value(s) in SearchFriend

move (BinarySearchArray(SearchFriend, MyFriends, Self, get_MySortComparison)) to iSearchIndex

showln "The search value was found in element number " (string(iSearchIndex))

// display array element values

move (SizeOfArray(MyFriends)) to iArraySize

for i from 0 to (iArraySize-1)

showln ":" MyFriends[i].First ":" MyFriends[i].Last ":"

loop

End_Procedure // OnClick

Example

Searching a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Schmidt Verne Ricci

If the first "row" (row 0) of the array is searched, the search term "Jones" is found in element 3. If the second "row" (row 1) of the array is searched, the search term "Jones" is not found. This effectively limits the search to a specific "row" of the array.

Procedure OnClick

string[2][4] sCustomers

string sSearchTerm

integer iSearchIndex

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

// search for "Jones" in first "row" of array

move "Jones" to sSearchTerm

move (SortArray(sCustomers[0])) to sCustomers[0]

move (BinarySearchArray(sSearchTerm, sCustomers[0])) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// search for "Jones" in second "row" of array

move "Jones" to sSearchTerm

move (SortArray(sCustomers[1])) to sCustomers[1]

move (BinarySearchArray(sSearchTerm, sCustomers[1])) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

End_Procedure // OnClick


Cast

See Also: Type Conversion Functions

Purpose

The Cast function returns a variable of the specified type that is the best conversion from the original variable. Cast differs from convert in that it will not report conversion errors.

Syntax

Cast( {Var}, {Type} )

Where:

  • {Var} can be any variable, but not an expression or a constant value

  • {Type} is the name of a data type, for example "number"

Example

Procedure TestCast

uint u

integer i

move -1 to i

// Move integer i to unsigned u without an error.

move (cast(i, uint)) to u

showln u

End_Procedure


Center

See Also: String Functions, Length, Pad, Trim

Purpose

Center returns a string of specified length with spaces added to, or characters truncated from, both sides so that the input content is centered.

Syntax

(Center( {string-value}, {length} ))

What It Does

Center returns a value that has spaces added to the beginning and end of {string-value} until the length of the expression value is equal to {length}.

Move (Center("Visual DataFlex", 50)) To sChapterName

Notes

  • If {length} is less than the length of {string}, the Center function returns the value of {string} truncated on both sides to {length}.

  • If the parameter {string} is of type other than string, its value will be converted to a string for output.


Character

See Also: String Functions, Ascii

Purpose

Character returns the character related to a specified ASCII value.

Syntax

(Character( {value} ))

What It Does

Character returns the character that is represented in the American Standard Code for Information Interchange (ASCII) by the value of {value}.

string sBell

Move (Character(7)) To sBell

Notes

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If the {value} parameter is of type other than integer, its value will be converted to an integer before conversion.


Convert

See Also: Type Conversion Functions

Purpose

The Convert function returns a variable of the specified type that is the best conversion from the original variable.

Syntax

Convert( {Var}, {Type} )

Where:

  • {Var} can be any variable, but not an expression or a constant value

  • {Type} is the name of a data type, for example "number"

Example

Procedure testConvert

uint u

real r

move 3.1415 to r

// Move Real r to Unsigned Integer u, error will result

move (convert(r, uint)) to u

showln u

End_Procedure

Notes

  • If a conversion error occurs, error 4381 will be reported.


CopyArray

See Also: Array Functions, Array Variable Assignments

Purpose

Returns array representing a range of elements from the existing array.

Syntax

(CopyArray( {ArrayId}, {indexFirst}, {indexLast} ))

Where:

  • {ArrayId} is the id of the array to retrieve a range of elements from.

  • {indexFirst} is the index of the first element in the range to retrieve.

  • {indexLast} is the index of the last element in the range to retrieve.

What it Does

Creates new array from elements within the range of existing array.

Example

This sample declares an array (integers1) of 100 integers and fills it with the numbers 1 through 100. Next, it copies the first 20 elements of integers1 to a dynamic array (integers2), then displays all elements of the new array (integers2).

// fires when the button is clicked

Procedure OnClick

integer[100] integers1

integer[] integers2

integer i iSize

for i from 0 to 99

move (i+1) to integers1[i]

loop

move (CopyArray(integers1, 0, 19)) to integers2

move (SizeOfArray(integers2)) to iSize

for i from 0 to (iSize-1)

showln "integers2[" (string(i)) "] = " (string(integers2[i]))

loop

End_Procedure // OnClick

Example

This sample declares a two-dimensional dynamic array (integers1), containing an undefined number of elements of type integer. It then fills the second dimension of the array 10 times with the numbers 1 through 10, creating a total of 100 elements. Next, the sample copies the first 5 outer elements of integers1 to a dynamic array (integers2), then displays all elements of the new array (integers2).

// fires when the button is clicked

Procedure OnClick

integer[][10] integers1

integer[][10] integers2

integer i j iSize

for i from 0 to 9

for j from 0 to 9

move (j+1) to integers1[i][j]

loop

loop

move (CopyArray(integers1, 0, 5)) to integers2

move (SizeOfArray(integers2)) to iSize

for i from 0 to (iSize-1)

for j from 0 to 9

showln "integers2[" (string(i)) "][" (string(j)) "] = " (string(integers2[i][j]))

loop

loop

End_Procedure // OnClick

Notes

  • To make a full copy of an array, simply move an existing array to another array variable. This copies the array using a deep memberwise copy operation.

Example

This sample declares an array (integers1) of 100 integers and fills it with the numbers 1 through 100. Next, it copies the entire array integers1 (including the contents of all elements) to array integers2, then displays all elements of the new array (integers2).

// fires when the button is clicked

Procedure OnClick

integer[100] integers1 integers2

integer i iSize

for i from 0 to 99

move (i+1) to integers1[i]

loop

// full array copy

move integers1 to integers2

move (SizeOfArray(integers2)) to iSize

for i from 0 to (iSize-1)

showln "integers2[" (string(i)) "] = " (string(integers2[i]))

loop

End_Procedure // OnClick


CountArray

See Also: Array Functions, Array Variable Assignments

Purpose

Returns the number of array elements whose value is equal to a test value.

Syntax

(CountArray( {CompareVal}, {ArrayId}, {ObjectId}, {MessageId} ))

Where:

  • {CompareVal} is the value to compare array elements' values to. If any element's value is equal to {CompareVal}, the count to return will be incremented.

  • {ArrayId} is the id of the array to retrieve a range of elements from. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare array elements to {CompareVal}.

What it Does

Iterates through all elements in an array and compares each element to the passed in value {CompareVal} or uses a custom function for the comparison. The returned count is incremented for each matching element in the array.

To determine the element count of one or more dimensions of an array, use SizeOfArray.
To find a specific element value in an array, use SearchArray or BinarySearchArray.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient comparison method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal comparison algorithms, simply do not pass the {ObjectId} and {MessageId} parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to compare an array of elements that are of a type that cannot be compared using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom comparison function for the comparison process if a custom function is desired or required (for arrays of data types that cannot be compared using the internal algorithms: struct, RowId, variant).

It is important to return EQ in the user defined function if the two parameters passed are equal. This can be used to count array elements that meet certain conditions. The array element is passed as first parameter and the comparison value as the second parameter to a message {MessageId} of object {ObjectId}.

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

Counting elements in an array of strings:

This sample creates an array of 10 strings, then fills the array with names, 2 of them being "Smith". When CountArray is called, it returns a count of 2 for the number of array elements being equal to "Smith".

// fires when the button is clicked

Procedure OnClick

string[10] sCustomers

integer iCount

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

move "Ricci" to sCustomers[7]

move "Sorensen" to sCustomers[8]

move "Garcia" to sCustomers[9]

// counts the occurrence of "Smith" in sCustomers

move (CountArray("Smith", sCustomers)) to iCount

End_Procedure // OnClick

Example

Case-insensitive counting of elements in an array of strings:

Counting elements in a string array in a case-insensitive manner is a common task, so the virtual machine provides a predefined function for case-insensitive string comparison: get_DFSTRICMP, defined in the Desktop object.

Syntax

(CountArray( {CompareVal}, {ArrayId} , Desktop , get_DFSTRICMP))

This sample creates an array of 10 strings, then fills the array with names, 2 of them being "Smith". When CountArray is called, it returns a count of 2 for the number of array elements being equal to "Smith".

// fires when the button is clicked

Procedure OnClick

string[10] sCustomers

integer iCount

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

move "SMITH" to sCustomers[7]

move "Sorensen" to sCustomers[8]

move "Garcia" to sCustomers[9]

// counts the occurrence of "smith", in any casing, in sCustomers

move (CountArray("Smith", sCustomers, Desktop, get_DFSTRICMP)) to iCount

End_Procedure // OnClick

Example

Counting elements in an array of structs:

This sample uses a custom comparison function to count how many friends with last name "Smith" are in an array of 10 tFriend structs.

The custom comparison function (MyComparison) returns EQ whenever the Last member of the tFriend struct passed in as the first parameter to the function is equal to the Last member of the tFriend struct passed in as the second parameter. If these values are not equal, the function returns GT or LT, if the first parameter is greater than or less than the second, respectively.

In Procedure OnClick, MyFriends is declared as an array of 10 elements of type tFriend and populated with friends' names. Another struct of type tFriend is declared to store the comparison value. Since our comparison function only compares the Last member (last name) of each struct in the array, the First struct member is not filled with any value.

The result in iCount will be 2 using the data in this sample.

Struct tFriend

String First

String Last

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tFriend MyFriend tFriend SearchFriend Returns Integer

integer iRetVal

if (MyFriend.Last > SearchFriend.Last) ;

Function_Return (GT)

if (MyFriend.Last < SearchFriend.Last) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

// declare array of 10 tFriend structs

tFriend[10] MyFriends

// declare tFriend struct that will hold comparison value(s)

integer iCount

// move value to compare array values to the Comparison struct

move "Smith" to CompareFriend.Last

// fill MyFriends array

move "Janet" to MyFriends[0].First

move "Smith" to MyFriends[0].Last

move "Pedro" to MyFriends[1].First

move "Rodriguez" to MyFriends[1].Last

move "Judy" to MyFriends[2].First

move "Smith" to MyFriends[2].Last

move "Fred" to MyFriends[3].First

move "Jones" to MyFriends[3].Last

move "Martin" to MyFriends[4].First

move "Anderson" to MyFriends[4].Last

move "Michael" to MyFriends[5].First

move "Schmidt" to MyFriends[5].Last

move "Jacques" to MyFriends[6].First

move "Verne" to MyFriends[6].Last

move "Enrico" to MyFriends[7].First

move "Ricci" to MyFriends[7].Last

move "Karl" to MyFriends[8].First

move "Sorensen" to MyFriends[8].Last

move "Juan" to MyFriends[9].First

move "Garcia" to MyFriends[9].Last

// call MyComparison function to count array elements that match value(s) in CompareFriend

move (CountArray(CompareFriend, MyFriends, Self, get_MyComparison)) to iCount

End_Procedure // OnClick

Example

Counting a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Smith Verne Ricci

The number of occurrences of "Smith" in the first "row" (row 0) of the array is counted and displayed, then the second "row" (row 1). Last, the total count is displayed.

Procedure OnClick

string[2][4] sCustomers

string sSearchTerm

integer iCount0 iCount1

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Smith" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

move (CountArray("Smith",sCustomers[0])) to iCount0

showln "Count in first row of array: " (string(iCount0))

move (CountArray("Smith",sCustomers[1])) to iCount1

showln "Count in second row of array: " (string(iCount1))

showln "Count in full array: " (string(iCount0+iCount1))

End_Procedure // OnClick


CString

See Also: Type Conversion Functions, String Functions, CStringLength

Purpose

The CString function returns a zero terminated string.

Syntax

CString( {Var} )

Where:

  • {Var} can be any variable, but not an expression or a constant value

Example

Procedure DoSomething

string sFileName

move (CString(sFileName)) to sFileName

End_Procedure

Notes

If a Visual DataFlex program calls a DLL (to make a Windows API call, for example) and the function addressed does return a string, there are 2 possibilities. Either the calling program (Visual DataFlex) must pass a pointer to preserved space in memory at which the DLL writes the result, or the called program (the DLL function) returns a pointer to memory in which the value is stored.

In languages like 'C' - used to create DLLs - string types are different than those in Visual DataFlex. A string in such languages is an array of characters which is terminated with a 0 (zero) character to indicate the end of the string.

If your function call returns the data in the memory space of a Visual DataFlex string variable, you must get rid of the bytes after the terminating zero.

The CString function will translate the zero terminated cstring to a standard Visual DataFlex string.

Example

ZeroString 20 To sResult

Move (SomeAPIFunction (AddressOf (sResult)) To iRetval

If (iRetval) Begin

Move (CString (sResult)) To sResult

End

Example

Define MAX_COMPUTERNAME_LENGTH For 15

External_Function WinAPI_GetComputerName "GetComputerNameA" Kernel32.Dll ;

Pointer lpComputerName ;

Dword nNameSize ;

Returns Integer

Function GetComputerName Desktop Returns String

String sComputerName

Dword dwNameSize

Integer iRetval

ZeroString MAX_COMPUTERNAME_LENGTH To sComputerName

Move MAX_COMPUTERNAME_LENGTH To dwNameSize

Move (WinAPI_GetComputerName (AddressOf (sComputerName), AddressOf (dwNameSize))) To iRetval

Function_Return (CString (sComputerName))

End_Function // GetComputerName


CStringLength

See Also: CString

Purpose

CStringLength returns the number of characters in a null terminated C string.

Syntax

(CStringLength({pointer})

Where:

  • {pointer} is the pointer to the null terminated C string.

Example

Procedure Test

Address aXml

Integer iXmlStringLen

Get paXml of hoXmlNode to aXml

Move (CStringLength(aXml)) to iXmlStringLen

End_Procedure // Test

Notes

{pointer} must be a valid pointer to a null terminated C string. Use of this function with an invalid pointer or a pointer to a non-null terminated C string yields undefined behavior.


Cos

See Also: Math Functions, Acos, Sin, Tan

Purpose

Cos returns the cosine of a value.

Syntax

(Cos( {expression} ))

What It Does

Cos returns the cosine of the value of {expression}. The expression is an angle stated in radians.

Real rCosine

Move (Cos(.70711)) To rCosine

Notes

  • Cos interprets {expression} as a number of radians. To calculate the cosine of a number of degrees, divide the degrees by 180 and multiply them by the value of p.

  • The domain for cos is [-1,1]. Value for values other than |x|>1 is UNDEFINED.

  • Cos converts {expression} to a real value, and outputs a real value.


CurrentDateTime

See Also: Time and Date Functions

Purpose

The CurrentDateTime function returns a DateTime variable or Time variable that contains the current local time.

Syntax

CurrentDateTime()

Example

Procedure testCurrentDateTime

DateTime dtCurrentDateTime

Move (CurrentDateTime()) To dtCurrentDateTime

Showln "The time is " dtCurrentDateTime

End_Procedure


Date

See Also: Time and Date Functions, Type Conversion Functions, Round, String Function, String Command

Purpose

The Date function returns a value of type date regardless of the type of the passed value.

Syntax

(Date( {expression} ))

What It Does

Date converts the {expression} into a date.

Date dDate

Move (Date(4583)) To dDate

In this example, the integer (4583) is converted to the date 07/19/1912 (July 19, 1912) and moved to the date variable dDate.

Notes

  • It is not always necessary to convert numbers, strings, or other types to date. Most date calculations can be performed directly on number or integer values.


DateGetDay

See Also: Time and Date Functions

Purpose

The DateGetDay function returns the day of the month component of the given DateTime variable dtVar.

Syntax

DateGetDay( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetDay

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The day of this month is: " (DateGetDay(dtVar))

End_Procedure


DateGetDayOfWeek

See Also: Time and Date Functions

Purpose

The DateGetDayOfWeek function returns the day of the week of the given DateTime variable, dtVar. Sunday is 1, Monday is 2, Tuesday is 3, etc.

Syntax

DateGetDayOfWeek( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetDayofWeek

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The day of week of " dtvar " is: " (DateGetDayOfWeek(dtVar))

End_Procedure


DateGetDayOfYear

See Also: Time and Date Functions

Purpose

The DateGetDayOfYear function returns the day of the year of the given DateTime variable, dtVar.

Syntax

DateGetDayOfYear( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetDayOfYear

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The day of year of " dtvar " is: " (DateGetDayOfYear(dtVar))

End_Procedure


DateGetHour

See Also: Time and Date Functions

Purpose

The DateGetHour function returns the hour component of the given DateTime variable, dtVar.

Syntax

DateGetHour( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetHour

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The hour of " dtVar " is: " (DateGetHour(dtVar))

End_Procedure


DateGetMinute

See Also: Time and Date Functions

Purpose

The DateGetMinute function returns the Minute component of the given DateTime variable, dtVar.

Syntax

DateGetMinute( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetMinute

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The minute of " dtVar " is: " (DateGetMinute(dtVar))

End_Procedure


DateGetMonth

See Also: Time and Date Functions

Purpose

The DateGetMonth function returns the Month component of the given DateTime variable, dtVar.

Syntax

DateGetMonth( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetMonth

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The Month of " dtVar " is: " (DateGetMonth(dtVar))

End_Procedure


DateGetSecond

See Also: Time and Date Functions

Purpose

The DateGetSecond function returns the Second component of the given DateTime variable, dtVar.

Syntax

DateGetSecond( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetSecond

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The Second of " dtVar " is: " (DateGetSecond(dtVar))

End_Procedure


DateGetYear

See Also: Time and Date Functions

Purpose

The DateGetYear function returns the Year component of the given DateTime variable, dtVar.

Syntax

DateGetYear( {dtVar} )

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testDateGetYear

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Showln "The Year of " dtVar " is: " (DateGetYear(dtVar))

End_Procedure


DateSetDay

See Also: Time and Date Functions

Purpose

The DateSetDay function returns a new DateTime value that is the original value, dtVar, with the Day component changed to iDay.

Syntax

DateSetDay( {dtVar}, {iDay} )

Where:

  • {dtVar} is a value of type DateTime

  • {iDay} is an integer value representing the new day component of the DateTime

Example

Procedure testDateSetDay

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetDay(dtVar, 20)) To dtVar

// This will print:

// The day of month of 12/20/2003 4:04:27 PM is: 20

Showln "The day of month of " dtVar " is: " (DateGetDay(dtVar))

End_Procedure


DateSetHour

See Also: Time and Date Functions

Purpose

The DateSetHour function returns a new DateTime value that is the original value, dtVar, with the Hour component changed to iHour.

Syntax

DateSetHour( {dtVar}, {iHour} )

Where:

  • {dtVar} is a value of type DateTime

  • {iHour} is an integer value representing the new Hour component of the DateTime

Example

Procedure testDateSetHour

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetHour(dtVar, 9)) To dtVar

// This will print:

// The Hour of 2/23/2005 9:12:37 AM is: 9

Showln "The Hour of " dtVar " is: " (DateGetHour(dtVar))

End_Procedure


DateSetMinute

See Also: Time and Date Functions

Purpose

The DateSetMinute function returns a new DateTime value that is the original value, dtVar, with the Minute component changed to iMinute.

Syntax

DateSetMinute( {dtVar}, {iMinute} )

Where:

  • {dtVar} is a value of type DateTime

  • {iMinute} is an integer value representing the new Minute component of the DateTime

Example

Procedure testDateSetMinute

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetMinute(dtVar, 20)) To dtVar

// This will print:

// The Minute of 2/23/2005 9:20:09 AM is: 20

Showln "The Minute of " dtVar " is: " (DateGetMinute(dtVar))

End_Procedure


DateSetMonth

See Also: Time and Date Functions

Purpose

The DateSetMonth function returns a new DateTime value that is the original value, dtVar, with the Month component changed to iMonth.

Syntax

DateSetMonth( {dtVar}, {iMonth} )

Where:

  • {dtVar} is a value of type DateTime

  • {iMonth} is an integer value representing the new Month component of the DateTime

Example

Procedure testDateSetMonth

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetMonth(dtVar, 4)) To dtVar

// This will print:

// The Month of 4/23/2005 9:15:15 AM is: 4

Showln "The Month of " dtVar " is: " (DateGetMonth(dtVar))

End_Procedure


DateSetSecond

See Also: Time and Date Functions

Purpose

The DateSetSecond function returns a new DateTime value that is the original value, dtVar, with the Second component changed to iSecond.

Syntax

DateSetSecond( {dtVar}, {iSecond} )

Where:

  • {dtVar} is a value of type DateTime

  • {iSecond} is an integer value representing the new Second component of the DateTime

Example

Procedure testDateSetSecond

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetSecond(dtVar, 20)) To dtVar

// This will print:

// The Second of 2/23/2005 9:16:20 AM is: 20

Showln "The Second of " dtVar " is: " (DateGetSecond(dtVar))

End_Procedure


DateSetYear

See Also: Time and Date Functions

Purpose

The DateSetYear function returns a new DateTime value that is the original value, dtVar, with the Year component changed to iYear.

Syntax

DateSetYear( {dtVar}, {iYear} )

Where:

  • {dtVar} is a value of type DateTime

  • {iYear} is an integer value representing the new year component of the DateTime.

Example

Procedure testDateSetYear

DateTime dtVar

// Locale specific string to Date variable.

Move (CurrentDateTime()) To dtVar

Move (DateSetYear(dtVar, 2000)) To dtVar

// This will print:

// The year of 2/23/2000 9:20:09 AM is: 2000

Showln "The year of " dtVar " is: " (DateGetYear(dtVar))

End_Procedure


Default_Currency_Symbol

See Also: Locale Formatting Functions, FormatCurrency, SetCurrencyFormat

Purpose

Returns the Windows locale currency symbol.

Syntax

Use GlobalFunctionsProcedures.pkg

(Default_Currency_Symbol())

What It Does

Returns the string used as the local monetary symbol from the windows configuration registry.

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Example

String sCurrency

Move (Default_Currency_Symbol()) to sCurrency

Send Info_Box ("Price = " + sCurrency + "100") "Example"

End_Procedure

Notes

Use this function to internationalize the currency symbol displayed in your applications.


DeRefC

See Also: Memory Management Functions

Purpose

Retrieves the contents of one byte of memory using its address.

Syntax

DeRefC( {pMemory}, {iOffset} )

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the reading will take place

What It Does

Retrieves the contents of one byte of a memory block using its address and a given offset.

Example

Function GetMemoryByte Address aPointer Integer iOffset Returns Integer

Integer iByteValue

Move (DeRefC(aPointer, iOffset)) to iByteValue

Function_Return iByteValue

End_Function

Notes

  • Using the DeRefC function with invalid parameters will likely cause your program to crash.


DeRefDw

See Also: Memory Management Functions

Purpose

Retrieves the contents of one double word (four bytes) of memory using its address.

Syntax

DeRefDW( {pMemory}, {iOffset} )

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the reading will take place

What It Does

Retrieves the contents of one dword of a memory block using its address and a given offset.

Example

Function GetMemoryDWord Address aPointer Integer iOffset Returns Integer

Integer iDWordValue

Move (DeRefDW(aPointer, iOffset)) to iDWordValue

Function_Return iWordValue

End_Function

Notes

  • Using the DeRefDW function with invalid parameters will likely cause your program to crash.


DeRefW

See Also: Memory Management Functions

Purpose

Retrieves the contents of one word (two bytes) of memory using its address.

Syntax

DeRefW( {pMemory}, {iOffset} )

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the reading will take place

What It Does

Retrieves the contents of one word of a memory block using its address and a given offset.

Example

Function GetMemoryWord Address aPointer Integer iOffset Returns Integer

Integer iWordValue

Move (derefw(aPointer, iOffset)) to iWordValue

Function_Return iWordValue

End_Function

Notes

  • Using the DeRefW function with invalid parameters will likely cause your program to crash.


DeSerializeRowID

See Also: RowId, RowId Helper Functions

Purpose

To deserialize a serialized RowId string back into a RowId data type

Syntax

DeserializeRowId( {RowId} )

Where:

  • {RowId} is a value of type RowId

Example

Procedure RefindFromWebPage

String sRowId

RowId riCustomer

Boolean bFound

Get SerializedRowIdFromPage to sRowid

Move (DeserializeRowId(sRowId)) to riCustomer

Move (FindByRowId(Customer.File_Number, riCustomer)) to bFound

End_Procedure // RefindFromWebPage

Notes

  • DeserializeRowId converts a previously serialized RowId string back to its native RowId data type. The RowId serialization / deserialization process was created primarily to allow RowId to be represented over HTTP in web pages and web services.

  • A serialized RowId string is created by using the SerializeRowId function.

  • RowId variables cannot be cast into any other variable type. This serialization / deserialization process represents the only way RowId data can be moved to another type.

  • The rules for serialization and deserialization are private. Therefore a serialized RowId has no meaningful value. You program code should not rely on specific values for serialized RowIds. The single exception to this are null serialized RowId values. They always serialize to an empty string.


Eval

See Also: Miscellaneous Functions, String Functions

Purpose

Eval returns the value of a string, evaluated as an expression at runtime.

Syntax

(Eval( {string-expression} ))

What It Does

The eval function provides evaluation at runtime of expressions stored as strings.

Procedure Test

String sExpression sOperator

Integer iOperand1 iOperand2 iResult

Move 10 to iOperand1

Move 8 to iOperand2

Move "+" to sOperator

Move (String (iOperand1) + sOperator + String(iOperand2)) to sExpression

Move (Eval(sExpression)) to iResult

End_Procedure // Test

In this example, string that is stored in sExpression is parsed and evaluated, the answer (18) is stored in the integer variable iResult.

Procedure Test

String sExpression sOperator sOperand1 sOperand2

Number nResult

Find Gt Invt.Recnum

Move "Invt.Unit_Price" to sOperand1

Move "Invt.On_Hand" to sOperand2

Move "*" to sOperator

Move (sOperand1 + sOperator + sOperand2) to sExpression

Move (Eval(sExpression)) to nResult

Send Info_Box ("The result of\n\n" + sExpression + "\n\nis" * String (nResult)) "Result"

End_Procedure // Test

The result of the record value invt.unit_price multiplied by the value of invt.on_hand will be shown in the message box. For this sample, the file invt needs to be opened before and the Windows.pkg needs to be USEd.

Notes

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.


Exp

See Also: Math Functions, Log, Sqrt

Purpose

Exp returns the natural antilogarithm of a value.

Syntax

(Exp( {expression} ))

What It Does

Exp raises the value of e (2.71828), the natural logarithm base, to the power of {expression}.

Real rPower

Move (Exp(10)) To rPower

Notes

  • To calculate the natural logarithm of a number, use the log function.

  • To calculate the common (base 10) antilogarithm of a value, use exp on the value multiplied by the common logarithm of 10 (2.30258509).

Example

In this example, the common antilogarithm (1.0e45) of 45 is output to variable rAntilogCom.

Procedure Test

real rAntilogCom

Move (Exp(45 * Log(10))) To rAntilogCom

End_Procedure // Test

  • Exp converts the {expression} parameter to a real value, and outputs a real value.


Field_Number_Default_Mask

See Also: Miscellaneous Functions, Number_Default_Mask, Field Masks

Purpose

Returns a number or currency mask for a specific database table and field.

Syntax

Use GlobalFunctionsProcedures.pkg

(Field_Number_Default_Mask( {hTable}, {iField}, {sMask} ))

Where:

  • {hTable} is the table number from filelist.cfg of a database table

  • {iField} is the field number of a numeric field in the table specified by hTable

  • {sMask} must be a valid Visual DataFlex numeric mask

What It Does

Field_Number_Default_Mask tailors the passed template mask {sMask} to the passed database table {hTable} and field {iField}.

Field_Number_Default_Mask returns a Visual DataFlex mask string.

Example

Use GlobalFunctionsProcedures.pkg

Open Customer

Procedure Example

String sMask

Integer iField

handle hTable

Get_FileNumber Customer.Balance to hTable

Get_FieldNumber Customer.Balance to iField

Move (Field_Number_Default_Mask(hTable, iField, "$,*;($,*)")) to sMask

Send Info_Box ("Mask = " + sMask) "Example"

End_Procedure

This example displays the mask string "$,######0.00;($,######0.00)"

Notes

The table referred to by the file number parameter must be open.


FillArray

See Also: Array Functions, Array Variable Assignments

Purpose

Fills an array element range with a specified value.

Syntax

(FillArray( {assignVal}, {ArrayId} [, {indexFirst}, {indexLast} ] ))

Where:

  • {assignVal} is the value that will be assigned to each array element in the specified range.

  • {ArrayId} is the id of the array to retrieve a range of elements from.

  • {indexFirst} is the index of the first element in the range to assign a value to.

  • {indexLast} is the index of the last element in the range to assign a value to.

What it Does

Iterates the array elements from {indexFirst} to {indexLast} and assigns each element in that range the value {assignVal}. This is useful for initializing arrays with default values. FillArray does not create new elements in an array, it only fills existing elements with values.

Example

This sample fills all elements in an array of 100 strings with the value "None".

string[100] sCustomers

move (FillArray("None", sCustomers)) to sCustomers

Example

This sample fills the first 20 elements in an array of 100 strings with the value "None".

string[100] sCustomers

move (FillArray("None", sCustomers, 0, 19)) to sCustomers

Example

This sample places default values into a struct of type tUSAddress (DefaultAddress), then fills all elements in an array of 100 tUSAddress structs with the defaulted values in the DefaultAddress struct.

Struct tUSAddress

String Street

String City

String State

Integer ZipCode

End_Struct

// fires when the button is clicked

Procedure OnClick

tUSAddress[100] sCustomerAddresses

tUSAddress DefaultAddress

// fill DefaultAddress struct with default values

move "" to DefaultAddress.Street

move "Miami" to DefaultAddress.City

move "FL" to DefaultAddress.State

move 33186 to DefaultAddress.ZipCode

// copy values from DefaultAddress struct to each of the structs

// in the sCustomerAddresses array

move (FillArray(DefaultAddress, sCustomerAddresses)) to sCustomerAddresses

End_Procedure // OnClick

Example

This sample fills a multidimensional array. This cannot be done directly, but instead this sample shows you how to loop through the outer dimension of the array and fill it one row at a time. Afterwards, the sample displays the array values to the screen.

// fires when the button is clicked

Procedure OnClick

string[10][10] sCustomers

integer i j iDim1Size iDim2Size

// loop through outer dimension

for i from 0 to 9

// fill array one row at a time

move (FillArray("None", sCustomers[i])) to sCustomers[i]

loop

// display values in array

move (SizeOfArray(sCustomers)) to iDim1Size

move (SizeOfArray(sCustomers[1])) to iDim2Size

for i from 0 to (iDim1Size-1)

for j from 0 to (iDim2Size-1)

show sCustomers[i][j]

show " "

loop

showln

loop

End_Procedure // OnClick

Example

This sample places default values into a struct of type tUSAddress (DefaultAddress), then fills the first 20 elements in an array of 100 tUSAddress structs with the defaulted values in the DefaultAddress struct.

Struct tUSAddress

String Street

String City

String State

Integer ZipCode

End_Struct

// fires when the button is clicked

Procedure OnClick

tUSAddress[100] sCustomerAddresses

tUSAddress DefaultAddress

// fill DefaultAddress struct with default values

move "" to DefaultAddress.Street

move "Miami" to DefaultAddress.City

move "FL" to DefaultAddress.State

move 33186 to DefaultAddress.ZipCode

// copy values from DefaultAddress struct to each of the structs

// in the sCustomerAddresses array

move (FillArray(DefaultAddress, sCustomerAddresses, 0, 19)) to sCustomerAddresses

End_Procedure // OnClick


FindByRowId

See Also: RowId, RowId Helper Functions

Purpose

Finds a record for a table by its RowId

Syntax

FindByRowId( {hTable}, {RowId} )

Where:

  • {hTable} is the table number of some open database table

  • {RowId} is a value of type RowId

Example

Function RefindLastRecord returns Boolean

RowId riCustomer

Boolean bFound

Get priLastRow to riCustomer

If (not(IsNullRowId(riCustomer))) begin

Move (FindByRowId(Customer.File_Number, riCustomer)) to bFound

End

Function_Return bFound

End_Function // RefindLastRecord

Notes

FindByRowId attempts to find a record by performing a find EQ based on a record's RowId. The function is passed a table number and a RowId and it returns a boolean determining if a row was found.

If a record is found, the function:

  1. Returns True

  2. Sets the Found indicator to True

  3. Has an active row loaded in the table's buffer

If a record is not found, the function:

  1. Returns False

  2. Sets the Found indicator to False

  3. Clears all columns in the table's buffer

If a null RowId is used in the function, no row is found and the table buffer is cleared.

The RowId value passed must be a valid RowId for the finding table. Passing a RowId from a different table, yields undefined behavior.


FormatCurrency

See Also: Locale Formatting Functions, String Functions, SetCurrencyFormat, SetNumberFormat, FormatNumber

Purpose

The FormatCurrency function formats a number and returns it as a string. The formatting by default uses the locale currency settings of your machine, and the iPoints parameter determines the number of digits to the right of the decimal.

FormatCurrency number nCurrency integer iPoints returns string — function

Syntax

Use gFormatNumbers.pkg

(FormatCurrency( {nVar}, {iPoints} ))

Where:

  • {nVar} ia a value of type number

  • {iPoints} determines the formatting. Possible values for {iPoints}:

0 or Greater | Use the points as specified to limit the digits to the right of the decimal
-1 | Use points as defined in the SetCurrencyFormat message
-2 | Allow any number of points to the right of the decimal as needed

What it Does

The formatting of the fractional portion is based on the iPoints parameter value. The rest of the currency formatting uses your locale Regional Setting Properties for Currency.

If you do not wish to use these default currency settings you may customize a format-string to use as the formatting mask by sending the SetCurrencyFormat message.

Move (FormatCurrency(nVar, 2)) to sString

Formatting with the locale Regional Setting Properties for Currency will give different results since settings can be different on each computer.

For example:

Move (FormatCurrency(nNumber, 2)) to sString

Would result with DM123.222,22 and -DM123.222,22 with German settings, but $123,222.22 and -$123,222.22 with USA regional settings.

Notes

  • The FormatCurrency function is almost identical to the FormatNumber function. The reason for the two very similar functions is that one is used in conjunction with the SetCurrencyFormat masking function and the other is used in conjunction with the SetNumberFormat masking function. This allows us to have two masks available, one for masking numbers and one for masking currency.

  • The iPoints parameter is used to truncate the decimal portion; no rounding of the number occurs.

This example shows when to use the FormatCurrency and FormatNumber functions:

Procedure OnBody

Send WriteHtmlRowBegin

Send WriteHtmlCell (HtmlEncode(invt.Item_id)) 'align="left" '

Send WriteHtmlCell (HtmlEncode(Invt.Description)) 'align="left" '

Send WriteHtmlCell (FormatNumber(OrderDtl.Price,2)) 'align="right" '

Send WriteHtmlCell (FormatNumber(OrderDtl.Qty_ordered,0)) 'align="right" '

// displays extended price with currency symbol:

Send WriteHtmlCell (FormatCurrency(OrderDtl.Extended_Price,2)) 'align="right" '

Send AddSubTotal 1 OrderDtl.Extended_Price

Send WriteHtmlRowEnd

End_Procedure

Procedure OnPageBottom

Number nTotal

Send WriteHtmlCell "" 'colspan="4" bgColor="Silver" '

Get SubTotal 1 to nTotal

Send WriteHtmlCell (FormatCurrency(nTotal,2)) 'bgColor="Silver" align="right" '

Send WriteHtmlTableEnd

End_Procedure


FormatNumber

See Also: Locale Formatting Functions, String Functions, SetNumberFormat, SetCurrencyFormat, FormatCurrency

Purpose

The FormatNumber function formats a number and returns it as a string. The formatting by default uses the locale number settings of your machine, and the iPoints parameter determines the number of digits to the right of the decimal.

FormatNumber number nNumber integer iPoints returns string — function

Syntax

Use gFormatNumbers.pkg

(FormatNumber( {nVar}, {iPoints} ))

Where:

  • {nVar} ia a value of type number

  • {iPoints} determines the formatting. Possible values for {iPoints}:

0 or Greater | Use the points as specified to limit the digits to the right of the decimal
-1 | Use points as defined in the SetNumberFormat message
-2 | Allow any number of points to the right of the decimal as needed

What it Does

The formatting of the fractional portion is based on the iPoints parameter value. The rest of the number formatting uses your locale Regional Setting Properties for Numbers.

If you do not wish to use these default currency settings you may customize a format-string to use as the formatting mask by sending the SetNumberFormat message.

Move (FormatNumber(nVar, 2)) to sString

Formatting with the locale Regional Setting Properties for Numbers will give different results since settings can be different on each computer.

For example:

Move (FormatNumber(nNumber, 2)) to sString

Would result with 123.222,22 and -123.222,22 with German settings, but 123,222.22 and -123,222.22 with USA regional settings.

Special Notes

  • The FormatNumber function is almost identical to the FormatCurrency function. The reason for the two very similar functions is that one is used in conjunction with the SetNumberFormat masking function and the other is used in conjunction with the SetCurrencyFormat masking function. This allows us to have two masks available, one for masking numbers and one for masking currency.

  • The iPoints parameter is used to truncate the decimal portion; no rounding of the number occurs.


FormatValue

See Also: Locale Formatting Functions, String Functions, SetCurrencyFormat, SetNumberFormat, FormatNumber, FormatCurrency

Purpose

The FormatValue function formats a number with a custom format-string.

FormatValue number nNumber string sFormatString returns string — function

Syntax

Use gFormatNumbers.pkg

(FormatValue( {nVar}, {sFormatString} ))

Where:

  • {nVar} ia a value of type number

  • {sFormatString} determines the formatting. Token characters for sFormatString are:

$ | currency symbol as defined by windows
, | thousands separator as defined by windows
. | decimal separator as defined by windows
; | separates the positive and negative format, if the negative format is omitted the positive string is used with a preceding "-"
# | represents a digit, the quantity of tokens only matters to the right of the decimal
* | can be used to the right of the decimal, it means any number of decimals

All other characters are constants. They are just printed as displayed. E.g; the "(" and ")" for negative numbers.

If you wish to display a token as a literal, use a slash in front of it e.g. /$ would create $. Even in Germany, no matter what the currency symbol defined by windows.

What it Does

The custom format in the sFormatString parameter is applied to the number. It returns the formated value as a string.

The sFormatString operates very similarly to the DataDictionary masking strings.

Example

The format-string $,#.##;($,#.##) will insert thousand separators (commas) and currency symbols and truncate the number to 2 decimal places; negative numbers would appear within parentheses.

Many tokens use locale information. Therefore the results will differ depending on your Regional Setting Properties for Numbers.

Move 123222.22 to nNumber
Move ",#.## $;,-#.## $" to sFormatString
Move (FormatValue(nNumber,sFormatString)) to sString

Would result with 123.222,22 DM and -123.222,22 DM with German settings, but 123,222.22 $ and -123,222.22 $ with USA regional settings.

Notes

  • Use this function when you need to customize a few numbers. Normally, it is best to use the FormatCurrency function or the FormatNumber function because they are faster.


Free

See Also: Memory Management Functions

Purpose

Frees a block of memory.

Syntax

Free( {pSomeAddress} )

Where:

  • {pSomeAddress} is the pointer of the memory block to be freed.

What It Does

Free is used to return allocated memory to the system. Use Free to dispose all allocations made by Alloc.

Example

Boolean bRetVal

Pointer aPointer

Move (Free(aPointer)) to bRetVal


G_From_RGB

See Also: Graphics Functions, Understanding RGB Colors, B_From_RGB, R_From_RGB, RGB

Purpose

Returns a byte value representing the Green color intensity value of an RGB integer.

Syntax

Use RGB.pkg

(G_From_RGB( {rgbColor} ))

Where:

  • {rgbColor} is an RGB color value

Examples

Use RGB.pkg

Procedure OnClick

Integer rgbColor

Integer iRed iGreen iBlue

Get Value of oColor to rgbColor

Set TextColor of oText to rgbColor

Move (R_From_RGB(rgbColor)) to iRed

Move (G_From_RGB(rgbColor)) to iGreen

Move (B_From_RGB(rgbColor)) to iBlue

Set Value of oText to ("Red = " + string(iRed) + ", " + ;

"Green = " + string(iGreen) + ", " + ;

"Blue = " + string(iBlue))

End_Procedure


GetRowID

See Also: RowId, RowId Helper Functions

Purpose

Returns the RowId of the currently buffered row of a database table.

Syntax

(GetRowId( {hTable} ))

Where:

  • {hTable} is the table number of some open database table

Example

Procedure GetRecord

RowId riCustomer

Find GT Customer by 1

If (Found) Begin

Move (GetRowId(Customer.File_Number)) to riCustomer

Set priLastRow to riCustomer

End

Ed_Procedure

Notes

  • GetRowId returns the RowId of a table as a RowId data type. Attempting to place a RowId value into some other data type will result in a runtime error.

  • If the table does not have any row buffered, the returned RowId value will be null. Using the IsNullRowId function can test for this condition.


GUIScreen_Size

See Also: Miscellaneous Functions

Purpose

Returns the height and width of the screen in pixels.

Syntax

Use GlobalFunctionsProcedures.pkg

(GUIScreen_Size( {eMode} ))

Where:

  • If {eMode} is 0, GUIScreen_Size returns the width and height, in pixels, of the screen.

  • If {eMode} is 1, GUIScreen_Size returns the width and height, in pixels, of the screen's working area. The working area is the portion of the screen not obscured by the tray (taskbar).

What It Does

GUIScreen_Size returns the height and width of the screen in pixels.

The height and width values returned are encoded into a single integer value. The height is stored in the high word and the width is stored in the low word.

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Example

Integer iSize iHeight iWidth

Move (GUIScreen_Size(0)) to iSize

Move (Hi(iSize)) to iHeight

Move (Low(iSize)) to iWidth

Send Info_Box ("Screen height = " + string(iHeight) + ;

" width = " + string(iWidth)) "Example"

Move (GUIScreen_Size(1)) to iSize

Move (Hi(iSize)) to iHeight

Move (Low(iSize)) to iWidth

Send Info_Box ("Working Area height = " + string(iHeight) + ;

" width = " + string(iWidth)) "Example"

End_Procedure

Notes

Use the Hi and Low functions to extract the height and width values from the returned integer.


Hi

See Also: Miscellaneous Functions, Low, Integer

Purpose

The Hi function returns the value of the upper 16 bits (left-most 2-bytes) of an integer value.

Syntax

(Hi( {expression} ))

Where:

  • {expression} may be of any type except string. If it is not an integer, it will be converted to an unsigned integer first.

What It Does

Visual DataFlex integers have a storage capacity of 32 binary bits (4-bytes). With the hi and low functions, a single integer can be used to encode two 16-bit (2-byte) values each. The value of the upper 16 bits only of an integer can be retrieved with the hi function.

Move (Hi(iCoordinate)) To iRowNum

Notes

  • The {expression} value is an unsigned integer, and may be in the range 0 to 4,294,967,294.

  • This function returns a value of type integer. If the {expression} parameter is not an integer, its value will be converted to an unsigned integer for use in this function. If the result of this function is moved to a variable of type other than integer, its value will be converted to the destination type.

  • To combine two positive integer values into a single Integer for subsequent disassembly by hi and low, multiply the value assigned to hi by 65,536 and add it to the value assigned to low.

  • Certain properties in the Visual DataFlex class library (such as Size and Location) use complex integers for disassembly by the hi and low functions.


HtmlEncode

See Also: Web Application Helper Functions

Purpose

The HtmlEncode function ensures that when field data is passed back to the ASP file, the data is properly encoded so that the text will not be interpreted by the browser as special HTML formatting characters. It also adds "<br />" to the end of each line.

Syntax

(HtmlEncode( {string-value} ))

What it Does

Before field data is passed back to the Active Server Page (ASP) file, you will often want to make sure that the data is properly encoded so that the text will not be interpreted by the browser as special HTML formatting characters. The characters that it checks for are &<>" and characters 10 and 13. For example, your data might contain the following text:

"To create a bold string you should enter the <b> character."

Without some kind of conversion, the <b> will be interpreted by your browser as the start of a bold block. The HtmlEncode function will convert this text so that it properly uses HTML replacement characters. In this case, you want the string to be passed to ASP as:

"To create a bold string you should enter the &lt;b&gt; character"

This will properly display in the browser as "<b>."

Note: The function DDValue (when iOption is 0) and the procedure WriteHtmlPlainText perform this conversion for you automatically. When you create custom augmentations of DDValue, you should remember to encode your data if it is required. When you create reports using any other Write message other than WriteHtmlPlainText, you should remember to encode your data as needed. Normally you will want to encode all string and text data.

Example

Move (HtmlEncode(sText)) to sText
Send WriteHtml (HtmlEncode (sTemp))
Move (HtmlEncode(Customer.Notes)) to sNotes
Send WriteHtml sNotes
Send WriteHtmlCell (HtmlEncode(Customer.Name))

Notes

  • The reason that most Write messages are not automatically encoded is so you can embed custom HTML encoding in your output strings. E.g.,

// output the text field in italics
Send WriteHtml ("<i>"+HtmlEncode(sNotes)+"</i>")

  • It is very important that you remember to encode your data or your resulting HTML output may be undesirabe.


HtmlEncodeNoCRLF

See Also: Web Application Helper Functions

Purpose

The HtmlEncodeNoCRLF function ensures that when field data is passed back to the ASP file, the data is properly encoded so that the text will not be interpreted by the browser as special HTML formatting characters.

To add "<br />" to the end of each line passed to the function, use HTMLEncode.

Syntax

(HtmlEncodeNoCRLF( {string-value} ))

What it Does

Before field data is passed back to the Active Server Page (ASP) file, you will often want to make sure that the data is properly encoded so that the text will not be interpreted by the browser as special HTML formatting characters. The characters that it checks for are &<>" and characters 10 and 13. For example, your data might contain the following text:

"To create a bold string you should enter the <b> character."

Without some kind of conversion, the <b> will be interpreted by your browser as the start of a bold block. The HtmlEncodeNoCRLF function will convert this text so that it properly uses HTML replacement characters. In this case, you want the string to be passed to ASP as:

"To create a bold string you should enter the &lt;b&gt; character"

This will properly display in the browser as "<b>."

Note: The function DDValue (when iOption is 0) and the procedure WriteHtmlPlainText perform this conversion for you automatically. When you create custom augmentations of DDValue, you should remember to encode your data if it is required. When you create reports using any other Write message other than WriteHtmlPlainText, you should remember to encode your data as needed. Normally you will want to encode all string and text data.

Example

Move (HtmlEncodeNoCRLF(sText)) to sText
Send WriteHtml (HtmlEncodeNoCRLF (sTemp))
Move (HtmlEncodeNoCRLF(Customer.Notes)) to sNotes
Send WriteHtml sNotes
Send WriteHtmlCell (HtmlEncodeNoCRLF(Customer.Name))

Notes

  • The reason that most Write messages are not automatically encoded is so you can embed custom HTML encoding in your output strings. E.g.,

// output the text field in italics
Send WriteHtml ("<i>"+HtmlEncodeNoCRLF(sNotes)+"</i>")

  • It is very important that you remember to encode your data or your resulting HTML output may be undesirabe.


If

See Also: Miscellaneous Functions, Case, For, Repeat, Until, While, If command

Purpose

Evaluates a Boolean expression, then returns the value of one of two other expressions depending on the Boolean result.

Syntax

(If( {Boolean-expression}, {true-expression}, {false-expression} ))

Where:

  • {Boolean-expression} is the test that is performed to determine which of the following expressions will be performed

  • {true-expression} is the value that will be returned if the Boolean result is True

  • {false-expression} is the value that will be returned if the Boolean result is False

What It Does

Returns {true-expression} if {Boolean-expression} evaluates to True and {false-expression} if {Boolean-expression} evaluates to False.

Showln (If(iHome > iVisitors, "we won!", "they won."))

In this example, if the value of variable iHome is greater than that of variable iVisitors, the constant, "we won!" is shown. If it is not, the constant "they won." is shown.

Notes

  • If the {Boolean-expression} is zero or blank, the {false-expression} is returned, and if it is not zero or blank, {true-expression} is returned.


Info_Box

See Also: Dialog and Message Box Functions, Message_Box, Stop_Box, YesNo_Box, YesNoCancel_Box

Purpose

Displays an information dialog box.

Syntax

Use Windows.pkg

Send Info_Box {sMessage} [ {sCaption} ]

Where:

  • {sMessage} is a string containing the information message to be shown. A carriage-return/linefeed can be placed in the message string by the inclusion of \n in the text.

  • The {sCaption} parameter is optional. If passed, it specifies the content of the caption bar. If {sCaption} is not passed, the caption bar will display the string "Information".

What It Does

Info_Box is used to pop up a modal information message box. The message string {sMessage} is displayed in a message box dialog along with the Information icon and a single OK button.

Examples

Send Info_Box "The update has successfully completed"

In the above example, the information dialog's caption bar will read "Information".

Send Info_Box ("Printer is On line.\n" + ;

"Current Port is" * sPortName) "Printer Status"

In the above example a string expression is used to build the message text. The text will be broken over two lines. The info box will display "Printer Status" in its caption bar.

Notes

If the user types Ctrl+C in the info box, the text of the message is copied to the clipboard.


Insert

See Also: String Functions, Length, Overstrike, Pos, Replace

Purpose

Insert returns a string made up of one string inserted into another at a specified place.

Syntax

(Insert ( {insert-string}, {host-string}, {position} ))

Where:

  • {insert-string} is the string to be inserted into the {host-string}.

  • {host-string} is the string that {insert-string} is to be inserted to.

  • {position} is the number of characters from the left of the {host-string} that the {insert-string} will be placed. The {position} value is 1-based. That is, the position of the first character in the {host-string} is 1, the second character is 2, etc.

What It Does

Insert returns the value of the {host-string} with the value of {insert-string} inserted before the character that occupies the {position}'th character in the {host-string}.

Number nDigits

Move 123456789 To nDigits

Show (Insert("abc", nDigits, 3))

In this example, the value "12abc3456789" is shown.

Notes

  • If the {insert-string}, or {host-string} parameters are of type other than string, their values will be converted to a string for output.


Integer

See Also: Type Conversion Functions, Integer, Number, Real, Round, String

Purpose

The Integer function returns a value of type integer from an input of another type.

Syntax

(Integer( {expression} ))

Where:

  • {expression} cannot be of type string

What It Does

The Integer function converts the {expression} into an integer. It eliminates the fractional portion (digits to the right of the decimal point) from the value of an expression.

Move (Integer(-8.3782)) To iTabulation

In this example, the value -8 is moved to the variable iTabulation.

The Integer function does not change the type of the {expression}. It only affects the numeric precision to which {expression} is converted.

Notes

  • When used inside an expression, integer affects only the precision of its own expression, not that of the evaluation of the overall expression.

Number nResult nMean

Move (3.14 * Integer(nMean)) To nResult

This example would output 3.14 times the integer of the value of the number variable nMean to the number variable nResult in the full precision of number variables.

  • Real and number values are converted to integer values by truncation of the decimal portion of the value. To round to integers, use the round function.

  • Integers can be used as Booleans values. A value of 0 is Boolean false, and any other value, positive or negative, is true.


IsDateValid

See Also: Time and Date Functions

Purpose

The IsDateValid function returns a boolean value of 0 if the date is invalid, or 1 if the date is a valid date. dtVar is a DateTime value.

Syntax

(IsDateValid( {dtVar} ))

Where:

  • {dtVar} is a value of type DateTime

Example

Procedure testIsDateValid

DateTime dtVar

// Locale specific string to Date variable.

Move "12/31/99 11:59:59 PM" To dtVar

Move (DateSetDay(dtVar, 99)) To dtVar

// The date is invalid.

If (IsDateValid(dtVar)=0);

Showln "Invalid Date!"

Else;

Showln "The new date is " dtVar

End_Procedure


IsFlagIn

See Also: Miscellaneous Functions, AddBitValue, RemoveBitValue, IAND operator, IOR operator

Purpose

Returns a value of True, if the iFlag bit is in any bit in the iFlags parameter.

Syntax

(IsFlagIn( {iFlag}, {iFlags} ))

Where:

  • {iFlag} is the bit pattern to check for in {iFlags}

  • {iFlags} is the value in which to check for the inclusion of {iFlag}

Example

Move (IsFlagIn(mkShift, fKeys)) To bShiftKey

If the value of fKeys was (mkShift +mkControl +mkLeft), it would return True, otherwise it would return False.


IsNullComObject

See Also: FlexCOM Helper Functions, IsComObjectCreated

Purpose

Returns True if the passed variable or property is of type variant IDispatch* and is set to NULL. It will return False if the passed value is a non-NULL IDispatch* value.

Syntax

(IsNullComObject( {vComObject} ))

Where:

  • vComObject is a value of type variant

What it Does

This Boolean function returns True if the passed variable or property is of type variant IDispatch* and is set to NULL. It will return False if the passed value is a non-NULL IDispatch* value.

Use this function instead of attempting to use an IDispatch* variant in a comparative expression like (vComObject = 0). Such an expression would never work and would raise a runtime error.

The following example tests a variant variable using IsNullComObject to see if it is a Null IDispatch*.

Variant vMyVar

// ...

If (Not(IsNullComObject(vMyVar))) Begin

Move (NullComObject()) To vMyVar

End


IsNullRowID

See Also: RowId, RowId Helper Functions

Purpose

Determines if a RowId value is null.

Syntax

(IsNullRowId( {RowId} ))

Where:

  • {RowId} is a value of type RowId

Example

Function RefindLastRecord returns Boolean

RowId riRow

Boolean bFound

Get priLastRow to riRow

If (IsNullRowId(riRow)) begin

Send RecordDoesNotExist

End

Else Begin

Move (FindByRowId(Customer.File_Number, riRow)) to bFound

End

Function_return bFound

End_Function // RefindLastRecord

Notes

IsNullRowId returns true if the value of the RowId variable is null. This is the only way you can test if a RowId variable is "empty" (i.e., null).


IsSameRowID

See Also: RowId, RowId Helper Functions

Purpose

Used to determine if two RowId values are the same.

Syntax

(IsSameRowID( {RowId}, {RowId} ))

Where:

  • {RowId} is a value of type RowId

Example

Function RefindLastRecord returns Boolean

RowId riCustomer

Boolean bFound

Get priLastRow to riCustomer // the RowId record we want to refind

// only refind the record if the current record's RowId is different

If not (IsSameRowId(GetRowId(Customer.File_Number), riCustomer)) begin

Move (FindByRowID(Customer.File_Number, riCustomer)) to bFound

End

Function_Return bFound

End_Function // RefindLastRecord

Notes

IsSameRowID returns true if the two RowIDs passed are the same. This function can be used to determine if a row has changed. It can also be used to optimize row finding by not refinding a row if it is already loaded.


IsSameComObject

See Also: FlexCOM Helper Functions

Purpose

Returns True if the two parameters are of type variant and point to the same COM object.

Syntax

(IsSameComObject( {vComObject1 }, {vComObject2 } ))

Where:

  • vComObject1 is a value of type variant

  • vComObject2 is a value of type variant

What It Does

This Boolean function returns True if the two parameters are of type Variant and point to the same COM object.

Use this function in place of the expression (vComObject1 = vComObject2). Such an expression is illegal and would raise a runtime error.

The following example loops through a collection automation object and uses the IsSameComObject function to determine the index of the current object in the collection.

Handle hoTestNode

Variant vTestNode vCurrentNode

Integer iNode icNode iCurrent

Object oNodes is a cComafNodes // cComAutomationObject

End_Object

Send AttachActiveObject of oNodes

If (IsComObjectCreated(oNodes)) Begin

// Get IDispatch* of the current node

Get ComCurrentNode of oNodes To vCurrentNode

// Get the number of nodes in the collection

Get ComCount of oNodes To icNode

// iterate through the nodes collection

Move 1 To iNode

While ((iNode <= icNode))

// Get a IDispatch* to the i'th node

Get ComItem of oNodes iNode To vTestNode

// test If this is the current node

If (IsSameComObject(vCurrentNode, vTestNode))) Begin

Move iNode To iCurrent // store the index

Move icNode To iNode // jump out of the Loop

End

Increment iNode

Loop

End


Left

See Also: String Functions, Ltrim, Mid, Right

Purpose

Left returns the leftmost characters of a string up to a specified length.

Syntax

(Left( {string-value}, {length} ))

Where:

  • {string-value} is the string that characters will be extracted from

  • {length} is the number of characters from the left of {value} that are returned

What It Does

Left returns the first (leftmost) characters of {string-value} up to and including the character in Position {length}.

Move (Left(sName, 5)) To Customer.Firstname

Sample

This sample reverses the letters in a string.

Move "Joe Smith" To sName

Move (Pos (" ", sName)) To iPos

Move (Right (sName, Length (sName) - iPos) + ", " + Left (sName, iPos)) To sReversedName

Sample

This sample separates a string into words by separating character groups (words) before and after any space in the text.

Function SplitStringIntoWords String sText returns String[]

String sWord

String[] Words

Integer iWordCount iSpacePos

// Repeat as long as sText contains data

While (sText <> "")

// Find the first/next space

Move (Pos (" ", sText)) To iSpacePos

// If a space was found

If (iSpacePos > 0) Begin

// Take the left part

Move (Left (sText, iSpacePos - 1)) To sWord

// Move the remainder to the text variable

Move (Right (sText, Length (sText) - iSpacePos)) To sText

End

// If no more spaces are found

Else Begin

// Make word equal to the text

Move sText To sWord

// Empty text to stop the loop

Move "" To sText

End

move sWord to Words[iWordCount]

increment iWordCount

Loop

function_return Words

End_Function // SplitStringIntoWords

Procedure OnClick

String sText

String[] Words

Move "Split this text into words" To sText

get SplitStringIntoWords sText to Words

End_Procedure // OnClick

Notes

  • If the {length} parameter = 0, the Left function will return an empty string. If {length} is less than 0, the function will return the {string-value} parameter in its entirety. If {length} is greater than the number of characters in {string-value} the function returns {string-value} in its entirety.

  • If the {string-value} parameter is of type other than string, its value will be converted to a string for output.


Length

See Also: String Functions, String, String command

Purpose

Length returns the number of the characters in a string.

Syntax

(Length( {string-value} ))

What It Does

Length returns the number of characters in {string-value}, including leading and trailing spaces, if present.

String sMeasure

Integer iLength

Move " 2 4 6" To sMeasure

Move (Length(sMeasure)) To iLength

In this example, the length of string variable sMeasure (6) is moved to iLength

Notes

  • When a database field is passed to the length function the defined length of the field is returned rather than the number of characters that are stored there. This is because string-type database fields are padded with spaces to the full defined length of the field.


Log

See Also: Math Functions, Exp

Purpose

Log returns the natural logarithm of a value.

Syntax

(Log( {expression} ))

What It Does

The Log function returns the power to which the constant e (2.71828), the natural logarithm base, would have to be raised to equal the value of {expression}.

Real rRoot

Move (Log(10)) To rRoot

Notes

  • To calculate the natural antilogarithm of a number, use the Exp function.

  • To calculate the common (base 10) logarithm of a value, divide Log({expression} by Log(10).

Move (Log(45) / Log(10)) To rRoot

In this example, the common logarithm (1.65321) of 45 is output to the variable rRoot.

  • Log converts the {expression} parameter to a real value, and outputs a real value.


Low

See Also: Miscellaneous Functions, Hi, Integer

Purpose

The Low function returns the value of the lower 16 bits (right-most 2-bytes) of an integer value.

Syntax

(Low( {expression} ))

Where:

  • {expression} may be of any type except string. If it is not an integer, it will be converted to an unsigned integer first.

What It Does

Visual DataFlex integers have a storage capacity of 32 binary bits (4-bytes). With the hi and low functions, a single integer can be used to encode two 16-bit (2-byte) values each. The value of the lower 16-bits only of an integer can be retrieved with the low function.

Move (Low(iCoordinate)) To iColumn

Notes

  • The {expression} value is an unsigned integer, and may be in the range 0 to 4,294,967,294.

  • This function returns a value of type integer. If the {expression} parameter is not an integer, its value will be converted to an unsigned integer for use in this function. If the result of this function is moved to a variable of type other than integer, its value will be converted to the destination type.

  • To combine two positive integer values into a single integer for subsequent disassembly by hi and low, multiply the value assigned to hi by 65,536 and add it to the value assigned to low.

  • Certain properties in the Visual DataFlex class library (such as Size and Location) use complex integers for disassembly by the hi and low functions.


Lowercase

See Also: String Functions, Uppercase

Purpose

Lowercase returns a string with all its characters converted to lower case.

Syntax

(Lowercase( {string-value} ))

What It Does

Lowercase changes all capital letters (A..Z) in the {string-value} to lowercase, leaving other characters unchanged.

Move (Lowercase("AEIOU812")) To sTitle

In this example , the string "aeiou812" is moved to the variable sTitle.

Notes

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {string-value} is of type other than string, its value will be converted to a string for output.


Ltrim

See Also: String Functions, Left, Rtrim, Trim

Purpose

Ltrim returns a string with leading spaces removed.

Syntax

(Ltrim( {string-value} ))

What It Does

Ltrim removes all spaces to the left of the leftmost non-space character in the {string-value} parameter.

Showln "$" (Ltrim(" 18.45"))

In this example, the string "$18.45" is shown.

Showln (Ltrim(" Joe "))

In this example, the string "Joe " is shown.

Notes

  • When the minus (-) operator is used in a string expression, the both operands are trimmed without needing to use this function. The asterisk (*) operator does the same thing, but inserts a single space.

Move ("ab " – " bc") To sResult1

Move ("ab " * " bc") To sResult2

In the above examples "abbc" is moved to sResult1 and "ab bc" is moved to sResult2.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {string-value} is of type other than string, its value will be converted to a string for output.


MaxArray

See Also: Array Functions

Purpose

Returns index of array element with the highest (maximum) value.

Syntax

(MaxArray( {ArrayId} [, {ObjectId} , {MessageId} ])

Where:

  • {ArrayId} is the id of the array being checked. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare 2 array elements.

What it Does

MaxArray returns the index of the array element with the highest value, which is determined using either an internal sorting algorithm or one provided by the developer.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient sorting method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal sorting algorithms, simply do not pass the {ObjectId} and {MessageId} parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to sort an array of elements that are of a type that cannot be sorted using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom sorting function for the sorting process if a custom function is desired or required (for arrays of data types that cannot be sorted using the internal algorithms: struct, RowId, variant).

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

Retrieving the highest value from an array of strings:

This sample returns the index of the array element with the highest string value in a dynamic array of strings (sCustomers), then displays the index and the value of the associated array element to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

integer iMaxCustomer

// populate sCustomers with customer data

move "Smith, Janet" to sCustomers[0]

move "Rodriguez, Pedro" to sCustomers[1]

move "Smith, Judy" to sCustomers[2]

move "Jones, Fred" to sCustomers[3]

move "Anderson, Martin" to sCustomers[4]

move "Schmidt, Michael" to sCustomers[5]

move "Verne, Jacques" to sCustomers[6]

move "Ricci, Enrico" to sCustomers[7]

move "Sorensen, Karl" to sCustomers[8]

move "Garcia, Juan" to sCustomers[9]

// get max array index

move (MaxArray(sCustomers)) to iMaxCustomer

// display the max array index and that element's value

showln "Highest value: " (string(iMaxCustomer)) ": " (sCustomers[iMaxCustomer])

End_Procedure // OnClick

Example

Retrieving the highest value from an array of structs:

This sample declares a structured data type (tUSAddress), then declares an array of type tUSAddress of 5 elements. The first array (myAddresses) is populated with zip codes (since we are only sorting using zip codes, we are not filling the other struct members for this sample).

A custom comparison function is used to determine how array elements are sorted. Last, the index of the array element with the highest zip code value is displayed to the screen, along with the value of the element.

Struct tUSAddress

String Street

Integer ZipCode

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tUSAddress address1 tUSAddress address2 Returns Integer

integer iRetVal

if (address1.ZipCode > address2.ZipCod) ;

Function_Return (GT)

if (address1.ZipCode < address2.ZipCode) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

tUSAddress[5] myAddresses

integer iMaxIndex

// initialize address array

move 33186 to myAddresses[0].ZipCode

move 33177 to myAddresses[1].ZipCode

move 90210 to myAddresses[2].ZipCode

move 10245 to myAddresses[3].ZipCode

move 78610 to myAddresses[4].ZipCode

// get the max element's index

move (MaxArray(myAddresses, Self, get_MyComparison)) to iMaxIndex

// display highest element index and value

showLn "The array element with the highest zip code is element " ;

iMaxIndex " with zip code " myAddresses[iMaxIndex].zipCode

End_Procedure // OnClick

Example

Retrieving the highest value from a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Smith Verne Ricci

The maximum value in the first "row" (row 0) of the array is determined and displayed, then the maximum value in the second "row" (row 1).

Procedure OnClick

string[2][4] sCustomers

string sSearchTerm

integer iCount0 iCount1

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

move (MaxArray(sCustomers[0])) to iCount0

showln "Max element value in first row of array: " ;

(string(iCount0)) " (" sCustomers[0][iCount0] ")"

move (MaxArray(sCustomers[1])) to iCount1

showln "Max element value in second row of array: " ;

(string(iCount1)) " (" sCustomers[1][iCount1] ")"

End_Procedure // OnClick


MemCompare

See Also: Memory Management Functions

Purpose

Compares the contents of two memory blocks.

Syntax

(MemCompare( {pMemBlock1}, {pMemBlock2}, {iBytes} ))

Where:

  • {pMemBlock1} and {pMemBlock2} are pointers to memory blocks (address variables)

  • {iBytes} is the number of bytes to compare.

What It Does

MemCompare returns zero if the two memory blocks are equal and nonzero if the memory blocks are unequal. Use of MemCompare with invalid parameters will likely crash your program.

Example

Function AreBlocksEqual Address a1 Address a2 Integer iBytes Returns Boolean

Boolean bRetVal

Move (MemCompare(a1, a2, iBytes)) to bRetVal

If (bRetVal = 0);

Function_Return 1

Else;

Function_Return 0

End_Function


MemCopy

See Also: Memory Management Functions

Purpose

Copies data from one address to another.

Syntax

(MemCopy( {pDest}, {pSource}, {iBytesToCopy} ))

Where:

  • {pDest} is an address variable that is the destination memory address,

  • {pSource} is an address variable that is the source memory address

  • {iBytesToCopy} is the number of bytes to copy

What It Does

MemCopy copies a memory block from one address to another. You must specify valid addresses for pDest and pSource. They must be allocated before you use them. Improper use of the MemCopy function can cause your program to crash.

Example

Move (MemCopy(pDest, pSource, iNumberOfBytesInRange)) to bOK

Example

This sample determines whether the MemCopy succeeded or not.

Move (Alloc (iLength)) To pDestination

Move (MemCopy (pDestination, pSource, iLength)) To bOk

If (Not (bOk)) Begin

Error DFERR_PROGRAM "The MemCopy function failed"

End


MemSet

See Also: Memory Management Functions

Purpose

Stores a given byte value in a memory block of a given size.

Syntax

(MemSet( {pBlock}, {iValue}, {iBytesToSet} ))

Where:

  • {pBlock} is an address variable that is the memory address of the buffer whose value is to be set

  • {iValue} is the character value to set (an integer)

  • {iBytesToSet} is the number of bytes to set

What It Does

The MemSet function is used to set a block of bytes to the same character value. It can be used, for example, to initialize blocks of data.

Example

Move (MemSet(pMemory, (ASCII('A')), 100)) to bOK // Move the letter 'A' to every byte in the memory buffer.


Message_Box

See Also: Dialog and Message Box Functions, Info_Box, Stop_Box, YesNo_Box, YesNoCancel_Box

Purpose

Displays a generic message dialog box.

Syntax

Use Windows.pkg

(Message_Box( {sMessage}, {sCaption}, {Buttons}, {Options} ))

Where:

  • {sMessage} is a string containing the information message to be shown. A carriage-return/linefeed can be placed in the message string by the inclusion of \n in the text.

  • {sCaption} specifies the content of the caption bar.

  • {Buttons} specifies the list of buttons to be shown on the message box. The table below lists the types of buttons that can be selected.

Button Constant | Description
MB_ABORTRETRYIGNORE | Abort, Retry and Ignore buttons
MB_HELP | Help button
MB_OK | OK button
MB_OKCANCEL | OK and Cancel buttons
MB_RETRYCANCEL | Retry and Cancel buttons
MB_YESNOCANCEL | Yes, No and Cancel buttons
MB_YESNO | Yes and No buttons

  • {Options} specifies additional options for configuring the message box. These options are grouped by type.

Icon Constant | Description
MB_ICONHAND | A stop-sign icon appears in the message box.
MB_ICONQUESTION | A question-mark icon appears in the message box.
MB_ICONEXCLAMATION | An exclamation-point icon appears in the message box.
MB_ICONASTERISK | An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONWARNING | An exclamation-point icon appears in the message box
MB_ICONERROR | A stop-sign icon appears in the message box.
MB_ICONINFORMATION | An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONSTOP | A stop-sign icon appears in the message box.

Default Button Constant | Description
MB_DEFBUTTON1 | The first button is the default button. This is the default.
MB_DEFBUTTON2 | The second button is the default button.
MB_DEFBUTTON3 | The third button is the default button.
MB_DEFBUTTON4 | The fourth button is the default button.

Modal Type Constant | Description
MB_APPLMODAL | The user must respond to the message box before continuing. MB_APPLMODAL is the default.
MB_SYSTEMMODAL | Same as MB_APPLMODAL except that the message box is the topmost window.

Other Constants | Description
MB_RIGHT | The message text is right-justified.
MB_SETFOREGROUND | The message box becomes the foreground window.
MB_TOPMOST | The message box is created with the Topmost window style.

You can combine one option from each type by using an expression where the options are Ior'ed. See the examples section below for more information.

What It Does

Message_Box is used to pop a message box and obtain the user's response. The message box contains a message and title, plus any combination of predefined icons and push buttons.

The message box function returns one of the following integer constants.

Return Type Constants | Description
MBR_OK | The OK button was clicked.
MBR_CANCEL | The Cancel button was clicked.
MBR_ABORT | The Abort button was clicked.
MBR_RETRY | The Retry button was clicked.
MBR_IGNORE | The Ignore button was clicked.
MBR_YES | The Yes button was clicked.
MBR_NO | The No button was clicked.

Examples

Move (Message_Box("This box displays a Help button!", "Example", ;

MB_OKCANCEL IOR MB_HELP, ;

MB_ICONWARNING)) to eResponse

The above example would display the following message box…

Use Windows.pkg

Procedure Example

Integer eResponse

Move (Message_Box("Delete this file?", "Example", MB_YESNO, ;

MB_ICONQUESTION IOR MB_DEFBUTTON2)) to eResponse

If (eResponse = MBR_YES) Begin

Send DeleteFile

End

End_Procedure

The above example displays the following message box…

In this example, the default button is the "No" button (the second button). After the message box is closed, the returned value is tested to see which button was pressed.

Notes

If the user types Ctrl+C in the message box, the text of the message is copied to the clipboard.

To add a help button to other buttons in a message dialog, use an expression in the {Buttons} parameter which Ior's the help button with the other selected buttons. For example (MB_OKCANCEL IOR MB_HELP).

When the user clicks the Help button or presses F1 from a message box, windows sends a WM_HELP message to the application.


Mid

See Also: String Functions, Left, Pos, Right

Purpose

Mid returns a substring of specified length and position from the value of the input string.

Syntax

(Mid( {string-value}, {length}, {position} ))

Where:

  • {string-value} is the string that the substring is extracted from

  • {length} is the length of the substring that is returned

  • {position} is the number of characters from the left of {string-value} marking the beginning of the substring. The {position} of the first character (leftmost) in {string-value} is 1 (position is 1-based).

What It Does

Move (Mid("Data Access Corporation", 3, 6)) To sWord

In this example, the characters "Acc" are moved to the variable sWord.

Notes

  • If {length} is less than 1, the function will return an empty string. If {length} is greater than the length of {string-value} to the right of {position}, all of {string-value} to the right of {position} will be returned. If {position} is less than 1, the function will return an empty string. If {position} is greater than the length of {string-value}, the function will return an empty string.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {string-value} is of type other than string, its value will be converted to a string for output.


MinArray

See Also: Array Functions

Purpose

Returns index of array element with the lowest (minimum) value.

Syntax

(MinArray( {ArrayId} [, {ObjectId} , {MessageId} ] )

Where:

  • {ArrayId} is the id of the array being checked. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare 2 array elements.

What it Does

MinArray returns the index of the array element with the lowest value, which is determined using either an internal sorting algorithm or one provided by the developer.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient sorting method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal sorting algorithms, simply do not pass the {ObjectId} and {MessageId} parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to sort an array of elements that are of a type that cannot be sorted using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom sorting function for the sorting process if a custom function is desired or required (for arrays of data types that cannot be sorted using the internal algorithms: struct, RowId, variant).

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

Retrieving the lowest value from an array of strings:

This sample returns the index of the array element with the lowest string value in a dynamic array of strings (sCustomers), then displays the index and the value of the associated array element to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

integer iMinCustomer

// populate sCustomers with customer data

move "Smith, Janet" to sCustomers[0]

move "Rodriguez, Pedro" to sCustomers[1]

move "Smith, Judy" to sCustomers[2]

move "Jones, Fred" to sCustomers[3]

move "Anderson, Martin" to sCustomers[4]

move "Schmidt, Michael" to sCustomers[5]

move "Verne, Jacques" to sCustomers[6]

move "Ricci, Enrico" to sCustomers[7]

move "Sorensen, Karl" to sCustomers[8]

move "Garcia, Juan" to sCustomers[9]

// get min array index

move (MinArray(sCustomers)) to iMinCustomer

// display the Min array index and that element's value

showln "Lowest value: " (string(iMinCustomer)) ": " (sCustomers[iMinCustomer])

End_Procedure // OnClick

Example

Retrieving the lowest value from an array of structs:

This sample declares a structured data type (tUSAddress), then declares an array of type tUSAddress of 5 elements. The first array (myAddresses) is populated with zip codes (since we are only sorting using zip codes, we are not filling the other struct members for this sample).

A custom comparison function is used to determine how array elements are sorted. Last, the index of the array element with the lowest zip code value is displayed to the screen, along with the value of the element.

Struct tUSAddress

String Street

Integer ZipCode

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tUSAddress address1 tUSAddress address2 Returns Integer

integer iRetVal

if (address1.ZipCode > address2.ZipCod) ;

Function_Return (GT)

if (address1.ZipCode < address2.ZipCode) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

tUSAddress[5] myAddresses

integer iMinIndex

// initialize address array

move 33186 to myAddresses[0].ZipCode

move 33177 to myAddresses[1].ZipCode

move 90210 to myAddresses[2].ZipCode

move 10245 to myAddresses[3].ZipCode

move 78610 to myAddresses[4].ZipCode

// get the min element's index

move (MinArray(myAddresses, Self, get_MyComparison)) to iMinIndex

// display lowest element index and value

showLn "The array element with the lowest zip code is element " iMinIndex " with zip code " myAddresses[iMinIndex].zipCode

End_Procedure // OnClick

Example

Retrieving the lowest value from a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Smith Verne Ricci

The minimum value in the first "row" (row 0) of the array is determined and displayed, then the minimum value in the second "row" (row 1).

Procedure OnClick

string[2][4] sCustomers

string sSearchTerm

integer iCount0 iCount1

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

move (MinArray(sCustomers[0])) to iCount0

showln "Min element value in first row of array: " ;

(string(iCount0)) " (" sCustomers[0][iCount0] ")"

move (MinArray(sCustomers[1])) to iCount1

showln "Min element value in second row of array: " ;

(string(iCount1)) " (" sCustomers[1][iCount1] ")"

End_Procedure // OnClick


Mod

See Also: Math Functions, Integer, DateGetDayOfWeek

Purpose

Mod returns the remainder from division of one integer value by another.

Syntax

(Mod( {dividend}, {divisor} ))

Where:

  • {dividend} is the integer value to divide

  • {divisor} is the integer value to divide {dividend} by

What It Does

This function is also called modulo division.

Example

Show (Integer(iElapsedTime /60))":" (Mod(iElapsedTime, 60))

In this example, a string is shown made up of the value of iElapsedTime divided by 60, a colon (:), and the modulo 60 of the same value. If iElapsedTime were a number of minutes, the display would be hours:minutes.

Example

integer i

for i from 1 to 100

if (mod(i,2)=0) showln "The number " i " is even"

loop

In this example, the mod function is used to determine whether the numbers from 1 to 100 are even or odd. If the expression mod(i,2) returns 0, there is no remainder of the value of i being divided by 2, thus the value of i must be even.

Example

Procedure Test

integer iDay

date dToday

sysdate dToday

move (mod(dToday,7)) to iDay

if (iDay = "0") move "Friday" to sWeekday
else if (iDay = "1") move "Saturday" to sWeekday
else if (iDay = "2") move "Sunday" to sWeekday
else if (iDay = "3") move "Monday" to sWeekday
else if (iDay = "4") move "Tuesday" to sWeekday
else if (iDay = "5") move "Wednesday" to sWeekday
else if (iDay = "6") move "Thursday" to sWeekday

showln "Today is " sWeekday

End_Procedure // Test

In this example, the mod function is used to determine and display the day of the week. The Julian date for the current date, retrieved to dToday using the sysdate4 function, is divided by 7. If the remainder of this calculation is 0, the day of the week is Friday, if the remainder is 1, the day of the week is Saturday, etc.

Note: Normally, you would use the built-in DateGetDayOfWeek function to retrieve the weekday associated with a given date.

Notes

  • This function returns a value of type integer. If the {dividend} and {divisor} parameters are not integers, they will be converted to that type for use in this function. If the result of this function is moved to a variable of type other than integer, its value will be converted to the destination type.

  • Mod returns a value having the same sign as the quotient of {dividend} divided by {divisor} would have. Mod(3, -2) = -1.


Not Function

Not

See Also: AND operator, OR operator, if command, if function

Purpose

To return the logical inverse of a value.

Syntax

(not( {variable} ))

or

(not( {expression} ))

or

(not( {value} ))

What It Does

Not returns 0 if variable is true or has a non-zero or non-blank value, and 1 if it is false or has a value of 0.

if ((not(mod(iYear,4))) and (mod(iYear,100)) ) begin

// code for leap year processing

end

In this example, the block of code inside begin and end is executed when the modulo 4 of variable iYear is zero (false) and the modulo 100 of iYear is not zero (true).

Example

Function IsSingle returns Boolean

Boolean bIsMarried bIsSingle

if (not(bIsMarried)) ;

move True to bIsSingle

else ;

move False to bIsSingle

function_return bIsSingle

End_Procedure // Test

Notes

  • If {value} is other than a logical expression or of type integer, this function converts its value to integer first.


Number

See Also: Type Conversion Functions, Integer, Real, Round, String

Purpose

The Number function returns a value of type number from an input of another type.

Syntax

(Number( {expression} ))

What It Does

Number eliminates the portion to the right of the eighth digit after the decimal point from the value of a variable.

Move (Number(3.14159265359)) To nPI

In this example, the value 3.14159265 is moved to the variable nPI. The digits more than eight places to the right of the decimal point are truncated.

The Number function does not change the type of its {expression} parameter. It only affects its precision.

When the absolute value of {expression} exceeds the maximum range of a Visual DataFlex Number (+/-99,999,999,999,999.99999999), the leading digits in the value are truncated, and no error is declared.

Notes

  • When used inside an expression, number affects the precision of the overall expression, unless a function converting to a lower order of precision contains the number expression.

Integer iMean

Number nResult

Move (3.14 * Number(iMean)) To nResult

This example would output 3.14 times the value of the integer variable iMean to the number variable nResult in the full precision of numbers.

  • Database fields in DataFlex that are capable of holding quantities are all of type number. There is no field data type to hold floating-point (real) values. If you move a real value to a field, or number-type window or variable, the value will be converted to a number automatically.


Number_Default_Mask

See Also: Miscellaneous Functions, Field_Number_Default_Mask, Field Masks

Purpose

Returns a mask for formatting number stings.

Syntax

Use GlobalFunctionsProcedures.pkg

(Number_Default_Mask( {iDigits}, {iPoints}, {sMask} ))

Where:

  • {iDigits} Is the maximum number of digits expects to be formatted by the mask

  • {iPoints} Is the number of decimal points to be formatted by the mask

  • {sMask} must be a valid Visual DataFlex numeric mask

What It Does

Number_Default_Mask tailors the passed a template mask {sMask} to the passed number of digits {iDigits} and decimal points {rPoints}.

Number_Default_Mask returns a Visual DataFlex mask string.

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Example

String sMask

Move (Number_Default_Mask(4, 4, "$,*;($,*)")) to sMask

Send Info_Box ("Mask = " + sMask) "Example"

End_Procedure

This example displays the mask string "$,###0.0000;($,###0.0000)"


NullComObject()

See Also: FlexCOM Helper Functions

Purpose

Returns a NULL value of variant type IDispatch*.

Syntax

(NullComObject())

What it Does

This function returns a NULL value of variant type IDispatch*. You can use this function to release a reference to a COM object that is stored in a variant property or variable, or to initialize a variant property or variable.

// initialize Property with a proper 0

Property Variant pvMyComObject (NullComObject()))

// Move null to vVar and dispose of Object If one existed.

Move (NullComObject())) to vVar

// moves null to Property an dispose of Object.

Set pvMyCombject to (NullComObject())


NullRowID

See Also: RowId, RowId Helper Functions

Purpose

Sets a RowId variable to Null.

Syntax

(NullRowID())

What it Does

NullRowId is used to "clear" a RowId variable. It moves a null value into a RowId variable.

Example

Function RefindLastRecord returns Boolean

RowId riCustomer

Boolean bFound

Get priLastRow to riCustomer

If (IsNullRowId(riCustomer)) begin

Send RecordDoesNotExist

End

Else Begin

Move (FindByRowId(Customer.File_Number, riCustomer)) to bFound

End

// after operation, set the RowId to null and store it in a property

Move (NullRowId()) to riCustomer

Set priLastRowId to riCustomer

Function_return bFound

End_Function // RefindLastRecord


OemToUtf8Buffer

See Also: Miscellaneous Functions, Utf8ToOemBuffer, Free

Purpose

Converts an OEM string to UTF-8.

Syntax

Use CharTranslate.pkg

(OemToUtf8Buffer( {pOemBuf}, {iLen} ))

Where:

  • {pOemBuf} is a pointer to the string buffer to be converted

  • {iLen} is the length, in bytes, of the string pointed to by {pOemBuf}

What It Does

OemToUtf8Buffer converts a string of OEM characters to UTF8 where…

Returns a pointer to a newly allocated string buffer containing the converted text.

Examples

// Translate data. pass: Data and translation mode.

// returns pointer to new translated data 0 if no translate needed.

// Passed data is not changed.

// eXlt can be: xtUtf8toOem, xtOemtoUtf8 and xtNoTranslate

Function TranslateData integer eXlt ;

address aData ;

integer iDataLen ;

returns address

address aDataXlt

Case Begin

case (eXlt = xtUtf8toOem)

Move (Utf8toOemBuffer(aData, iDataLen)) to aDataXlt

case Break

case (eXlt = xtOemtoUtf8)

Move (OemToUtf8Buffer(aData, iDataLen)) to aDataXlt

case Break

case else

Move 0 to aDataXlt

Case End

Function_Return aDataXlt

End_Function

Notes

OemToUtf8Buffer will allocate a new block of memory to store the converted string. A pointer to this memory is returned by the function. You must use Free to de-allocate this memory when it is no longer required. Failure to do this will cause a memory leak in your application.


Overstrike

See Also: String Functions, Insert, Pos, Remove, Replace

Purpose

Overstrike returns a host string which has some or all of its characters replaced by a new string at a specified position in the host string.

Syntax

(Overstrike( {new-string}, {host-string}, {position} ))

Where:

  • {new-string} is the string that will be merged into the {host-string}

  • {host-string} is the string that {new-string} will be merged into

  • {position} is the number of characters from the left of {host-string} that the {new-string} will be inserted. The {position} parameter is 1-based (position 1 represents the first character in the host string).

What It Does

Overstrike replaces the characters in {host-string} starting at {position} with the value of {new-string}.

Move "Fish not Chips" To sMenu

Showln (Overstrike("and", sMenu, 6))

In this example, the string "Fish and Chips" is shown.

The overstrike function resembles the mode of word processors known as overtype.

Notes

  • If the {position} parameter is less than 1, characters on the left of {new-string} are truncated to the extent that they lie to the left of position 1 in {host-string}. Provided {new-string} is long enough, its right-lying characters will overstrike those of {host-string}.

Show (Overstrike("123456789", "Begin hostString", -3))

The first four characters of 123456789 will be truncated, and the next five will overwrite the first five characters of "Begin hostString". This example would show "56789 hostString".

  • If {position} is greater than the length of {host-string}, {host-string} will be padded with blanks in order to append {new-string} to the position named in the {position} parameter.

Show (Overstrike("123456789", "automaton", 14))

This example would show "automaton ····123456789", where · represents a space.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the type of the destination variable.

  • If the {new-string} or {host-string} parameters are of type other than string, their value will be converted to a string for output.


Pad

See Also: String Functions, Append, Center, Left, Length, Trim

Purpose

Pad returns a string of specified length with spaces added to, or characters truncated from, the right of the input string as necessary.

Syntax

(Pad( {string-value}, {length} ))

Where:

  • {string-value} is the source string to be padded with spaces

  • {length} is the length to which {string-value} will be padded

What It Does

Pad adds spaces to the right of {string-value} until the length of the string is equal to {length}.

Procedure Test

string sFirstName sLastName

Move "John" To sFirstName

Move "Smith" To sLastName

Showln (Pad(sFirstName, 10)) sLastName

End_Procedure // Test

In the above example the string "John······Smith" would be shown, where · represents a space character.

Notes

  • If {length} is less than the length of {string-value}, this function returns the value of type string truncated on the right to {length}, identically to the way the Left function works.

  • If {length} is 0, the function returns an empty string.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {string-value} is of type other than string, its value will be converted to a string for output.


Pos

See Also: String Functions, Left, Length, Mid, Right

Purpose

Pos returns the ordinal position of a substring in a host string.

Syntax

(Pos( {sub-string}, {host-string} ))

Where:

  • {sub-string} is the string value that pos searches for in {host-string}

  • {host-string} is the string value pos searches for an occurrence of {sub-string} in

What It Does

Pos finds the first occurrence of {sub-string} in {host-string} and returns the position of the first character of {sub-string} as it stands in {host-string}.

If (Pos("XXX", sTitle)) Send DoAddXRated

In this example, if the expression (Pos("XXX",sTitle)) returns any number greater than zero, it means that sTitle contains the string "XXX" somewhere in it. If this is the case, the method DoAddXRated is called.

Sample

This sample separates a string into words by separating character groups (words) before and after any space in the text.

Function SplitStringIntoWords String sText returns String[]

String sWord

String[] Words

Integer iWordCount iSpacePos

// Repeat as long as sText contains data

While (sText <> "")

// Find the first/next space

Move (Pos (" ", sText)) To iSpacePos

// If a space was found

If (iSpacePos > 0) Begin

// Take the left part

Move (Left (sText, iSpacePos - 1)) To sWord

// Move the remainder to the text variable

Move (Right (sText, Length (sText) - iSpacePos)) To sText

End

// If no more spaces are found

Else Begin

// Make word equal to the text

Move sText To sWord

// Empty text to stop the loop

Move "" To sText

End

move sWord to Words[iWordCount]

increment iWordCount

Loop

function_return Words

End_Function // SplitStringIntoWords

Procedure OnClick

String sText

String[] Words

Move "Split this text into words" To sText

get SplitStringIntoWords sText to Words

End_Procedure // OnClick

Notes

  • If {sub-string} is not found in {host-string}, this function returns zero.

  • This function returns a value of type integer. If the result of this function is moved to a variable of type other than integer, its value is converted to the destination type.

  • If {sub-string} or {host-string} are of type other than string, its value will be converted to a string for output.


R_From_RGB

See Also: Graphics Functions, Understanding RGB Colors, B_From_RGB, G_From_RGB, RGB

Purpose

Returns a byte value representing the Red color intensity value of an RGB integer.

Syntax

Use RGB.pkg

(R_From_RGB( {rgbColor} ))

Where:

  • {rgbColor} is an RGB color value

Examples

Use RGB.pkg

Procedure OnClick

Integer rgbColor

Integer iRed iGreen iBlue

Get Value of oColor to rgbColor

Set TextColor of oText to rgbColor

Move (R_From_RGB(rgbColor)) to iRed

Move (G_From_RGB(rgbColor)) to iGreen

Move (B_From_RGB(rgbColor)) to iBlue

Set Value of oText to ("Red = " + string(iRed) + ", " + ;

"Green = " + string(iGreen) + ", " + ;

"Blue = " + string(iBlue))

End_Procedure // OnClick


Random

See Also: Math Functions

Purpose

Random returns a random number between zero and a specified upper limit.

Syntax

(Random( {limit} ))

Where:

  • {limit} determines the upper limit of the generated random number

What It Does

Random returns a randomly-generated integer whose absolute value is between zero and {limit}

Move (Random(10000000)) To iNumberToDial

In this example, a random number from zero to 9,999,999 is moved to the variable iNumberToDial.

Notes

  • The Random function returns only values having the same sign as {limit}. If {limit} is negative, the returned value will always be negative.

  • This function returns a value of type integer. If {limit} is not an integer, its value will be converted to that type for use in this function. If the result of this function is moved to a variable of type other than integer, its value will be converted to the destination type.


Real

See Also: Type Conversion Functions, Integer, Number, Round, String

Purpose

The Real function returns a value of type real from a source of another data type.

Syntax

(Real( {expression} ))

What It Does

Real returns floating point (real) values from sources of other types.

Procedure Test

Number nSide

Real rArea

Move 6.567 To nSide

Move (Real(nSide ^ 2)) To rArea

End_Procedure // Test

In this example, the value of number variable nSide is squared and moved to the real variable rArea in floating-point precision.

Real does not change the type of any value. It only affects the precision to which an expression is evaluated.

Notes

  • When used inside an expression, real affects the precision of the overall expression, unless a function converting to a lower order of precision contains the real expression.

Number nSum nPopulation

Real rMean

Move (Real(nSum / nPopulation)) To rMean

This example would output the quotient of the nSum divided by nPopulation to the real variable rMean in full floating point precision.


ReAlloc

See Also: Memory Management Functions

Purpose

Changes the size of a block of memory.

Syntax

Realloc( {aPointer}, {iNewSize} )

Where:

  • {aPointer} is a valid pointer (allocated on the process heap using Alloc)

  • {iNewSize} is the new desired size in bytes

What It Does

Realloc changes the size of the given memory block, aPointer, reallocating it to the size specified in iNewSize. The return value is either a valid memory address (meaning it worked) or 0, in case of failure.

Example

Move (Realloc(pMemory, 10000)) To pNewMemoryBlock

if (pNewMemoryBloce <> 0) ...


Remove

See Also: String Functions, Mid, Overstrike, Replace

Purpose

Remove returns a string value consisting of the value of the input string with a specified number of characters removed from a specified location in the string.

Syntax

(Remove( {host-string}, {position}, {length} ))

Where:

  • {host-string} is the string value to remove characters from

  • {position} is an integer value indicating the starting position in {host-string} to remove characters

  • {length} is the number of characters to remove from {host-string}

What It Does

Remove returns the value of {host-string} with {length} characters removed, starting at {position}.

Move "This is the the end" To sLine

Move (Remove(sLine, 9, 4)) To sLine

In this example, the Remove function removes the first occurrence of the word "the" from sLine.

Notes

  • If {length} is less than 1, the function will return the value of {host-string} unchanged.

  • If {length} is greater than the length of {host-string} minus {position}, then the part of the {host-string} lying to the left of {position} will be returned.

  • If {position} is less than 1, it will be considered 1. If {position} is greater than the length of {host-string}, the function will return the value of {host-string} intact.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {host-string} is of type other than string, its value will be converted to a string for output.


RemoveBitValue

See Also: Miscellaneous Functions, AddBitValue, IsFlagIn , IAND operator, IOR operator

Purpose

Zeros (clears) the bit pattern of one integer in another.

Syntax

Use GlobalFunctionsProcedures.pkg

(RemoveBitValue( {iBitValue}, {iSource} ))

Where:

  • {iBitValue} is a single binary digit to clear in {iSource}

  • {iSource} is the integer value to clear binary digits in using {iBitValue}

What It Does

RemoveBitValue compares the binary digits of two integers {iBitValue} and {iSource}. An integer value is returned where for the binary digit in (iBitValue} = 1, the corresponding digit in {iSource} is set to 0.

For example RemoveBitValue(16, 2704) = 2688

We can see this by inspecting the binary values of each integer…

1010 1001 0000 = 2704

0000 0001 0000 = 16

1010 1000 0000 = 2688

If {iBitValue} has more than one binary digit = 1, the then no operation is performed and the value returned = {iSource}. Thus RemoveBitValue is only to be used for clearing a single binary digit in {iSource}.

For example, RemoveBitValue(255, 2704) = 2704

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Test

Integer iResult

Move (RemoveBitValue(16, 2704)) to iResult

Send Info_Box ("Result = " + string(iResult)) "Test"

End_Procedure

Notes

RemoveBitValue is useful for binary encoding information into a single integer value.


Repeat

See Also: String Functions, Append, Character, Length, String, Set_Argument_Size

Purpose

Repeat returns a string made up of a specified number of repetitions of the input string.

Syntax

(Repeat( {string-value}, {count} ))

Where:

  • {string-value} is the string value to repeat

  • {count} is an integer value indicating the number of times to repeat {string-value}

What It Does

Repeat returns {string-value} appended together {count} times.

Showln (Repeat("Void if altered ", 5))

In this example, the string "Void if altered " is shown 5-times.

Notes

  • If {string-value} is of type other than string, its value will be converted to a string for output.

  • If {count} is negative, {string-value} will be repeated until it is as large as possible, and still less than the maximum allowable size of a string expression.


Replace

See Also: String Functions, Replaces

Purpose

Replace returns a string with the first occurrence of a specified substring in a host string replaced with a new substring.

Syntax

(Replace( {old-substring}, {host-string}, {new-substring} ))

Where:

  • {old-substring} is the substring of {host-string} to replace

  • {host-string} is the string value to make the replacement in

  • {new-substring} is the string value to replace {old-substring} with

What It Does

Replace finds the first occurrence of {old-substring} in the {host-string} and replaces it with the value of {new-substring}.

Procedure Test

String sSentence

Move "We will be in town for two weeks." To sSentence

Showln (Replace("two weeks", sSentence, "a fortnight"))

End_Procedure // Test

In this example, the value of the variable sSentence will be changed from "We will be in town for two weeks." to "We will be in town for a fortnight."

The first occurrence of a substring may be removed by replacing it with "" (empty string).

Notes

  • When {old-substring} is not found in {host-string}, the value of {host-string} is returned unchanged.

  • If {host-string} is of type other than string, its value will be converted to a string for output.


Replaces

See Also: String Functions, Replace

Purpose

Replace returns a string with every occurrence of a specified substring in a host string replaced with a new substring.

Syntax

(Replaces( {old-substring}, {host-string}, {new-substring} ))

Where:

  • {old-substring} is the substring of {host-string} to replace

  • {host-string} is the string value to make the replacement in

  • {new-substring} is the string value to replace {old-substring} with

What It Does

Replaces finds every occurrence of {old-substring} in the {host-string} and replaces them with the value of {new-substring}.

Procedure Test

String sSentence

Move "I have three eyes, three ears, three arms and three legs." to sSentence

Showln (Replaces("three", sSentence, "two"))

End_Procedure // Test

In this example, the value of the variable sSentence will be changed from "I have three eyes, three ears, three arms and three legs." to "I have two eyes, two ears, two arms and two legs."

Every occurrence of a substring may be removed by replacing it with "" (empty string).

Notes

  • When {old-substring} is not found in {host-string}, the value of {host-string} is returned unchanged.

  • If {host-string} is of type other than string, its value will be converted to a string for output.

  • Iterations are not supported. For example, replacing two spaces (" ") in a string with one will work, but occurrences of two spaces in the resulting string will not be replaced again.

    For example:

Move "This is a nice example" To sData // Contains three spaces

Move (Replaces (" ", sData, " ")) To sData // Contains two spaces

Showln (Pos (' ', sData)) // Shows the value of 8 which is the position of a double space

Can be solved by:

Move "This is a nice example" To sData // Contains three spaces

While (Pos (' ', sData) > 0) // Test for two spaces

Move (Replaces (" ", sData, " ")) To sData // Contains two spaces on first round and 1 on second

Loop

Showln (Pos (' ', sData)) // Shows the value of 0 which indicates not found


ResizeArray

See Also: SizeOfArray, Array Functions

Purpose

The ResizeArray function returns a new array that is a copy of the specified array and resized accordingly.

Syntax

(ResizeArray( {ArrayId}, {iArraySize} [, {assignVal} ] ))

Where:

  • {ArrayId} is the id of the array being resized.

  • {iArraySize} is the desired number of array elements.

  • {assignVal} is the value that will be assigned to each newly created array element if iArraySize is larger than the current member count.

What it Does

Specifying a size that is larger than the current member count will append n elements to the end of the array, where n is the difference between the new and current (prior to resizing) number of elements. The new elements are initialized to the array type's null value. This is useful for preparing an array for many insertions (quickly and efficiently expanding to a specified size).

Specifying a smaller size than the current size of the specified array removes n elements from the end, effectively shrinking the array down to the specified size. Elements that were above the new array size are erased. To erase all elements of the array, simply specify a size of zero.

Examples

Procedure Test

Integer[] iValues

Integer iCount icCount

Move (ResizeArray(iValues, 100)) to iValues // creates 100 array elements

Move (SizeOfArray(iValues)) to icCount

For iCount from 0 to (icCount – 1)

Move iCount to iValues[iCount] // move value to each element

Loop

Move (ResizeArray(iValues, 0)) to iValues // clears the array

End_Procedure // Test

The next example demonstrates how to resize the second dimension in a jagged array:

Procedure Test

Integer[][] iJaggedRows // declare a jagged array

Integer iCount

// create 10 items in row 0

for iCount from 0 to 9

Move iCount to iJaggedRows[0][iCount]

loop

// now resize row 0 to only contain 5 elements.

Move (ResizeArray(iJaggedRows [0], 5)) to iJaggedRows [0]

End_Procedure // Test

The important thing to notice in this example is how the return value of the ResizeArray function is moved to the first row of iJaggedRows i.e. iJaggedRows[0].

Example

This sample a dynamic array of integers and assigns the value 3 to the first 5 array elements. When ResizeArray is called, it resizes the array to 10 elements and assigns the value 7 to the 5 newly created array elements.

// fires when the button is clicked

Procedure OnClick

integer[] iValues

integer i iArraySize

for i from 0 to 4

move 3 to iValues[i]

loop

move (ResizeArray(iValues, 10, 7)) to iValues

// display array values

move (SizeOfArray(iValues)) to iArraySize

for i from 0 to (iArraySize-1)

showln iValues[i]

loop

End_Procedure // OnClick

Notes

  • Static arrays cannot be resized.

  • Only the first (left-most) dimension of a dynamic rectangular array can be resized, whereas any dimension of a jagged array can be resized.

  • It is not necessary to use ResizeArray to create new elements of a dynamic array, since Visual DataFlex will create the elements as needed. However, if you are creating a large array it can be more efficient to create array elements in blocks since adding new members may require the entire array to be moved in memory.

  • Attempting to reference an array element that is beyond the current size of the array will result in error 4509 "Reference Array Index Out Of Bounds".


ReverseArray

See Also: Array Functions

Purpose

Returns array with elements in reverse order of original array.

Syntax

(ReverseArray( {ArrayId} ))

Where:

  • {ArrayId} is the id of the array being sorted. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

What it Does

ReverseArray reverses the order of the elements in an array.

Example

This sample reverses a dynamic array of integers (ints1) and places the result into array ints2.

// fires when the button is clicked

Procedure OnClick

integer[][] ints1 ints2

// add some code to populate ints1 array

// :

// reverse the array

move (ReverseArray(ints1)) to ints2

End_Procedure // OnClick

Example

This sample reverses an array of 10 strings (sCustomers), then displays the reversed array elements to the screen.

// fires when the button is clicked

Procedure OnClick

string[10] sCustomers

integer i iArraySize

// populate array

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

move "Ricci" to sCustomers[7]

move "Sorensen" to sCustomers[8]

move "Garcia" to sCustomers[9]

// reverse the array

move (ReverseArray(sCustomers)) to sCustomers

// display the elements in the reversed array

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Reversing a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Schmidt Verne Ricci

The first "row" (row 0) of the array is then sorted and placed in row 0 of the resulting array (in this sample, the results of SortArray are placed back in the original array), resulting in this array:

Jones Scott Rodriguez Smith

Anderson Schmidt Verne Ricci

Procedure OnClick

string[2][4] sCustomers

integer i j

// populate array

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

// reverse the array's first "row"

move (ReverseArray(sCustomers[0])) to sCustomers[0]

End_Procedure // OnClick


RGB

See Also: Graphics Functions, B_From_RGB, G_From_RGB, R_From_RGB, RGB, Understanding RGB Colors

Purpose

Returns a RGB value for GDI functions from byte values representing Red, Green & Blue color intensity.

Syntax

Use RGB.pkg

(RGB( {iRed}, {iGreen}, {iBlue} ))

Where:

  • {iRed} is an integer value representing red color intensity

  • {iGreen} is an integer value representing green color intensity

  • {iBlue} is an integer value representing blue color intensity

Examples

Use RGB.pkg

Procedure OnClick

Integer rgbColor

Integer iRed iGreen iBlue

Get Value of oRColor to iRed

Get Value of oGColor to iGreen

Get Value of oBColor to iBlue

Move (RGB(iRed, iGreen, iBlue)) to rgbColor

Set TextColor of oText to rgbColor

Set Value of oText to ("rgbColor = " + string(rgbColor))

End_Procedure // OnClick


Right

See Also: String Functions, Left, Mid, Pos, Rtrim

Purpose

Right returns the rightmost characters of a string up to a specified length.

Syntax

(Right( {string-value}, {length} ))

Where:

  • {string-value} is the string that characters will be extracted from

  • {length} is an integer value indicating the number of characters that are extracted from the right of {string-value}

What It Does

The Right function returns the trailing (rightmost) characters of {string-value} up to and including the character in Position {length} as counted backwards from the end of the string.

String sName

Move "John Smith" to sName

Move (Right(sName, 5)) To Customer.LastName

In this example, the last 5 characters of the value in the variable sName ("Smith") would be moved to the database field Customer.Lastname.

Sample

This sample separates a string into words by separating character groups (words) before and after any space in the text.

Function SplitStringIntoWords String sText returns String[]

String sWord

String[] Words

Integer iWordCount iSpacePos

// Repeat as long as sText contains data

While (sText <> "")

// Find the first/next space

Move (Pos (" ", sText)) To iSpacePos

// If a space was found

If (iSpacePos > 0) Begin

// Take the left part

Move (Left (sText, iSpacePos - 1)) To sWord

// Move the remainder to the text variable

Move (Right (sText, Length (sText) - iSpacePos)) To sText

End

// If no more spaces are found

Else Begin

// Make word equal to the text

Move sText To sWord

// Empty text to stop the loop

Move "" To sText

End

move sWord to Words[iWordCount]

increment iWordCount

Loop

function_return Words

End_Function // SplitStringIntoWords

Procedure OnClick

String sText

String[] Words

Move "Split this text into words" To sText

get SplitStringIntoWords sText to Words

End_Procedure // OnClick

Notes

  • If the {length} parameter = 0, the Right function will return an empty string. If {length} is less than 0, the function will return the {string-value} parameter in its entirety. If {length} is greater than the number of characters in {string-value} the function returns {string-value} in its entirety.

  • If the {string-value} parameter is of type other than string, its value will be converted to a string for output.


Round

See Also: Math Functions, Integer, Number, Real

Purpose

Round returns an integer value from a variable of another numeric type by rounding the decimal portion.

Syntax

(Round( {expression} ))

What It Does

Round returns {expression} rounded to the nearest integer value. When the decimal portion of the {expression} is .5 or more it is rounded up, otherwise it is rounded down.

Move (Round(8.3782)) To iSample

In this example, the value 8 is moved to iSample.

Round rounds negative numbers whose decimal value exceeds 0.5 downward.

Move (Round(-6.6)) To iSample

In this example, the value -7 is moved to iSample.

Notes

  • When used inside an expression, round affects only the precision of its own expression, not that of the evaluation of the overall expression.

Move (3.14 * Round(nMean)) To nResult

This example would output 3.14 times the rounded value of number variable nMean to number variable nResult in the full precision of number variables.


Rtrim

See Also: String Functions, Length, Ltrim, Pos, Right, Trim

Purpose

Rtrim returns a string with trailing spaces removed.

Syntax

(Rtrim( {string-value} ))

What It Does

Rtrim removes all spaces to the right of the rightmost non-space character in the {string-value} parameter.

Showln (Rtrim("18.45 ")) "%"

In this example, the string "18.45%" is shown.

Showln (Rtrim(" Joe "))

In this example, the string " Joe" is shown.

Notes

  • When the minus (-) operator is used in a string expression, the both operands are trimmed without needing to use this function. The asterisk (*) operator does the same thing, but inserts a single space.

Move ("ab " – " bc") To sResult1

Move ("ab " * " bc") To sResult2

In the above examples "abbc" is moved to sResult1 and "ab bc" is moved to sResult2.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If {string-value} is of type other than string, its value will be converted to a string for output.


SearchArray

See Also: Array Functions, CountArray, BinarySearchArray

Purpose

Returns the index of the first element in the array (or indicated element range) equal to a particular value.

Syntax

(SearchArray( {SearchVal}, {ArrayId} [, {ObjectId} , {MessageId} ]))

Where:

  • {SearchVal} is the value to compare array elements' values to. The index of the first element whose value is equal to {SearchVal} is returned.

  • {ArrayId} is the id of the array being searched. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare 2 array elements.

What it Does

Iterates from the first to the last element in an array and compares each element to the passed in value {SearchVal} or uses a custom function for the comparison. The index of the first element whose value is equal to {SearchVal} is returned. If no element with a value equal to {SearchVal} is found, -1 is returned.

To determine the number of times a value occurs in array, use CountArray.

For a more efficient search of large arrays, use BinarySearchArray.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient comparison method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal comparison algorithms, simply do not pass the ObjectId and MessageId parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to compare an array of elements that are of a type that cannot be compared using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom comparison function for the comparison process if a custom function is desired or required (for arrays of data types that cannot be compared using the internal algorithms: struct, RowId, variant).

It is important to return EQ in the user defined function if the two parameters passed are equal. This can be used to count array elements that meet certain conditions. The array element is passed as first parameter and the comparison value as the second parameter to a message MessageId of object ObjectId.

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

String array search:

This sample populates a dynamic array of strings (sCustomers), then searches it for the string "Jones". If the string is found, it displays the element in which the search term was found to the screen, otherwise a message stating that the string was not found is displayed. Last, the values of each array element is displayed to the screen.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

string sSearchTerm

integer iSearchIndex i iArraySize

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

// search for "jones", in any casing, in array

move "Jones" to sSearchTerm

move (SearchArray(sSearchTerm, sCustomers)) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// display array values

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Case-insensitive string array search:

Searching a string array in a case-insensitive manner is a common task, so the virtual machine provides a predefined function for case-insensitive string comparison: get_DFSTRICMP, defined in the Desktop object.

Syntax

(SearchArray( {SearchVal}, {ArrayId} , Desktop , get_DFSTRICMP))

This sample populates a dynamic array of strings (sCustomers), then searches it for the string "jones", no matter what the casing of any occurrence of "jones", in the sCustomers array. If the string is found, it displays the element in which the search term was found to the screen, otherwise a message stating that the string was not found is displayed. Last, the values of each array element is displayed to the screen.

This is really not a representative sample, since for an array of only 7 elements, you would use SearchArray rather than BinarySearchArray, but the sample shows you the proper syntax for this function.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

string sSearchTerm

integer iSearchIndex i iArraySize

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "JOnes" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

// search for "Jones" in array

move "jones" to sSearchTerm

move (SearchArray(sSearchTerm, sCustomers, Desktop, get_DFSTRICMP)) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// display array values

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Struct array search:

This sample uses a custom comparison function to find the first friend with last name "Jones" are in an array of 10 tFriend structs.

The custom comparison function (MyComparison) returns EQ whenever the Last member of the tFriend struct passed in as the first parameter to the function is equal to the Last member of the tFriend struct passed in as the second parameter. If these values are not equal, the function returns GT or LT, if the first parameter is greater than or less than the second, respectively.

In Procedure OnClick, MyFriends is declared as an array of 10 elements of type tFriend and populated with friends' names. Another struct of type tFriend is declared to store the search value. Since our comparison function only compares the Last member (last name) of each struct in the array, the First struct member is not filled with any value.

Struct tFriend

String First

String Last

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tFriend MyFriend tFriend SearchFriend Returns Integer

integer iRetVal

if (MyFriend.Last > SearchFriend.Last) ;

Function_Return (GT)

if (MyFriend.Last < SearchFriend.Last) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

// declare array of 10 tFriend structs

tFriend[10] MyFriends

// declare tFriend struct that will hold search value(s)

tFriend SearchFriend

integer iSearchIndex i iArraySize

// move value to compare array values to the Comparison struct

move "Jones" to SearchFriend.Last

// fill MyFriends array

move "Janet" to MyFriends[0].First

move "Smith" to MyFriends[0].Last

move "Pedro" to MyFriends[1].First

move "Rodriguez" to MyFriends[1].Last

move "Judy" to MyFriends[2].First

move "Smith" to MyFriends[2].Last

move "Fred" to MyFriends[3].First

move "Jones" to MyFriends[3].Last

move "Martin" to MyFriends[4].First

move "Anderson" to MyFriends[4].Last

move "Michael" to MyFriends[5].First

move "Schmidt" to MyFriends[5].Last

move "Jacques" to MyFriends[6].First

move "Verne" to MyFriends[6].Last

move "Enrico" to MyFriends[7].First

move "Ricci" to MyFriends[7].Last

move "Karl" to MyFriends[8].First

move "Sorensen" to MyFriends[8].Last

move "Juan" to MyFriends[9].First

move "Garcia" to MyFriends[9].Last

// call MyComparison function to search array elements for value(s) in SearchFriend

move (SearchArray(SearchFriend, MyFriends, Self, get_MyComparison)) to iSearchIndex

showln "The search value was found in element number " (string(iSearchIndex))

// display array values

move (SizeOfArray(MyFriends)) to iArraySize

for i from 0 to (iArraySize-1)

showln ":" MyFriends[i].First ":" MyFriends[i].Last ":"

loop

End_Procedure // OnClick

Example

Searching a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Schmidt Verne Ricci

If the first "row" (row 0) of the array is searched, the search term "Jones" is found in element 3. If the second "row" (row 1) of the array is searched, the search term "Jones" is not found. This effectively limits the search to a specific "row" of the array.

Procedure OnClick

string[2][4] sCustomers

string sSearchTerm

integer iSearchIndex

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

// search for "Jones" in first "row" of array

move "Jones" to sSearchTerm

move (SearchArray(sSearchTerm, sCustomers[0])) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

// search for "Jones" in second "row" of array

move "Jones" to sSearchTerm

move (SearchArray(sSearchTerm, sCustomers[1])) to iSearchIndex

if (iSearchIndex <> -1) ;

showln "The search value " sSearchTerm " was found in element " (string(iSearchIndex))

else ;

showln "The search value " sSearchTerm " was NOT found"

End_Procedure // OnClick


SerializeRowID

See Also: RowId, RowId Helper Functions

Purpose

To serialize a RowId so it can be represented by a string

Syntax

SerializeRowId( {RowId} )

Where:

  • {RowId} is a value of type RowId

Example

Procedure StoreSerializedId

String sRowId

RowId riCustomer

Move (GetRowId(Customer.File_Number)) to riCustomer

Move (SerializeRowId(riCustomer)) to sRowId

Send StoreIDInMyWebPage sRowId

End_Procedure // StoreSerializedId

Notes

  • SerializeRowId converts data of type RowId to a serialized string. This was created primarily to allow RowId to be represented over HTTP in web pages and web services.

  • A serialized RowId string can be moved back into a RowId variable using the DeserializeRowId function.

  • RowId variables cannot be cast into any other variable type. This serialization / deserialization process represents the only way RowId data can be moved to another type.

  • The rules for serialization and deserialization are private. Therefore a serialized RowId has no meaningful value. You program code should not rely on specific values for serialized RowIds. The single exception to this are null serialized RowId values. They always serialize to an empty string.


Seq_New_Channel

See Also: File I/O Functions, Seq_Release_Channel, Append_Output, Close_Input, Close_Output, Direct_Input, Direct_Output, Sequential File I/O

Purpose

Retrieves the next available sequential input/output (I/O) channel in an organized way. Specifying a channel number without these management functions can result in a collision. Open output can be closed without wanting to do so explicitly.

Syntax

Use seq_chnl.pkg

(Seq_New_Channel())

Example

Use seq_chnl.pkg

integer iChannel

move (Seq_New_Channel()) to iChannel

//...do some sequential I/O work...

send Seq_Release_Channel iChannel

Use seq_chnl.pkg

Procedure ChannelExample

integer iChIn iChOut

string sFileIn sFileOut sLineIn

// specify the original (input) file name

move "c:\testfile.txt" to sFileIn

// specify the new (output) file name

move "c:\newfile.txt" to sFileOut

// obtain 2 open channels, 1 for input, 1 for output

move (Seq_New_Channel()) to iChIn

// no channel available

if (iChIn=DF_SEQ_CHANNEL_NOT_AVAILABLE) begin

send Info_Box "No Channel Available for Process" "Error"

procedure_return

end

move (Seq_New_Channel()) to iChOut

// no channel available

if (iChOut=DF_SEQ_CHANNEL_NOT_AVAILABLE) begin

send Info_Box "No Channel Available for Process" "Error"

// if iChIn contains a valid channel, release it

if ((iChIn >= DF_SEQ_CHANNEL_MIN) AND (iChIn <= DF_SEQ_CHANNEL_MAX)) ;

send Seq_Release_Channel iChIn

procedure_return

end

// at this time both iChIn and iChOut contain a valid value

direct_input channel iChIn sFileIn // open input channel

direct_output channel iChOut sFileOut // open output channel

repeat

// read a line from input file

readln channel iChIn sLineIn

if (not (seqeof)) begin

// write the line to output file

writeln channel iChOut sLineIn

end

until (seqeof) // until sequential end of file

close_input channel iChIn // close input channel

close_output channel iChOut // close output channel

// release both channels for reuse

send Seq_Release_Channel iChIn

send Seq_Release_Channel iChOut

End_Procedure // ChannelExample

Notes

  • The Seq_New_Channel function can return a number of predefined constants:

  • DF_SEQ_CHANNEL_MIN (predefined value = 0)
    The returned channel number must be a minimum of this value to be a valid channel.

  • DF_SEQ_CHANNEL_MAX (predefined value = 9)
    The returned channel number must be a maximum of this value to be a valid channel.

  • DF_SEQ_START_CHANNEL (predefined value = 2)
    The default channels for sequential input and output operations are 0 and 1, when not using channels. Thus, the Seq_New_Channel function will start looking for available channels at 2 and use 0 and 1 last.

  • DF_SEQ_CHANNEL_NOT_AVAILABLE (predefined value = -2)
    This value will be returned if no channel is currently available for sequential input and output operations.

  • Valid channel numbers are DF_SEQ_CHANNEL_MIN through DF_SEQ_CHANNEL_MAX. The first returned channel number will be 2 because the channel numbers 0 and 1 are the default channels for direct_input and direct_output to operate on. When the function is called over 8 times the numbers 0 and 1 will be returned.

  • If no channel is available, the return value of this function will be DF_SEQ_CHANNEL_NOT_AVAILABLE. This function should be used to find an available I/O channel for use in sequential input and output operations. Usually this means that either the channel management is used incorrectly or that you want to use too many I/O channels at one time.

  • The function does NOT open the I/O channel for you. That must be done with a direct_input, direct_output or an append_output command.

  • Using this management function can only be successful when applied in all cases in a program.


Seq_Release_Channel

See Also: File I/O Functions, Seq_New_Channel, Append_Output, Close_Input, Close_Output, Direct_Input, Direct_Output, Sequential File I/O

Purpose

Releases specified sequential input/output (I/O) channel for reuse

Syntax

send Seq_Release_Channel {channel-number}

Where:

  • {channel-number} is a valid channel number or an integer variable containing a valid channel number

Example

Use seq_chnl.pkg

integer iChannel

move (Seq_New_Channel()) to iChannel

//...do some sequential I/O work...

send Seq_Release_Channel iChannel

Use seq_chnl.pkg

Procedure ChannelExample

integer iChIn iChOut

string sFileIn sFileOut sLineIn

// specify the original (input) file name

move "c:\testfile.txt" to sFileIn

// specify the new (output) file name

move "c:\newfile.txt" to sFileOut

// obtain 2 open channels, 1 for input, 1 for output

move (Seq_New_Channel()) to iChIn

// no channel available

if (iChIn=DF_SEQ_CHANNEL_NOT_AVAILABLE) begin

send Info_Box "No Channel Available for Process" "Error"

procedure_return

end

move (Seq_New_Channel()) to iChOut

// no channel available

if (iChOut=DF_SEQ_CHANNEL_NOT_AVAILABLE) begin

send Info_Box "No Channel Available for Process" "Error"

// if iChIn contains a valid channel, release it

if ((iChIn >= DF_SEQ_CHANNEL_MIN) AND (iChIn <= DF_SEQ_CHANNEL_MAX)) ;

send Seq_Release_Channel iChIn

procedure_return

end

// at this time both iChIn and iChOut contain a valid value

direct_input channel iChIn sFileIn // open input channel

direct_output channel iChOut sFileOut // open output channel

repeat

// read a line from input file

readln channel iChIn sLineIn

// write the line to output file

writeln channel iChOut sLineIn

until (seqeof) // until sequential end of file

close_input channel iChIn // close input channel

close_output channel iChOut // close output channel

// release both channels for reuse

send Seq_Release_Channel iChIn

send Seq_Release_Channel iChOut

End_Procedure // ChannelExample

Notes

  • Valid channel numbers are DF_SEQ_CHANNEL_MIN (0) through DF_SEQ_CHANNEL_MAX (9). Using a different number will not result in an error but the call is ignored.

  • A channel must be released to be available for reuse for future input/output in the same program.


SetCurrencyFormat

See Also: Locale Formatting Functions, SetNumberFormat, FormatNumber, FormatCurrency

Purpose

The SetCurrencyFormat message sets the global currency format-string. This currency format-string can then be used by the FormatCurrency function to format number variables.

Syntax

Use gFormatNumbers.Pkg

Send SetCurrencyFormat {sFormatString}

Where:

  • {sFormatString} operates very similarly to the DataDictionary masking strings.

The format-string $,#.##;($,#.##) will insert thousand separators (commas) and currency symbols and truncate the number to 2 decimal places, negative numbers would appear within parenthesis.

Token characters for sFormatString are:

$ | currency symbol as defined by windows
, | thousands separator as defined by windows
. | decimal separator as defined by windows
; | separates the positive and negative format, if the negative format is omitted the positive string is used with a preceding "-"
# | represents a digit, the quantity of tokens only matters to the right of the decimal
* | can be used to the right of the decimal, it means any number of decimals

All other characters are constants. They are just printed as displayed. E.g. the "(" and ")" for negative numbers.

If you wish to display a token as a literal, use a slash in front of it. E.g., /$ would create $, even in Germany, no matter what the currency symbol defined by windows.

Many tokens use locale information. Therefore the results will differ depending on your Regional Setting Properties for Currency.

What it Does

Allows you to create a custom format-string (mask) that can then be used to format numbers. The formatting of numbers is then accomplished by the FormatCurrency function when it uses the –2 parameter.

Send SetCurrencyFormat ",#.## $;,-#.## $"
Move (FormatCurrency(nNumber,iPoints)) to sString

Would result with 123.222,22 DM and -123.222,22 DM with German settings, but

123,222.22 $ and -123,222.22 $ with USA regional settings.

Notes

  • Normally, changing the format will be required only once in a program. However, you can change it as often as you need.

  • The SetCurrencyFormat is almost identical to the SetNumberFormat but its format-string is for a numeric mask whereas this mask is for a standard currency format-string.


SetNumberFormat

See Also: Locale Formatting Functions, SetCurrencyFormat, FormatCurrency, FormatNumber

Purpose

The SetNumberFormat message sets the global currency format-string. This numeric format-string can then be used by the FormatCurrency function to format number variables.

Syntax

Use gFormatNumbers.Pkg

Send SetNumberFormat {sFormatString}

Where:

  • {sFormatString} operates very similarly to the DataDictionary masking strings.

The format-string $,#.##;($,#.##) will insert thousand separators (commas) and currency symbols and truncate the number to 2 decimal places, negative numbers would appear within parenthesis.

Token characters for sFormatString are:

$ | currency symbol as defined by windows
, | thousands separator as defined by windows
. | decimal separator as defined by windows
; | separates the positive and negative format, if the negative format is omitted the positive string is used with a preceding "-"
# | represents a digit, the quantity of tokens only matters to the right of the decimal
* | can be used to the right of the decimal, it means any number of decimals

All other characters are constants. They are just printed as displayed. E.g. the "(" and ")" for negative numbers.

If you wish to display a token as a literal, use a slash in front of it. E.g., /$ would create $, even in Germany, no matter what the currency symbol defined by windows.

Many tokens use locale information. Therefore the results will differ depending on your Regional Setting Properties for Currency.

What it Does

Allows you to create a custom format-string (mask) that can then be used to format numbers. The formatting of numbers is then accomplished by the FormatCurrency function when it uses the –2 parameter.

Example

The format-string $,#.##;($,#.##) will insert thousand separators (commas) and currency symbols and truncate the number to 2 decimal places, negative numbers would appear within parenthesis.

Many tokens use locale information. Therefore the results will differ depending on your Regional Setting Properties for Numbers.

Send SetNumberFormat ",#.## ;,-#.##"
Move (FormatNumber(nNumber,iPoints)) to sString

Would result with 123.222,22 and -123.222.33 with German settings, but 123,222.22 and -23,222.22 with USA regional settings.

Notes

  • Normally, changing the format will be required only once in a program. However, you can change it as often as you need.

  • The SetNumberFormat is almost identical to the SetCurrencyFormat but its format-string is for a currency mask whereas this mask is for a standard numeric format-string.


Sformat

See Also: String Functions, Replace, Replaces

Purpose

Creates a formatted string by replacing markers in a host string (%1, %2, etc.) with sub-string values.

Syntax

Use GlobalFunctionsProcedures.pkg

(SFormat( {host-string}, {new-substring-1},....,{new-substring-9} ))

Where:

  • {host-string} is a string value with (%1, %2, ...) placeholders for string substitution

  • {new-substring-1},...,{new-substring-9} are string values to replace the respective placeholders (%1, %2, ...) with

What It Does

SFormat is passed a host-string and 1 to 9 replacement sub-strings. The host string contains replacement markers for each sub-string. The function returns a formatted string where all markers are replaced with the passed sub-strings. A replacement marker is defined as the % symbol followed by the replacement number. The first replacement marker is %1, the second is %2 and so on.

Examples

The following example will return "Hello, John how are you today".

Move (SFormat("Hello, %1 how are you today", "John")) to sReply

Replacement markers may be placed in any order and used more than once. The following example will return the string "I want to say Hello, Goodbye, Hello".

Move (SFormat("I want to say %2, %1, %2","Goodbye", "Hello")) to sReply

This function is used extensively by the packages to support multi language text. For example:

Send Log_Status (SFormat(C_$EndProcessNumberOfErrors, ;

Process_Title(self), ;

ErrCount))

where the constant C_$EndProcessNumberOfErrors is defined in a separate language package. The English version of this constant is "End Process: %1 (number of errors=%2)"

Notes

Note that the above sample passes the replacement parameter ErrCount as an integer. The integer will be converted to a string before being inserted into the host string. This can be a useful automatic conversion technique.

If your host string needs to display % symbol followed by a number, you should use %% instead of % to represent the text. The following example will return "This first parameter %1, will get replaced with coffee".

Move "coffee" to sSomeSymbol

Move (SFormat("This first parameter %%1, will get replaced with %1, ;

sSomeSymbol)) to sReply


ShowLastError

See Also: External_Function

Purpose

Returns an integer value and displays the error message for the system error codes returned by Win32 API function GetLastError.

Syntax

Use GlobalFunctionsProcedures.pkg

(ShowLastError())

What It Does

Displays the error message for the system error codes returned by Win32 API function GetLastError. This is useful for displaying errors (if any) after making Windows API calls.

Examples

Use GlobalFunctionsProcedures.pkg

Procedure Test

integer iResult

// :

// make some Windows API call here using External_Function command

// :

move (ShowLastError()) to iResult

End_Procedure // Test


ShuffleArray

See Also: Array Functions

Purpose

Returns array with elements in shuffled (random) order of original array.

Syntax

(ShuffleArray( {ArrayId} )

Where:

  • {ArrayId} is the id of the array being sorted. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

What it Does

ShuffleArray changes the order of the elements in an array to a random order.

Example

This sample shuffles a dynamic array of integers (ints1) and places the result into array ints2.

// fires when the button is clicked

Procedure OnClick

integer[][] ints1 ints2

// add some code to populate ints1 array

// :

// shuffle the array

move (ShuffleArray(ints1)) to ints2

End_Procedure // OnClick

Example

This sample shuffles an array of 10 strings (sCustomers), then displays the shuffled array elements to the screen.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

integer i iArraySize

// populate array

move "Smith" to sCustomers[0]

move "Rodriguez" to sCustomers[1]

move "Smith" to sCustomers[2]

move "Jones" to sCustomers[3]

move "Anderson" to sCustomers[4]

move "Schmidt" to sCustomers[5]

move "Verne" to sCustomers[6]

move "Ricci" to sCustomers[7]

move "Sorensen" to sCustomers[8]

move "Garcia" to sCustomers[9]

// randomize the array

move (ShuffleArray(sCustomers)) to sCustomers

// display the elements in the shuffled array

move (SizeOfArray(sCustomers)) to iArraySize

for i from 0 to (iArraySize-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Shuffling a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional string array with 8 (2x4) elements and fills it with unsorted string values. This creates an array as such:

Smith Rodriguez Scott Jones

Anderson Schmidt Verne Ricci

The first "row" (row 0) of the array is then shuffled and placed in row 0 of the resulting array (in this sample, the results of Shuffle Array are placed back in the original array). So, the first "row" of the array is randomized.

Procedure OnClick

string[2][4] sCustomers

integer i j

// populate array

move "Smith" to sCustomers[0][0]

move "Rodriguez" to sCustomers[0][1]

move "Scott" to sCustomers[0][2]

move "Jones" to sCustomers[0][3]

move "Anderson" to sCustomers[1][0]

move "Schmidt" to sCustomers[1][1]

move "Verne" to sCustomers[1][2]

move "Ricci" to sCustomers[1][3]

// randomize the array's first "row"

move (ShuffleArray(sCustomers[0])) to sCustomers[0]

End_Procedure // OnClick


Sin

See Also: Math Functions, Asin, Cos, Tan

Purpose

Sin returns the sine of a value.

Syntax

(Sin( {expression} ))

What It Does

Sin returns the sine of the value of {expression}. The expression is an angle stated in radians.

Real rSine

Move (Sin(.70711)) To rSine

In this example, the sine of .70711 is moved to the real variable rSine.

Notes

  • Sin interprets {expression} as a number of radians. To calculate the sine of a number of degrees, divide the degrees by 180 and multiply them by the value of p.

  • The domain for sin is [-1,1]. Value for values other than |x|>1 is UNDEFINED.

  • Sin converts the parameter {expression} to a real value, and outputs a real value.


SizeOfArray

See Also: ResizeArray, Array Functions

Purpose

Returns the number of elements in an array dimension.

Syntax

(SizeOfArray( {ArrayId [ {DimensionIndex} ] } ))

Where:

  • {ArrayId} is the id of the array being resized.

  • {DimensionIndex} is the dimension of the array to retrieve the number of elements of. If omitted, the outer (leftmost) dimension is used.

What it Does

SizeOfArray can retrieve the number of elements of any array dimension.

For example:

Integer[10] iMyArray

Move (SizeOfArray(iMyArray)) to iSize

Multi-dimensional arrays and jagged arrays can be thought of as arrays of arrays. So to get the number of elements of the second dimension of a multi-dimensional or Jagged array you just specify the indexer for the first dimension, resulting in an expression of the array for the particular dimension:

Integer[][] iMyArray

// Move some values to iMyArray

Move (SizeOfArray(iMyArray[1])) to iSize

The above example retrieves the number of elements in dimension 1 of iMyArray.

Example

This sample declares and fills a dynamic two-dimensional integer array. It then uses SizeOfArray to determine the number of elements of the two dimensions and displays the result to the screen.

// fires when the button is clicked

Procedure OnClick

integer[][] ints1

integer i j iDim1Size iDim2Size

// fill the array

move 1 to ints1[0][0]

move 2 to ints1[0][1]

move 3 to ints1[0][2]

move 4 to ints1[1][0]

move 5 to ints1[1][1]

move 6 to ints1[1][2]

move 7 to ints1[2][0]

move 8 to ints1[2][1]

move 9 to ints1[2][2]

// retrieve size of outer (leftmost) dimension

move (SizeOfArray(ints1)) to iDim1Size

// retrieve size of inner (2nd) dimension

move (SizeOfArray(ints1[1])) to iDim2Size

// display the array's contents

for i from 0 to (iDim1Size-1)

for j from 0 to (iDim2Size-1)

show ints1[i][j]

show " "

loop

showln // go to next line for next row

loop

End_Procedure // OnClick

Notes

  • Attempting to reference an array dimension that is beyond the current number of dimensions of the array will result in error 4509 "Reference Array Index Out Of Bounds".


SizeOfType

See Also: Data Types, Variables and Constants

Purpose

SizeOfType returns the size in bytes of the specified data type. Can be used with both fundamental types and user defined struct types.

Syntax

(SizeOfType( {type} ))

Where:

  • {type} is any of the built in fundamental types or a user defined struct type

Example

This sample shows how to determine the size of the string data type.

Function SizeOfString

Move (SizeOfType(string)) to iSize

function_return iSize

End_Function // SizeOfString

Example

This sample shows how to determine the size of a structured data type.

Struct tPoint

Integer iXPos

Integer iYPos

End_Struct

Function SizeOf_tPoint returns Integer

Integer iSize

Move (SizeOfType(tPoint)) to iSize

function_return iSize

End_Function // SizeOf_tPoint

Notes

  • A common mistake is to pass a variable of a particular data type instead of the data type itself. For example:

Procedure OnClick

integer iCounter iTypeSize

move (SizeOfType(iCounter)) to iTypeSize

End_Procedure // OnClick

This code will result in compiler error 54 "Invalid symbol in expression". The corrected version of the above code is shown below, passing the data type itself:

Procedure OnClick

integer iCounter iTypeSize

move (SizeOfType(integer)) to iTypeSize

End_Procedure // OnClick


SpanDays

See Also: Time and Date Functions

Syntax

SpanDays(tsVar)

What it Does

The SpanDays function returns the Days component of the given TimeSpan variable field, tsVar.

Example

Procedure testSpanDays

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The days between " dtVar1 " and " dtVar2 " is " (SpanDays(tsVar))

End_Procedure


SortArray

See Also: Array Functions

Purpose

Returns array with sorted elements.

Syntax

(SortArray( {ArrayId} [, {ObjectId} , {MessageId} ] )

Where:

  • {ArrayId} is the id of the array being sorted. Array must be non-jagged and one dimensional (it can be a single dimension of a multi-dimensional array).

  • {ObjectId} is the id of object that implements the comparison function.

  • {MessageId} is the id of the function that will be used to compare 2 array elements.

What it Does

SortArray sorts an array using either an internal sorting algorithm or one provided by the developer.

Visual DataFlex implements different sorting algorithms for different data types in the virtual machine, in order to provide developers with the most efficient sorting method based on the data type. Algorithms provided in the virtual machine will also run faster. To use the internal sorting algorithms, simply do not pass the {ObjectId} and {MessageId} parameters.

We recommend the use of these internal algorithms if there is no strong reason for a developer to use a special comparison, or to sort an array of elements that are of a type that cannot be sorted using the internal algorithms: struct, RowId, variant.

The developer has the option of providing a custom sorting function for the sorting process if a custom function is desired or required (for arrays of data types that cannot be sorted using the internal algorithms: struct, RowId, variant).

The function provided in {MessageId} must follow the following syntax:

Function MyCompareFunc {array-element-type} arg1 {array-element-type} arg2 Returns Integer

This function must return one of these values:

  • (GT) - if first parameter is greater than second parameter

  • (EQ) – if parameters order is irrelevant

  • (LT) – if first parameter is less than second parameter

Example

String array sort:

This sample sorts a dynamic array of strings (sCustomers), then displays the sorted array to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

integer i iArrayCount

// populate sCustomers with customer data

// :

// sort the array

move (SortArray(sCustomers)) to sCustomers

// display the sorted array

move (SizeOfArray(sCustomers)) to iArrayCount

for i from 0 to (iArrayCount-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Case-insensitive string array sort:

Sorting a string array in a case-insensitive manner is a common task, so the virtual machine provides a predefined function for case-insensitive string comparison: get_DFSTRICMP, defined in the Desktop object.

Syntax

(SortArray( {ArrayId} , Desktop , get_DFSTRICMP))

This sample sorts a dynamic array of strings (sCustomers) in a case-insensitive manner, then displays the sorted array to the screen.

The code that populates the sCustomers array is not shown for the sake of simplicity and clarity.

// fires when the button is clicked

Procedure OnClick

string[] sCustomers

integer i iArrayCount

// populate sCustomers with customer data

// :

// sort the array in a case-insensitive manner

move (SortArray(sCustomers, Desktop, get_DFSTRICMP)) to sCustomers

// display the sorted array

move (SizeOfArray(sCustomers)) to iArrayCount

for i from 0 to (iArrayCount-1)

showln sCustomers[i]

loop

End_Procedure // OnClick

Example

Struct array sort:

This sample declares a structured data type (tUSAddress), then declares 2 arrays of type tUSAddress of 5 elements each. The first array (myAddresses) is populated, then sorted, and the result placed in the second array (mySortedAddresses), the contents of which are displayed to the screen.

The code that populates the myAddresses array is not shown for the sake of simplicity and clarity.

Struct tUSAddress

String Street

Integer ZipCode

End_Struct

// Custom sort and search comparison function:

// Returns (LT) if struct value in first parameter < struct value in second parameter.

// Returns (GT) if struct value in first parameter > struct value in second parameter.

// Otherwise returns (EQ).

Function MyComparison tUSAddress MyAddress tUSAddress SearchAddress Returns Integer

integer iRetVal

if (MyAddress.Last > SearchAddress.Last) ;

Function_Return (GT)

if (MyAddress.Last < SearchAddress.Last) ;

Function_Return (LT)

Function_Return (EQ)

End_Function // MyComparison

// fires when the button is clicked

Procedure OnClick

tUSAddress[5] myAddresses mySortedAddresses

integer iSize iCount

// initialize address array

move 33186 to myAddresses[0].ZipCode

move 33177 to myAddresses[1].ZipCode

move 90210 to myAddresses[2].ZipCode

move 10245 to myAddresses[3].ZipCode

move 78610 to myAddresses[4].ZipCode

move (SortArray(myAddresses, Self, get_MyComparison)) to mySortedAddresses

// display sorted array

move (SizeOfArray(mySortedAddresses)) to iSize

for iCount From 0 to (iSize-1)

showLn "mySortedAddresses[" iCount "]= " mySortedAddresses[iCount].street ", " mySortedAddresses[iCount].zipCode

Loop

End_Procedure // OnClick

Example

Sorting a single dimension of a multi-dimensional array:

This sample declares a 2 dimensional integer array with 9 (3x3) elements and fills it with unsorted integer values. This creates an array as such:

7 5 2

4 6 1

9 7 2

The first "row" (row 0) of the array is then sorted and placed in row 0 of the resulting array (in this sample, the results of SortArray are placed back in the original array), resulting in this array:

2 5 7

4 6 1

9 7 2

Procedure OnClick

integer[3][3] myInts

integer i j

move 7 to myInts[0][0]

move 5 to myInts[0][1]

move 2 to myInts[0][2]

move 4 to myInts[1][0]

move 6 to myInts[1][1]

move 1 to myInts[1][2]

move 9 to myInts[2][0]

move 7 to myInts[2][1]

move 2 to myInts[2][2]

move (SortArray(myInts[0])) to myInts[0]

End_Procedure // OnClick

Notes

  • What is the complexity of the Visual DataFlex SortArray function (where n is number of array elements)?

a) Using internal logic:

    • Sorting data type string uses O(n), in other words, linear time, and requires additional memory for n-string pointers. The algorithm is stable (equal elements are in the order in which they were in the unsorted array). Based on MSD RadixSort.

    • Sorting data types bigint, char, currency, date, datetime, decimal, dword, integer, number, short, ubigint, uchar, uinteger and ushort is done in linear time and requires additional memory of the array size. Based on LSD RadixSort.

    • Sorting data types Boolean, float, real, time and timespan uses O(n log n) time complexity, it is in place (no additional memory required) and not stable. Based on QSort.

b) Using a developer supplied comparison method:

    • Sorting is O(n log n) time complexity, it is in place and not stable. Based on QSort.


SpanHours

See Also: Time and Date Functions

Syntax

(SpanHours( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanHours function returns the Hours component of the given TimeSpan variable field tsVar.

Example

Procedure testSpanHours

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The hours between " dtVar1 " and " dtVar2 " is " (SpanHours(tsVar))

End_Procedure

Notes

  • To find the total number of hours between two date time fields, use the SpanTotalHours function.


SpanMinutes

See Also: Time and Date Functions

Syntax

(SpanMinutes( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanMinutes function returns the Minutes component of the given TimeSpan variable field, tsVar.

Example

Procedure testSpanMinutes

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The Minutes between " dtVar1 " and " dtVar2 " is " (SpanMinutes(tsVar))

End_Procedure

Notes

  • To find the total number of Minutes between two date time fields, use the SpanTotalMinutes function.


SpanSeconds

See Also: Time and Date Functions

Syntax

(SpanSeconds( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanSeconds function returns the Seconds component of the given TimeSpan variable field, tsVar.

Example

Procedure testSpanSeconds

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The seconds between " dtVar1 " and " dtVar2 " is " (SpanSeconds(tsVar))

End_Procedure

Notes

  • To find the total number of Seconds between two date time fields, use the SpanTotalSeconds function.


SpanTotalDays

See Also: Time and Date Functions

Syntax

(SpanTotalDays( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanTotalDays function calculates the total number of days in the time span and returns a double precision real number of that amount. tsVar is a TimeSpan value.

Example

Procedure testSpanTotalDays

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The total days between " dtVar1 " and " dtVar2 " is " (SpanTotalDays(tsVar))

End_Procedure


SpanTotalHours

See Also: Time and Date Functions

Syntax

(SpanTotalHours( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanTotalHours function calculates the total number of Hours in the time span and returns a double precision real number of that amount. tsVar is a TimeSpan value.

Example

Procedure testSpanTotalHours

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The total Hours between " dtVar1 " and " dtVar2 " is " (SpanTotalHours(tsVar))

End_Procedure


SpanTotalMinutes

See Also: Time and Date Functions

Syntax

(SpanTotalMinutes( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanTotalMinutes function calculates the total number of Minutes in the time span and returns a double precision real number of that amount. tsVar is a TimeSpan value.

Example

Procedure testSpanTotalMinutes

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The total Minutes between " dtVar1 " and " dtVar2 " is " (SpanTotalMinutes(tsVar))

End_Procedure


SpanTotalSeconds

See Also: Time and Date Functions

Syntax

(SpanTotalSeconds( {tsVar} ))

Where:

  • {tsVar} is a value of type TimeSpan

What it Does

The SpanTotalSeconds function calculates the total number of Seconds in the time span and returns a double precision real number of that amount. tsVar is a TimeSpan value.

Example

Procedure testSpanTotalSeconds

DateTime dtVar1 dtVar2

TimeSpan tsVar

// Set dtVar1 to 12/31/1999, 11:59:59pm

Move (DateSetYear (dtVar1, 1999)) To dtVar1

Move (DateSetMonth (dtVar1, 12)) To dtVar1

Move (DateSetDay (dtVar1, 31)) To dtVar1

Move (DateSetHour (dtVar1, 23)) To dtVar1

Move (DateSetMinute(dtVar1, 59)) To dtVar1

Move (DateSetSecond(dtVar1, 59)) To dtVar1

Move (CurrentDateTime()) To dtVar2

Move (dtVar1 - dtVar2) To tsVar

Showln "The total Seconds between " dtVar1 " and " dtVar2 " is " (SpanTotalSeconds(tsVar))

End_Procedure


Sqrt

See Also: Math Functions

Purpose

Sqrt returns the square root of a value.

Syntax

(Sqrt( {expression} ))

Where:

  • {expression} can be any data type except string

What It Does

Sqrt returns the value which, if multiplied by itself, equals the original {expression}.

Number nRoot

Move (Sqrt(9)) To nRoot

In this example, the square root of 9 is moved to the number variable nRoot.

If {expression} is negative, sqrt will give the same result as though {expression} were positive.

Notes

  • Sqrt converts the {expression} parameter to a real value, and outputs a real value.


Stop_Box

See Also: Dialog and Message Box Functions, Info_Box, Message_Box, YesNo_Box, YesNoCancel_Box

Purpose

Displays an error dialog box.

Syntax

Use Windows.pkg

Send Stop_Box {sMessage} [ {sCaption} ]

Where:

  • {sMessage} is a string containing the information message to be shown. A carriage-return/linefeed can be placed in the message string by the inclusion of \n in the text.

  • {sCaption}. The {sCaption} parameter is optional. If passed, it specifies the content of the caption bar. If {sCaption} is not passed, the caption bar will display the string "Stop".

What It Does

Stop_Box is used to pop up a serious error information message box. The message string {sMessage} is displayed in a message box dialog along with the Stop icon and a single OK button.

Examples

Send Stop_Box "Unable to open file for output!"

In the above example, the information dialog's caption bar will read "Stop".

Notes

If the user types Ctrl+C in the stop box, the text of the message is copied to the clipboard.


StoreC

See Also: Memory Management Functions

Purpose

Places a one byte value in memory using its address and an offset.

Syntax

(StoreC( {pMemory}, {iOffset}, {iValue} ))

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the value will be stored

  • {iValue} is the value that will be stored

What It Does

Stores the given value, {iValue}, in one byte of a memory block using its address and a given offset. Using the StoreC function with invalid parameters will likely cause your program to crash.

Example

Function PutMemoryByte Address aPointer Integer iOffset Integer iValue Returns Boolean

Boolean bResult

Move (StoreC(aPointer, iOffset, iValue)) to bResult

Function_Return bResult

End_Function // PutMemoryByte


StoreDw

See Also: Memory Management Functions

Purpose

Places a one double-word value in memory using its address and an offset.

Syntax

(StoreDW( {pMemory}, {iOffset}, {iValue} ))

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the value will be stored

  • {iValue} is the value that will be stored

What It Does

Stores the given value, {iValue}, in one word of a memory block using its address and a given offset. Using the StoreDW function with invalid parameters will likely cause your program to crash.

Example

Function PutMemoryDWord Address aPointer Integer iOffset Integer iValue Returns Boolean

Boolean bResult

Move (storedw(aPointer, iOffset, iValue)) to bResult

Function_Return bResult

End_Function // PutMemoryDWord


StoreW

See Also: Memory Management Functions

Purpose

Places a one word value in memory using its address and an offset.

Syntax

(StoreW( {pMemory}, {iOffset}, {iValue} ))

Where:

  • {pMemory} is an address variable that is set equal to the block of memory

  • {iOffset} is an integer variable that contains the offset within the block of memory where the value will be stored

  • {iValue} is the value that will be stored

What It Does

Stores the given value, {iValue}, in one word of a memory block using its address and a given offset. Using the StoreW function with invalid parameters will likely cause your program to crash.

Example

Function PutMemoryWord Address aPointer Integer iOffset Integer iValue Returns Boolean

Boolean bResult

Move (storew(aPointer, iOffset, iValue)) to bResult

Function_Return bResult

End_Function // PutMemoryWord


String Function

See Also: Type Conversion Functions, Date, Integer, Number, Real, Round, String

Purpose

String returns data of type string regardless of the type of the source value.

Syntax

(String( {expression} ))

What It Does

String returns the value of {expression} as a string.

Procedure Test

number nNum

string sFormatted

Move -45 To nNum

Move ("$" + String(nNum) + ".00") To sFormatted

End_Procedure // Test

In this example, the string "$-45.00" is moved to the string variable sFormatted.

Notes

  • It is not always necessary to convert numbers, dates, and other types to string in order to perform string manipulations on their values. Many string manipulations can be performed more straightforwardly without conversion.


SysConf

See Also: Locale Formatting Functions, Miscellaneous Functions

Purpose

Returns a string value containing environment-specific information.

Syntax

(SysConf( {environment_option} ))

Where:

  • {environment_options} can be one of the following:

sysconf_timer_resolution

sysconf_dir_separator

sysconf_os_short_name

sysconf_os_major_rev

sysconf_os_minor_rev

sysconf_os_name

sysconf_machine_name

sysconf_file_mask

sysconf_dataflex_rev

sysconf_system_name

sysconf_runtime_name

sysconf_utc_time_offset

What It Does

This function takes a single parameter and returns the appropriate environment-specific information. The valid {environment_options} and the information each returns are listed below.

Environment_Options

sysconf_timer_resolution

Returns the number of timer events per second in a Visual DataFlex timer object.

Example

string sVal

move (SysConf(sysconf_timer_resolution)) to sVal

send Info_Box sVal "Timer Events Per Second"

sysconf_dir_separator

Directory separation character for the current environment (e.g., "\" for DOS and Windows, "/" for UNIX or LiNUX).

Example

string sVal

move (SysConf(sysconf_dir_separator)) to sVal

send Info_Box sVal "Directory Separator"

sysconf_os_short_name

Returns the operating system short name (e.g., "WIN32" for Windows NT 4.0).

Example

string sVal

move (SysConf(sysconf_os_short_name)) to sVal

send Info_Box sVal "OS Short name"

sysconf_os_major_rev

Returns the major, or whole-number, operating system revision (e.g., "4" for Windows NT 4.0).

Example

string sVal

move (SysConf(sysconf_os_major_rev)) to sVal

send Info_Box sVal "OS Major Revision"

sysconf_os_minor_rev

Returns the minor, or decimal number, operating system revision (e.g., "0" for Windows NT 4.0).

Example

string sVal

move (SysConf(sysconf_os_minor_rev)) to sVal

send Info_Box sVal "OS Minor Revision"

sysconf_os_name

Returns the specific operating system name (e.g., "Windows NT" for Windows NT 4.0).

Example

string sVal

move (SysConf(sysconf_os_name)) to sVal

send Info_Box sVal "OS Name"

sysconf_machine_name

This environment_option is obsolete.

sysconf_file_mask

Returns the wildcard search mask to find all files in the current environment.

Example

string sLine sDrive

integer iChIn

move 2 to iChIn

move "D" to sDrive

direct_input channel iChIn ;

("DIR: "+sDrive+":"+(sysconf(sysconf_file_mask)))

while not (seqeof)

readln channel iChIn sLine

showln sLine

loop

This code opens and displays a directory of all files in a specified drive (drive D in this example).

sysconf_dataflex_rev

Returns the name of the current Visual DataFlex revision (e.g., "11.0").

Example

string sVal

move (SysConf(sysconf_dataflex_rev)) to sVal

send Info_Box sVal "VDF Revision"

sysconf_system_name

Returns the system-specific operating system name.

Example

string sVal

move (SysConf(sysconf_system_name)) to sVal

send Info_Box sVal "System Name"

sysconf_runtime_name

Returns the path and name of the runtime executable program.

Example

string sVal

move (SysConf(sysconf_runtime_name)) to sVal

send Info_Box sVal "Runtime Executable Path & Name"

sysconf_utc_time_offset

Returns the number of seconds east or west of the meridian.

Example

string sVal

integer iTime

move (SysConf(sysconf_utc_time_offset)) to sVal

move (sVal/60/60) to iTime

send Info_Box ((string(iTime))+" hours") ;

"Time Offset from Meridian"

Notes

  • The SYSCONF function will allow the developer to make use of operating system services without requiring hard-coded references to these services, thereby increasing source code portability.


Tan

See Also: Math Functions, Atan, Cos, Sin

Purpose

Tan returns the tangent of a value.

Syntax

(Tan( {expression} ))

Where:

  • {expression} is an angle stated in radians

What It Does

Tan returns the tangent of the value of {expression}.

Move (Tan(.70711)) To nTangent

Notes

  • Tan interprets value as a number of radians. To calculate the tangent of a number of degrees, divide the degrees by 180 and multiply them by the value of p.

  • The domain for tan is [-1,1]. Value for values other than |x|>1 is UNDEFINED.

  • Tan converts the parameter {expression} to a real value, and outputs a real value.


Trim

See Also: String Functions, Ltrim, Rtrim

Purpose

Trim returns a string with leading and trailing spaces removed.

Syntax

(Trim( {string-value} ))

What It Does

Trim removes all spaces to the left of the leftmost non-space and to the right of the rightmost non-space character in the {string-value} parameter.

Showln "$" (Trim(" Happyness ")) "$"

In this example, the string "$Happyness$" is shown.

Notes

  • When the minus ( ) operator is used in a string expression, the both operands are trimmed without needing to use this function. The asterisk (*) operator does the same thing, but inserts a single space.

Move ("ab " – " bc") To sResult1

Move ("ab " * " bc") To sResult2

In the above examples "abbc" is moved to sResult1 and "ab bc" is moved to sResult2.

  • This function returns a value of type string. If the result of this function is moved to a variable of type other than string, its value is converted to the destination type.

  • If the {string-value} parameter is of type other than string, its value will be converted to a string for output.


ToANSI

See Also: String Functions, ToOEM

Purpose

Converts a string from the OEM (Original Equipment Manufacturer) character set to the ANSI (American National Standards Institute) character set.

Syntax

Use GlobalFunctionsProcedures.pkg

(ToANSI( {string-value} ))

What It Does

ToANSI converts the string from OEM to ANSI.

Notes

  • Windows controls need to display ANSI data. Internally, Visual DataFlex objects uses OEM data. Therefore, before a value is displayed it must be converted to ANSI. When a value is moved from a Windows control back to the Visual DataFlex object it must be converted to OEM. This translation occurs automatically and it is not something you normally need to deal with. If for some reason your application is directly working with ANSI data, you may need to convert the data manually between the 2 different character sets.

  • The OEM_Translate_State property determines if a control should convert a value to ANSI when displaying it in a window and converted back into OEM when stored in the Visual DataFlex object.


ToOEM

See Also: String Functions, ToANSI

Purpose

Converts a string from the ANSI (American National Standards Institute) character set to the OEM (Original Equipment Manufacturer) character set.

Syntax

Use GlobalFunctionsProcedures.pkg

(ToOEM( {string-value} ))

What It Does

ToOEM converts the string from ANSI to OEM.

Notes

  • Windows controls need to display ANSI data. Internally, Visual DataFlex objects uses OEM data. Therefore, before a value is displayed it must be converted to ANSI. When a value is moved from a Windows control back to the Visual DataFlex object it must be converted to OEM. This translation occurs automatically and it is not something you normally need to deal with. If for some reason your application is directly working with ANSI data, you may need to convert the data manually between the 2 different character sets.

  • The OEM_Translate_State property determines if a control should convert a value to ANSI when displaying it in a window and converted back into OEM when stored in the Visual DataFlex object.


Uppercase

See Also: String Functions, Lowercase

Purpose

To return a string made up of the input string with all the letters capitalized.

Syntax

(Uppercase( {string-value} ))

What It Does

Uppercase capitalizes all letters in {string-value}, leaving other characters unchanged.

String sLastname

Move "Smith" to sLastname

Move (Uppercase(sLastname)) To sLastname

This example would change the value of the variable sLastname from "Smith" to "SMITH"

Notes

  • If {string-value} is of type other than string, its value will be converted to a string for output.


Utf8ToOemBuffer

See Also: Miscellaneous Functions, OemToUtf8Buffer, Free

Purpose

Converts a UTF-8 string to OEM.

Syntax

Use CharTranslate.pkg

(Utf8ToOemBuffer( {pUtf8Buf}, {iLen} ))

Where:

  • {pUtf8Buf} is a pointer to the string buffer to be converted

  • {iLen} is the length, in bytes, of the string pointed to by {pUtf8Buf}

What It Does

Returns a pointer to a newly allocated string buffer containing the converted text. Converts a string of UTF-8 characters to OEM.

Examples

// Translate data. pass: Data and translation mode.

// returns pointer to new translated data 0 if no translate needed.

// Passed data is not changed.

// eXlt can be: xtUtf8toOem, xtOemtoUtf8 and xtNoTranslate

Function TranslateData integer eXlt ;

address aData ;

integer iDataLen ;

returns address

address aDataXlt

Case Begin

case (eXlt = xtUtf8toOem)

Move (Utf8toOemBuffer(aData, iDataLen)) to aDataXlt

case Break

case (eXlt = xtOemtoUtf8)

Move (OemToUtf8Buffer(aData, iDataLen)) to aDataXlt

case Break

case else

Move 0 to aDataXlt

Case End

Function_Return aDataXlt

End_Function

Notes

Utf8ToOemBuffer will allocate a new block of memory to store the converted string. A pointer to this memory is returned by the function. You must call Free to de-allocate this memory when it is no longer required. Failure to do this will cause a memory leak in your application.


WindowsMessage

See Also: Miscellaneous Functions

Purpose

Send a message to the Windows message queue for the current object.

Syntax

Use GlobalFunctionsProcedures.pkg

(WindowsMessage( {iMsg}, {wParam}, {lParam} ))

Where:

  • {iMsg} Is an integer value that specifies the message to be sent

  • {wParam} Is a wide integer that specifies additional message-specific information

  • {lParam} Is a long integer that also specifies additional message-specific information

What It Does

WindowsMessage sends the specified message to the window handle retrieved from the current object. The return value specifies the result of the message processing and depends on the message sent.

Examples

Function piPosition Returns Integer

If (Window_Handle(self)) Begin

Function_Return (WindowsMessage(PBM_GETPOS, 0, 0))

End

Else Function_Return 0

End_Function

The above example shows how to use WindowsMessage to retrieve the progress bar position VDF cProgressBar object.

Function NextSibling Handle hItem returns Handle

Move (WindowsMessage(TVM_GETNEXTITEM, TVGN_NEXT, hItem)) To hItem

Function_Return hItem

End_Function

The above example shows how to use WindowsMessage to retrieve a handle to the next sibling of a passed node in a VDF TreeView object.

Notes

The WindowsMessage function uses delegation to obtain a window handle of the window that will process the message.

Use of the WindowsMessage function requires Windows API knowledge about the message being sent and the control that will process the message.


WMLEncode

See Also: Web Application Helper Functions

Purpose

Returns a string encoded so that it content will not be interpreted by a WAP browser as special WML formatting characters. It also adds "<br />" to the end of each line.

Syntax

Use WMLEncode.pkg

(WMLEncode( {string-value} ))

What It Does

Before field data is passed to an Active Server Page (ASP) file, you will often want to make sure that the data is properly encoded so that the text will not be interpreted by the WAP browser as special WML formatting characters.

Without some kind of conversion, embedded tags will be interpreted by your browser.

Examples

Procedure Test

string sText

// initialize sText with a string value

Send WriteWml (WMLEncode(sText))

End_Procedure // Test

Notes

The reason that most Write messages are not automatically encoded is so you can embed custom WML encoding in your output strings.

It is very important that you remember to encode your data or your resulting WML output may be undesirable.


WMLEncodeNOCRLF

See Also: Web Application Helper Functions

Purpose

Returns a string encoded so that it content will not be interpreted by a WAP browser as special WML formatting characters.

Syntax

Use WMLEncode.pkg

(WMLEncodeNOCRLF( {string-value} ))

What It Does

Before field data is passed to an Active Server Page (ASP) file, you will often want to make sure that the data is properly encoded so that the text will not be interpreted by the WAP browser as special WML formatting characters.

Without some kind of conversion, embedded tags will be interpreted by your browser.

Examples

Procedure Test

string sText

// initialize sText with a string value

Send WriteWml (WMLEncodeNoCRLF(sText))

End_Procedure // Test

Notes

The reason that most Write messages are not automatically encoded is so you can embed custom WML encoding in your output strings.

It is very important that you remember to encode your data or your resulting WML output may be undesirable.


YesNo_Box

See Also: Dialog and Message Box Functions, Info_Box, Message_Box, Stop_Box, YesNoCancel_Box

Purpose

Displays a dialog box with Yes & No buttons.

Syntax

Use Windows.pkg

(YesNo_Box( {sMessage} [, {sCaption} [, {Default-Button} ] ] ))

Where:

  • {sMessage} is a string containing the information message to be shown. A carriage-return/linefeed can be placed in the message string by the inclusion of \n in the text.

  • {sCaption}. The {sCaption} parameter is optional. If passed, it specifies the content of the caption bar. If {sCaption} is not passed, the caption bar will display the string "Question".

  • {Default-Button}. The {Default-Button} parameter is optional. If passed, it will specify which button will be the default. If not passed, the first button (Yes) will be the default. Valid default buttons are specified by the following constants:

    • MB_DEFBUTTON1 (Yes)

    • MB_DEFBUTTON2 (No)

If you wish to specify a default button but not a caption, pass two quotation marks (null) as {sCaption}, followed by the desired default button.

What It Does

YesNo_Box is used to pop a Yes/No confirmation message box and obtain the user's response. The passed message {sMessage} is displayed along with the Information icon, a Yes button, and a No button.

The return value will be one of two predefined message-box return values:

  • MBR_YES (Yes was selected)

  • MBR_NO (No was selected)

Examples

Use Windows.pkg

Procedure Example

Integer eResponse

Move (YesNo_Box("Delete this file?", "", MB_DEFBUTTON2)) to eResponse

If (eResponse = MBR_YES) Begin

Send DeleteFile

End

End_Procedure // Example

Notes

If the user types Ctrl+C in the message box, the text of the message is copied to the clipboard.


YesNoCancel_Box

See Also: Dialog and Message Box Functions, Info_Box, Message_Box, Stop_Box, YesNo_Box

Purpose

Displays a dialog box with Yes, No & Cancel buttons.

Syntax

Use Windows.pkg

(YesNoCancel_Box( {sMessage} [, {sCaption} [, {Default-Button} ] ] ))

Where:

  • {sMessage} is a string containing the information message to be shown. A carriage-return/linefeed can be placed in the message string by the inclusion of \n in the text.

  • {sCaption}. The {sCaption} parameter is optional. If passed, it specifies the content of the caption bar. If {sCaption} is not passed, the caption bar will display the string "Question".

  • {Default-Button}. The {Default-Button} parameter is optional. If passed, it will specify which button will be the default. If not passed, the first button (Yes) will be the default. Valid default buttons are specified by the following constants:

    • MB_DEFBUTTON1 (Yes)

    • MB_DEFBUTTON2 (No)

    • MB_DEFBUTTON3 (Cancel)

If you wish to specify a default button but not a caption, pass two quotation marks (null) as {sCaption}, followed by the desired default button.

hat It Does

YesNoCancel_Box is used to pop a Yes/No/Cancel confirmation message box and obtain the user's response. The passed message {sMessage} is displayed along with the Information icon, a Yes button, a No button, and a Cancel button.

The return value will be one of two predefined message-box return values:

  • MBR_YES (Yes was selected)

  • MBR_NO (No was selected)

  • MBR_CANCEL (cancel was selected)

Examples

Use Windows.pkg

Procedure Example

Integer eResponse

Move (YesNoCancel_Box("Save the current setup profile?")) To eResponse

If (eResponse = MBR_CANCEL) Procedure_Return

If (eResponse = MBR_YES) Send SaveProfile

Send SaveData

End_Procedure // Example

Notes

If the user types Ctrl+C in the message box, the text of the message is copied to the clipboard.


Global Variables

This section describes some important global variables that are built into Visual DataFlex for various purposes. They are listed alphabetically.

See Also: Global Variables, Global_Variable command


Constrain_Found_Count

Constrain_Found_Count Global Variable

See Also: Global Variables Used by Data Dictionaries, Constrain_Tests_Count, Constrained_Find, Constraint_Set, Constraint_Validate

Purpose

To determine how many records meet the criteria in a constrained find.

Type

Integer

What It Does

This integer increments continuously while a program runs. It contains the number of records which meet the criteria in the constraint.

Notes

  • You must initialize constrain_found_count to zero (0) at the point where you wish to begin counting.


Constrain_Tests_Count

Constrain_Tests_Count Global Variable

See Also: Global Variables Used by Data Dictionaries, Constrain_Found_Count, Constrained_Find, Constraint_Set, Constraint_Validate

Purpose

To determine how many records are being tested in a constrained find.

Type

Integer

What It Does

This integer increments continuously while a program runs. It contains the number of records tested by the constraint system.

Notes

  • You must initialize constrain_tests_count to zero (0) at the point where you wish to begin counting.


Err

Err Global Variable

See Also: Global Variables Used by Data Dictionaries

Purpose

To provide a means for determining if an error has been generated, and for restoring the error indication to negative.

Type

Boolean

What It Does

Whenever a runtime error occurs in Visual DataFlex, Err is set true. After occurrence of the first error, Err remains true until it is reset false by an explicit command. So long as error routines in your program reset Err false, Err may be used to control actions on the condition of an error's having occurred.

If (Err) send Stop_Box "An Error was Encountered"

move False to Err

If Err is true when the first line above is executed, it displays the "An Error was Encountered". The next line unconditionally resets Err false.

If (Err) Send DoUpdate

If Err is true when this line of code is executed, Procedure DoUpdate is executed. DoUpdate would typically have a "move False to Err" line in it.

Notes

  • Never rely on the value of the Err indicator other than on the line immediately following the line of code that sets it. Many different commands and messages alter the value of Err and other global indicators.

  • Err remains true until your program or the system issues a "move False to Err" command. These commands make it possible for you to switch Err on or off at any point in your program, to provide any error action desired.

  • The value of the Pre defined Variable lasterr may be managed so as to provide any desired error message independently of which error was originally triggered.

  • The on error gosub command also provides action when an error (any error) is triggered. If however, Err is true when an error is triggered, on error gosub will have no effect (the error will not be trapped).

  • To suspend automatic functions (save, clear, delete) of the enter macro, you can "move True to Err" inside the pertinent user-modifiable procedure(s) and the function will not be performed.


Errline

Errline Global Variable

See Also: Err, Error Command

Purpose

To identify the program command line on which an error was last triggered.

Type

Integer

What It Does

When a runtime error occurs, DataFlex moves the number of program line on which the error occurred to errline. By use of this value, you can provide error action in your program which varies according to where in the program it occurred.

if (errline = 23) Showln "Ignore this error"

This command would cause any error triggered on Line 23 of the program to be ignored.

Notes

  • You can use the errline number with move commands to trigger further messages and command sequences.

  • The value of errline may be compared to number of the line on which a label is located, so long as the label has been executed at least once. The name of the label must be in parentheses. This is useful in error routines which you supply yourself (see On error Command).

if (errline > C_OBJECT_SECTION) abort

In this example, execution would end if an error were generated on a line below the constant C_OBJECT_SECTION.

  • The line number in errline is the compiled command line number, not the line count in your source code. A printout of the compile time listing will enable you to identify line numbers in your program.


Error_Object_id

Error_Object_id Global Variable

See Also: Err, Error Command, Error_Report Command

Purpose

To identify the object to be used for handling of error reports.

Type

Integer

What It Does

When the error package is used, it creates an instance of the ErrorSystem class. When this object is created, the value of its object_id is moved to predefined variable error_object_id. When the value of error_object_id is greater than 0, as it is after this event, error events not diverted or deferred by an on error routine in force produce a message to the error object.

When error_object_id is zero, as it is before an error object has been created, error events not diverted or deferred by an on error command are reported on a single line at the bottom line of the screen. When the value 1 has been moved to error_object_id, error events not deferred or diverted send a message to the object that currently has the focus. This method is to be used where context-sensitive error handling is desired.

Notes

  • Error objects can also be activated from error handling routines executed through an on error command by inclusion of an error lasterr command for those errors for which such handling is desired.

  • At such points in the program as you may wish to defeat error handling by the error object, you may move 0 or -1 to error_object_id, and move its original value back to it when you wish to restore the handling.

  • "Fatal" errors, if not trapped by the error object, will abort the running program.

  • Error 10 (Out of memory) cannot be trapped or deferred. It is always reported immediately.


File_Number

File_Number Global Variable

Purpose

Stores the table number of the table in the current filelist.

Type

Integer

What it does

TableName.File_Number contains the table number of the data table referenced by TableName in the current filelist.

Example

integer hTable

open Customer

move Customer.File_Number to hTable

Notes

  • File_Number is not a global variable by itself. It must be used following "TableName."


Found

Found Global Variable

See Also: Global Variables Used by Data Dictionaries, Constrained_Find, Constraint_Validate, Find, Open, Vfind

Purpose

To indicate the success or failure of the last find.

Type

Boolean

What It Does

Whenever a find command is executed, the Found predefined indicator is set. If the find is successful, Found is set true. If the find is unsuccessful, Found is set false. This allows you to program the appropriate action when a find command finds a record.

find eq Parts.Code

If (Found) Send DoUpdate

If a record in database table Parts is Found with the value of Field code equalling the value in the buffer, (Found is true), the DoUpdate method is called.

The constrained_find command also sets Found, but unlike find, it will bring a new record into the buffer even with Found false.

Notes

  • Never rely on the value of the Found indicator other than on the line immediately following the line of code that sets it. Many different commands and messages alter the value of Found and other global indicators.

Example

clear Parts

repeat

find gt Parts.Code

If (Found) Begin

// do something else

End

Until Not (Found)

The sample code above attempts to loop through all records in the Parts table. The problem is that code executed inside the if (Found) begin...end block of code may change the value of Found. If the value of Found is changed to False by the use of another command or message, this could result in the loop ending before all records have been processed by the loop.

The sample code below solves this problem by resetting the value of Found to True at the end of the if (Found) begin...end block of code, ensuring that the loop will continue after any find gt that successfully finds a record.

clear Parts

repeat

find gt Parts.Code

If (Found) Begin

// do something else

move True to Found // reset Found for repeat...until loop

End

Until Not (Found)

  • Found is also set by the String commands replace and pos to indicate whether the substring being searched for was found.

  • Found is set by the open command to indicate whether the file on which open was attempted was in fact opened.

  • The constraint_validate command sets Found.

  • The FindErr Predefined Indicator is set at the same times as Found, and to the opposite status (true when Found is false, false when Found is true).

  • The value of Found is set by the most recent find, (replace, pos, open, constrained_find, etc.) regardless of where it was performed. To ascertain the state of a record buffer at any point other than immediately after the find, use status TableName for the buffer in question.


LineCount

LineCount Global Variable

See Also: Direct_Output, Output, Write

Purpose

To return the number of lines output since the last formfeed.

Type

Integer

What It Does

Linecount is intended to keep track of the number of lines of the current output page which have been used as a program outputs through the output and writeln commands. Every time an image is output the number of lines in that image is added to linecount. Every time a writeln command is executed, linecount is incremented by one. Every time a formfeed command is executed, a new page is considered to have been started, and linecount is zeroed.

Move 0 To Linecount

Writeln "Line One"

Writeln "Line Two"

Showln Linecount

Writeln "Line three"

Showln Linecount

In this example, the first Showln command would display the number 2, since it occurs after two lines are written to the sequential I/O channel. The second Showln will display 3.

The report class uses linecount to calculate the number of lines remaining unused on the current page so that they can start a new page when the current page has insufficient space remaining to accommodate the next output image.

Notes

  • Linecount counts lines output to a file when a file is named in the direct_output command, but it does not count output done through the show or showln commands.

  • Linecount is maintained in a separate value for each input/output channel in use in the program.


Self

Self Global Variable

Purpose

Stores the object ID of the current object.

Type

Integer

What It Does

The Self keyword is defined as a reference to the current object (current instance of the class). Wherever a statement requires a handle to some object the Self keyword can be used when you wish to reference the current object.

The current object is whatever object is currently executing code. For example, if you click on a Button object it will execute its OnClick method. During execution of the OnClick method that particular Button is the current object.

The identifier Current_Object is a synonym for Self.


Seqeof

SeqEOF Global Variable

See Also: Sequential File I/O, Close_Input, Close_Output, Direct_Input , Direct_Output, Read, Read_Block, Readln

Purpose

To indicate that the end of a sequential input file has been reached.

Type

Boolean

What It Does

When read_block, read or readln encounters an end of file (eof) character, it sets seqeof true. If you use the direct_input command to open a file that is not found, seqeof is set true.

Seqeof is commonly used to control the execution of loops that read data from sequential files.

Open Trees

Direct_Input "trees.txt"

If (Not(Seqeof)) Begin

Repeat

Clear Trees

Readln Trees.Species Trees.Height

Save Trees

Until (Seqeof)

End

In this example, input file TREES.TXT is opened and, if it is found, data is read from it into new records of Database File trees. When the end of the file is reached, seqeof is set true, and the repeat ... until loop terminates (abort). If TREES.TXT is not found in the directory, seqeof will be set true by the direct_input command, and the repeat ... until loop loop will never execute.

Notes

  • Never rely on the value of the seqeof indicator other than on the line immediately following the line of code that sets it. Many different commands and messages alter the value of seqeof and other global indicators.

  • Different operating systems indicate eof in different ways. Visual DataFlex interprets EOF in whatever way it is indicated in the host operation system and sets seqeof so that the condition may be dealt with a single version of the program whose commands are not operating system-dependent.

  • The following commands set seqeof false unconditionally: close_input, close_output, and direct_output.


Seqeol

SeqEOL Global Variable

See Also: Sequential File I/O, Read, Readln

Purpose

To indicate that the end of a line has been reached in a sequential data file.

Type

Boolean

What It Does

When a read command encounters an end of line (eol) character in a sequential input file, it sets seqeol true. The readln command, however, sets seqeol false and allows subsequent read commands to function.

String sElement

Direct_Input Aircraft.Txt

Repeat

Repeat

Read sElement

Show sElement ", "

Until (Seqeol)

Readln

Showln

Until (Seqeof)

In this example, input file AIRCRAFT.TXT is opened, and delimited data items are read into string variable sElement and shown to the screen. When an end of line is detected, the repeat ... until loop terminates and the readln command discards the EOL and sets seqeol false. The showln command outputs a carriage return/linefeed to the screen, and execution loops back to the next line of input data.

Notes

  • Never rely on the value of the seqeol indicator other than on the line immediately following the line of code that sets it. Many different commands and messages alter the value of seqeol and other global indicators.

  • Readln always reads to and including the end of line (EOL) character, and sets seqeol false.

  • Without readln, read commands cannot read past an EOL.

  • Different operating systems indicate EOL in different ways. Visual DataFlex interprets EOL in whatever way it is indicated in the host operation system and sets seqeol so that the condition may be dealt with a single program whose commands are not operating system dependent.

  • Read_block does not respect end-of-line markers.


Miscellaneous Topics

Contents:

  • Implementing Callback Functions

  • Variable Parameter Lists


Implementing Callback Functions

See Also: Call_Driver, Copy_Db, Copy_Records, Structure_End, and Sort

Purpose

To enable objects executing long-duration processes to report status of the process and to interrupt it in the event invalid data is encountered.

Syntax

Function Callback string CallbackMessage integer CallbackType ;

returns integer

: (optional code for progress-monitoring display)

: (code to set result value True or False //false =continue)

Function_Return result

End_Function

Argument Explanation

CallbackMessage A string to receive the first parameter of the received message, being progress-display text or progress-extent values.

CallbackType An integer to receive the second parameter of the received message, being a classification of the first parameter as follows:

  • DF_MESSAGE_PROGRESS_TITLE A caption explaining display of progress values.

  • DF_MESSAGE_PROGRESS_VALUE up to two values indicating extent of progress of the process.

  • DF_MESSAGE_HEADING_1 Level 1 heading

  • DF_MESSAGE_HEADING_2 Level 2 heading

  • DF_MESSAGE_HEADING_3 Level 3 heading.

  • DF_MESSAGE_HEADING_4 Level 4 heading.

  • DF_MESSAGE_HEADING_5 Level 5 heading.

  • DF_MESSAGE_TEXT An unclassified message.

  • DF_MESSAGE_WARNING A warning message.

What It Does

Get_callback is a message sent (with parameters) by a number of commands that carry out long-duration processes on database files. These include the call_driver, copy_db, copy_records, structure_end, and sort commands, as well as various tools in which such processes are performed.

This message is sent once every 100 cycles (usually records) of the process in question to the object that called the process.

The (receiving) function itself is not defined anywhere in Visual DataFlex. What is defined is the get_callback message and its parameters. These are defined in the commands that send it. Also defined in most of these commands are routines to act on the value returned by the callback function defined in the object receiving the message. If True is returned, the process will abort; False will allow it to continue.

The first of the two parameters sent with get_callback is display text or a pair of integer values separated by a comma (to drive an extent-of-progress report). The second parameter is a classification for the content of the first parameter. The types may be any of those shown above for callback_type. Special values for the parameters peculiar to each command that sends this message are documented with each command. The callback function you define should be able to handle each of the values sent by the command(s) that send to it.

Notes

  • The frequency (number of cycles) of sending get_callback can be adjusted by changing the value of the DF_RUNTIME_PROGRESS_FREQUENCY attribute of the embedded database driver. Its default value is 100.

  • Use of the callback function is optional in the commands that support it. Typically, the option is elected by identifying the receiving object in the command line. If the receiving object either does not exist or has no callback definition, an error will be triggered.


Variable Parameter Lists

Num_Arguments (Variable Parameter Lists)

See Also: Function, Procedure

Purpose

To provide the number of arguments passed with each invocation of a procedure or function.

Type

Integer

What It Does

Num_arguments carries the number of arguments passed to a function or procedure. It can be used only within a function or procedure. Its value can change with each invocation of the function or procedure.

Function Mean Global Integer i1 Integer i2 Integer i3 Returns Integer

integer iArgs

move Num_Arguments to iArgs

if (iArgs=3) Function_Return ((i1 + i2 + i3) / iArgs)

else if (iArgs=2) Function_Return ((i1 + i2) / iArgs)

else if (iArgs=1) Function_Return i1

else Function_Return 0

End_Function

In this example, the function Mean is defined using three parameters, integers i1, i2, and i3. The Function_Return statement contains an expression to calculate the mean of the values input. The function for calculating the return value uses Num_Arguments to provide a value appropriate to the number of arguments passed with each invocation.

Notes

  • Num_arguments is a local variable. That is, it is local to each function or procedure. Therefore, a variable of that name might concurrently have different values in two or more functions or procedures.


Operators

This section describes each member of the Visual DataFlex set of operators.

Operator List

Operator | Purpose
AND | To combine two variables into one expression that is true when both variables are true, and false when either or both variables are false.
Contains | Returns true from an expression in which the value of the second string is contained within the value of the first string.
IAND | To return the bitwise AND of two integer values.
IOR | Performs a bitwise OR on two integral values.
Matches | To return true from an expression in which the value of the first string matches the value or the ambiguous pattern specified by the value of the second string.
Max | To return the greater of two values from an expression.
Min | To return the lesser of two values from an expression.
OR | To combine two variables into one expression that is true when either variables are true, and false only when both variables are false.


AND Operator

See Also: OR operator, IAND operator, IOR operator, if command, if function, until, while

Purpose

To combine two variables into one expression that is true when both variables are true, and false when either or both variables are false.

Syntax

( {var1} and {var2} )

where {var1} and {var2} may be either expressions, variables or constants.

What It Does

When two variables are connected within an encompassing expression by and, the encompassing expression evaluates as true when both variables are true.

Example

move (bFriday and b5PM) to bHappyHour

if (bHappyHour=True) send Info_Box "It's 5 PM on Friday, stop working and go to the bar!"

In this example, if the Boolean variable bFriday and the Boolean variable b5PM are both true, the value of bHappyHour will be true. In that case, an Info_Box MessageBox will appear to tell the user to stop work and celebrate Happy Hour.

Multiple ands may be used to link more than two logical expressions into a single expression that evaluates true when all component expressions are true, and false when one or more component expression is false:

Example

Boolean bHappyHour

move (bFriday and b5PM and bWorkIsDone) to bHappyHour

if (bHappyHour=True) ;

send Info_Box "It's 5 PM on Friday, stop working and go to the bar!"

else ;

send Info_Box "It's not time to party yet, keep working!"

In this example, if all three Boolean variables, bFriday, b5PM and bWorkIsDone are true, the value of bHappyHour will be true. If any one of bFriday, b5PM and bWorkIsDone is false, then bHappyHour will evaluate to false.

Notes

  • There is no symbolic substitute for the word and.

  • When ands and ors are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(true and false or true and false)

would evaluate as false, while

(true or false and true or false)

would evaluate as true.

  • When using variables other than Booleans (e.g. integers), and expressions do not necessarily return a value of 1. They return the second non-zero argument. Thus,

(5 and 4)

would evaluate as 4, while

(-2 and 3)

would evaluate as 3.


Contains

Contains Operator

See Also: Constrain Command, Pos Function, Uppercase Function, Lowercase function

Purpose

Returns true from an expression in which the value of the second string is contained within the value of the first string.

Syntax

( {host-string} contains {sub-string} )

where {host-string} is the string being parsed; and {sub-string} the string being searched for. {host-string} and {sub-string} can be either a literal or a string variable.

What It Does

When the value of {sub-string} is present in the value of {host-string}, a contains expression evaluates to 1 (true), and when it is not, it evaluates to 0 (false).

Example

string sTitle

if ((sTitle contains "engineer") OR (sTitle contains "manager")) ;

send DoCalcBonus

In this example, the procedure DoCalcBonus is called for any value of the string variable title that contains either "engineer" or "manager".

Example

string sFruit

if (uppercase(sFruit) contains "APPLE") ;

send DoMakeCider

In this example, the procedure DoMakeCider is called whenever the value of the string variable sFruit is made up of the letters of "APPLE", regardless of their capitalization.

Notes

  • Contains does not support wildcard characters (* and ?). It treats these characters only as literals.

  • Contains does not return the position in {host-string} at which {sub-string} is found, nor the number of times it is present. The pos function may be used to determine the position of {sub-string} in {host-string}.

  • Contains does not recognize a match between the upper and lower cases of the same letter. The uppercase or lowercase functions may be used to disable this behavior.


IAND Operator

See Also: AND operator, IOR operator, Hi function, Low function

Purpose

To return the bitwise AND of two integer values.

Syntax

( {value1} IAND {value2} )

where {value1} and {value2} may be either expressions, variables or constants.

What It Does

When two values are connected with an encompassing expression by IAND, the encompassing expression evaluates as the value of a binary number derived from the other two values as 1 in positions where both values are 1, and 0 in positions where either value is 0.

Example

move (iMode IAND iForm) to iForm

In this example, 1s in the binary form of the value of iForm are changed to 0s, except for those positions where the binary form of the value of iMode has 1s.

Multiple IANDs may be used to link more than two values into a single expression that evaluates as the bitwise and of all the values in the expression:

Example

while (iPass1 IAND iPass2 IAND iPass3)

// some code in loop

loop

In this example, the block of commands controlled by while is executed until no position in the binary form of the values of all three variables iPass1, iPass2 and iPass3 contains a 1.

Notes

  • There is no symbolic substitute for the word IAND

  • When IANDs, iors and other arithmetic operators are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(1 IAND 2 IOr 3 IAND 4)

would evaluate as 0, while

(1 IOr 2 IAND 3 IOr 4)

would evaluate as 7.


IOR Operator

See Also: AND operator, OR operator, IAND operator, Hi function, Low function

Purpose

Performs a bitwise OR on two integral values.

Syntax

( {value1} IOR {value2} )

where {value1} and {value2} may be either expressions, variables or constants of either integral type, Char / UChar / Short / UShort / Integer / UInteger / BigInt / UBigInt.

What It Does

When two values are connected with an encompassing expression by IOR, the encompassing expression evaluates as the value of a binary number derived from the other two values as 1 in positions where either value is 1, and 0 in positions where both values are 0.

Example

move (iMode IOR 1) to iAltMode

In this example, the binary form of the value of iAltMode is set to the value of iMode with its last bit set to 1, regardless of whether the last bit of the binary form of iMode is 1 or 0.

Multiple IORs may be used to link more than two values into a single expression that evaluates as the bitwise or of all the values in the expression:

Example

repeat

// some code in loop

until (iTop IOR iMiddle IOR iBottom)

In this example, the block of commands controlled by until is executed until no position in the binary form of the values of the variables iTop, iMiddle and iBottom contains 1.

Notes

  • There is no symbolic substitute for the word IOR.

  • When iands, IORs and other arithmetic operators are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(1 iand 2 IOR 3 iand 4)

would evaluate as 0, while

(1 IOR 2 iand 3 IOR 4)

would evaluate as 7.


OR Operator

See Also: AND operator, IAND operator, IOR operator, if command, if function, until, while

Purpose

To combine two variables into one expression that is true when either variables are true, and false only when both variables are false.

Syntax

( {var1} or {var2} )

where {var1} and {var2} may be either expressions, variables or constants.

What It Does

When two variables are connected within an encompassing expression by or, the encompassing expression evaluates as true when either or both variables are true.

Example

move ((nWealth > 15000) or (nIncome > 5000)) to bRich

In this example, if either nWealth is greater than 15000 or nIncome is greater than 5000, the value of bRich will be true. Only if both expressions are false, nWealth is less than 1500 and nIncome is less than 5000, will bRich evaluate to false.

Multiple ors may be used to link more than two logical expressions into a single expression that evaluates true when any component expression is true, and false when all component expressions are false:

Example

move ((nWealth > 15000) or (nIncome > 5000) or (nInheritance > 250000)) to bRich

In this example, if either nWealth is greater than 15000 or nIncome is greater than 5000 or nInheritance is greater than 250000, the value of bRich will be true. Only if all 3 expressions are false, nWealth is less than 1500 and nIncome is less than 5000 and nInheritance is less than 250000, will bRich evaluate to false.

Notes

  • There is no symbolic substitute for the word or.

  • When ands and ors are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(true and false or true and false)

would evaluate as false, while

(true or false and true or false)

would evaluate as true.

  • When using variables other than Booleans (e.g. integers), or expressions do not necessarily return a value of 1. They return the first non-zero argument. Thus,

(5 or 4)

would evaluate as 5, while

(-2 or 3)

would evaluate as -2


Matches Operator

See Also: Constrain Command, Contains operator, Pos Function

Purpose

To return true from an expression in which the value of the first string matches the value or the ambiguous pattern specified by the value of the second string.

Syntax

( {sub-string} matches {host-string} )

where {host-string} is the string being parsed; and {sub-string} the string being searched for. {host-string} and {sub-string} can be either a literal or a string variable.

What It Does

The matches operator compares the value of {sub-string} with the value of {host-string} and returns 1 (True) from the expression if their values are the same and 0 (False) if they are not. A question mark (?) may be used in {host-string} to permit a match with any character in {sub-string}, and an asterisk (*) may be used in {host-string} to permit a match wit any character or characters. Any character given in {host-string} after an asterisk are of no effect -- a match will be reported regardless of what characters are in {sub-string} after the position of the asterisk.

Example

if ((Clan.Name matches "Frazier") OR (Clan.Name matches "Fra?er")) ;

send DoGoHighland

In this example, the procedure DoGoHighland is called when the Name field of the Clan table is "Frazier" or "Fra" followed by any letter, followed by "er".

Example

if (Lowercase(Clan.Name) matches "frazier*") ;

send DoGoHighland

In this example, the procedure DoGoHighland is called whenever the value of the Name field of the Clan table is made up of the letters "frazier" regardless of their capitalization. Note that the match is only valid regardless of capitalization because the data is lowercased before the matches operator is executed.

Notes

  • Wildcard characters (* and ?) are evaluated simply as literals (asterisk and question mark, respectively) in {sub-string}. They function as wildcards only in {host-string}.


Max Operator

See Also: Min Operator

Purpose

To return the greater of two values from an expression.

Syntax

( {value1} max {value2} )

where {value1} and {value2} may be either expressions, variables or constants.

What It Does

When two values are connected with an encompassing expression by max, the encompassing expression evaluates as the greater of the two values.

Example

move (nBalance max 0) to nInvoiceAmount

In this example, if nBalance were greater than 0, the value of nBalance would be moved to nInvoiceAmount. Otherwise, zero would be moved to nInvoiceAmount.

Multiple maxs may be used to link more than two values into a single expression that evaluates as the maximum of all the values in the expression:

Example

move (nBalance max 0 max nLastTransaction) to nCollectAmount

In this example, the greatest value among the values nBalance, 0 and nLastTransaction is moved to nCollectAmount.

Notes

  • There is no symbolic substitute for the word max.

  • When mins, maxs and other operators are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(1 max 2 min 3 max 4)

would evaluate as 4, while

(1 min 2 max 3 min 4)

would evaluate as 3.


Min Operator

See Also: Max operator

Purpose

To return the lesser of two values from an expression.

Syntax

( {value1} min {value2} )

where {value1} and {value2} may be either expressions, variables or constants.

What It Does

When two values are connected with an encompassing expression by min, the encompassing expression evaluates as the lesser of the two values.

Example

move (nWeightBill min nWeightJoe) to nLighterPerson

In this example, if Bills weighs less than Joe, the value of nWeightBill would be moved to nLighterPerson. Otherwise, nWeightJoe would be moved to nLighterPerson.

Multiple mins may be used to link more than two values into a single expression that evaluates as the miniimum of all the values in the expression:

Example

move (nWeightBill min nWeightJoe min nWeightCory) to nLighterPerson

In this example, the weight of the lightest person among Bill, Joe and Cory is moved to nLighterPerson.

Notes

  • There is no symbolic substitute for the word min.

  • When mins, maxs and other operators are intermingled in a single expression without grouping parentheses, evaluation proceeds from left to right with each operator connecting the next expression with the result of all previous (left-lying) ones.

(1 max 2 min 3 max 4)

would evaluate as 4, while

(1 min 2 max 3 min 4)

would evaluate as 3.


Obsolete Commands, Functions and Other Symbols

Purpose of the Obsolete Section

Anything documented in the obsolete section may or may not be up-to-date with the current revision of Visual DataFlex, with the exception of the first paragraph of each obsolete item, which should point the developer to the replacement of the obsolete item -- this is the only purpose for documenting these obsolete items here at all. Obsolete items are also not included in the help index, you can only find them by looking here or by going to the Search tab of the help.

DataFlex History

The Visual DataFlex command language has a long history stretching back to the original procedural DataFlex language that ran on character-mode systems.

Each step of the evolution; from a procedural language to object-oriented; from character mode to Windows 3.1 from Windows 3.1 to Windows 95, etc. bought about new and improved ways of performing certain operations. This necessitated many changes and additions to the command language. The result is that after many iterations the DataFlex language allowed too many ways of performing the same operation, whereas only one way was appropriate or necessary.

Beginning with Visual DataFlex revision 6.0, the documented DataFlex command set was made simpler, more focused, easier to learn and easier to use. All the obsolete pieces will eventually be removed from the Visual DataFlex documentation and sample applications.

Each obsolete command, function and symbol should function as in earlier versions of Visual DataFlex, unless noted that it now works differently. However, you are encouraged not to use them when writing new code.

This section of the Language Reference alphabetically lists the obsolete commands, functions and symbols.


#REPLACE

Obsolete

This command is replaced by the Define command.

See Also

Purpose

To replace in compilation all occurrences of one token source code with another.

Syntax

#REPLACE {existing} {replacement}

What It Does

#REPLACE causes the compiler to replace any subsequent occurrence of a symbolic token with some other symbol. Example:

#REPLACE C_iMaxLines 100

In the above example, any subsequent occurrence of the token C_iMaxLines will be replaced with the number 100 by the compiler.

Other examples of #REPLACE follow:

#REPLACE S_nGrossPay (nHours * nRate)

#REPLACE S_nNetPay (nGrossPay – nDeductions)

Notes

  • #REPLACE must be spelled in capital letters.

  • #REPLACE does not affect portions of source code above the line on which it is placed. It only affects source code following it.

  • The Define command is better suited for declaring program constants.


Append (Obsolete Command)

Obsolete

This command is replaced by the Append function.

See Also

Purpose

To add the contents of one or more strings onto the contents of a string.

Syntax

append destination source [... source]

Argument Explanation

destination May not be a constant or an expression.

source May be any class of data.

What It Does

Append attaches the contents of one or more sources to destination. If the length of destination is set in the string command which established it to a length (###) shorter than the combined appended length, then only the first ### characters of the appended value remains in destination. No error is declared if this occurs.

To append to an existing string:

append size weight " cat"

If size has a value of big. and if weight has a value of fat, this command gives size a value of big fat cat.

To append to an empty string:

1) Make the string empty.

2) Append to it.

move "" to size

append size weight " cat"

Upon declaration with the string command, a string is "full" of spaces, rather than empty. Append does not clear these spaces, nor any other contents which may be in destination. Therefore, the move command above, followed by a pair of quotation marks ("") is required to clear the contents of size even if size has never been used before. If weight has a value of fat, the append command above gives size a value of fat cat.

Notes

  • You can use other string commands, such as right, ascii, character, etc. to create the values of the sources and destination.

  • Use care not to lose characters when you append to destination. If you append two 10 character variables to a destination which itself has a declared length of only 10 characters, the resulting string will still only be 10 characters long, there will be no error message, and the resulting string will be truncated on the right.

  • With string commands such as append, use in memory variables rather than windows or fields to preserve the integrity of the data. Windows always strip trailing spaces, and fields maintain their full defined length with padded spaces. These characteristics may frustrate the attainment of the desired results of using append.

  • The trim command is an effective way to remove spaces from fields before using append.

Wrong:

open companies

find companies by recnum

append companies.name " Incorporated"

save companies

In this example, the word .Incorporated (with a leading space) is appended to the value of the name field of Database File companies. Since the field contents always contain spaces out to the full defined length of the field, this command would leave the contents of the field unchanged.

Right:

string tempstr

open companies

find companies by recnum

trim companies.name to tempstr

append tempstr " Incorporated"

move tempstr to companies.name

save companies

In this example, the contents of Field name in Database File companies are trimmed to a temporary variable (tempstr). The word .Incorporated (with a leading space) is then appended to tempstr, and the appended value is moved back to companies.name.

  • Although append is normally used with String type variables, it may be used with any type, or combination of types, of variable.

integer shapes kinds

move 34 to kinds

move 12 to shapes

append kinds shapes

This will place the value 3412 in kinds, since the 12 and the 34 are appended, not added.

  • Source and destination may be the same variable. Where this is the case, appending will double the content of the original variable, up to the declared length in the string command which established the variable.


ASCII (Obsolete Command)

Obsolete

This command is replaced by the Ascii function.

See Also

Purpose

To place the ASCII value of the first character of a string in a variable.

Syntax

ascii ascii_char to ascii_num

Argument Explanation

ascii_char May be of any data class. It is treated as a String regardless of its actual type.

ascii_num May not be a constant or an expression, and may be of any type.

What It Does

Ascii converts a single ASCII character (the first character in ascii_char) to the number (ascii_num) associated with the character in the ASCII character table.

integer code

ascii "AARDVARK" to code

These commands would place a value of 65 in code (the first character of AARDVARK is A, and the ascii value of A is 65).

Notes

  • Ascii acts only on the first character of ascii_char. Succeeding characters in the value are ignored.

  • The character command does the reverse of ascii; it converts a numeric value into the ASCII character for that value.

  • If ascii_char is empty, the value of ascii_num will be set to zero.

  • The ascii command renders ASCII values as decimal numbers (not hexadecimal).

  • Ascii_char and ascii_num may be the same variable.


Autoback Field Property

Obsolete

This option is obsolete. This field property is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To cause the cursor to move from the first position in the item to the previous item when the left arrow or Backspace key is pressed.

Syntax

set field_options field file.field to dd_autoback

or

entry_item file.field {autoback}

What It Does

Autoback is used on a set field_options or entry_item command line. When the cursor is in the first position in an item connected to a field having the option and the left arrow or Backspace is pressed, the cusor will move to the last position in the previous item.

entry_item customer.address {autoback}

In this example, if left arrow is pressed when the cursor is in the first position in the item addressing Field address in File customer, it will move back to the last position in the previous item.

Notes

  • If autoback is in force on the first item in a DEO and the left arrow or Backspace accelerator key is pressed when the cursor is in the first position of that item, the cursor will move as though the key assigned to kswitch_back had been pressed.

  • Autoback behavior is different from pressing Previous Item. When Previous Item is pressed, the cursor goes to the first position of the previous item, while autoback places the cursor at the last position


Autofind Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To execute an automatic find eq (equals) on an entry_item command.

Syntax

set field_options field file.field to dd_autofind

or

entry_item file.field {autofind [... option]}

File.field must have a Main Index in the definition of file.

What It Does

Autofind performs a find eq (equals) by the main index of file.field when an entry_item is executed on field. If a record is found whose value in the main index of file.field exactly matches the values in the item and any other items whose fields participate in the index, it is displayed to the screen. If no such record is found, the cursor exits the item normally and no record is moved into the buffer. No error will be declared.

set field_options field vendor.id_code to dd_autofind

When the cursor exits any item attached to Field id_code in File vendor after typing a value into it, DataFlex will search the main index for id_code in Database File vendor and display the record whose index value matches those in the screen buffer for the fields which make up the index. If there is no vendor record with matching id_code index value, the cursor proceeds normally to the next item and no error is reported.

Notes

  • Autofind uses the Main Index for file.field to search by.

  • Do not use autofind with a file.field whose Main Index is non unique, since the absence of the record number in the entry will prevent an exact match. Where you wish to find by a non unique index, use autofind_ge.

  • Where you are autofinding by a multi segment index, place the autofind option on the last entry_item command that addresses a field that participates in the index. For autofind to work, it is necessary that values be in the screen buffer for all segments of the index, although it is not necessary that they be addressed by entry_item commands in the same order as they are in the index. The file definition for file must specify the search index as the Main Index for file.field.

  • If you want to execute an automatic find ge (greater than or equal to) command, use autofind_ge.

  • If entry_item commands address another file(s) to which file is related as child, data from related to record(s) in the parent file(s) also will be found and displayed.

  • If used together with findreq, autofind will require users to enter a valid existing key before continuing.


Autofind_ge Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To execute an automatic find ge (greater than or equal to) on an entry_item command.

Syntax

set field_options field file.field to dd_autofind_ge

or

entry_item file.field {autofind_ge [... option]}

File.field must have a Main Index in the definition of file.

What It Does

Autofind_ge performs a find ge (greater than or equal to) by the Main Index of file.field when an entry_item command line is executed on file.field. If a record is found whose value in the main index of df_filename.field exactly matches the values in the item and any other items whose fields participate in the index, it is displayed to the screen. If no such record is found, the record whose index value next follows that in the item(s) is displayed.

set field_options field vendor.id_code to dd_autofind_ge

When the cursor exits any DEO item attached to Field id_code in File vendor, DataFlex will search the Main Index for id_code in Database File vendor and display the record whose index value matches those in the item(s) for the field(s) which makes up the index. If there is no vendor record with matching id_code index value, the record whose index value next follows that in the item(s) is displayed.

Autofind_ge is useful for finding records on partial entries to items or, in multi segment indexes, by keys for only the first segment or segments (rather than all of them). All non unique indexes, for example, are multi segment (being composed of at least one field plus the record number), and since the record number is not usually a known entered key value, autofind_ge is the only way to automatically find by a non unique index.

It is not necessary that fields for which entered key values are used be addressed by entry_item commands in the same order as they are in the index. The file definition for file must specify the search index as the Main Index for file.field.

Notes

  • Autofind_ge uses the main index for file.field to search by.

  • You may use autofind_ge with any indexed file.field regardless of whether the index is unique or non unique.

  • Where you are autofind_geing by a multi segment index, place the autofind_ge option on the last field or the entry_item command that address the last field which participates in the index for which you wish to use an entered key value. If any field which comes before the one with the autofind_ge option on it in the index lacks an entered key value in its item, the value of that field will be considered empty (for ASCII fields) or minus infinity (for other types of fields) for purposes of the find. The found record will be the one whose value for the first such field is the lowest in the index.

  • If you want to execute an automatic find eq (equals) command for an exact match with the item contents, use autofind.

  • If entry_item commands address another file(s) to which file is related as child, data from related to record(s) in the parent file(s) also will be found and displayed.

  • Autofind_ge will always find a record, unless the file has no records in it (is empty).


Autopage Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To imply image windows consecutively for addressing by succeeding window addressing commands that omit explicit window references.

Syntax

autopage pagename[###]

If ### is omitted, autopageing will begin with the first window of pagename.

What It Does

Autopage is a programming convenience that makes it unnecessary to refer explicitly to windows when using print. It is useful where a series of such commands addresses the windows of one or more images consecutively.

Autopage supplies implicit window references to these commands in the order in which they appear in pagename, from left to right, going down the page from top to bottom.

Autopage may be used in either of two ways:

1. With the image name only:

autopage vendor

print vend.name

print vend.address

print vend.city

Here three print commands access the first three windows of an image named vendor. The equivalent commands without autopage would read as follows:

print vend.name to vendor.1

print vend.address to vendor.2

print vend.city to vendor.3

2. With the image name and starting window:

autopage employee 6

print emp.fica

print emp.withholding

Here autopage covers only part of an image (employee), starting with the sixth window.

The equivalent commands without autopage would be:

print emp.fica to employee.6

print emp.withholding to employee.7

Notes

  • Window addressing commands that rely on autopage must address windows in the order in which they appear, with no gaps. However, autopage does not have to begin with the first window in an image, nor end with the last one.

  • Commands that address windows explicitly may be intermingled among commands that rely on autopage without affecting autopage's window counter.

  • In the report object, each procedure_section command supplies an automatic autopage command.


Autoreturn Field Property

Obsolete

This option is obsolete. This field property is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To cause the cursor to move from the last position in an item connected to a field to the next item when keyboard entry exceeds the capacity of the field.

Syntax

set field_options field file.field to dd_autoreturn

or

entry_item file.field {autoreturn}

What It Does

Autoreturn is used on a set field_options line in a DataDictionary object or on an entry_item command line. When the cursor is in the last position in an item connected to file.field and a user continues to enter keystrokes, the cursor will go to the first position of the next item, and entry will continue in that item.

entry_item customer.phone_area{autoreturn}

entry_item customer.phone_num

In this example, if data entry continues after the item attached to Field phone_area in File customer is filled, the cursor will go to the next item, customer.phone_num, and continue data entry there.

When autoreturn is applied to a field through a DataDictionary object, the cursor does not move to the next field in the database file. It always moves to the next item of any DEO that is using the DataDictionary object. This will, in the typical case, presumably always be the same field and in turn, may often turn out to be the next field in the file structure.

Notes

  • If autoreturn is in force on the last entry_item in a DEO and data entry continues after that window is full, the cursor proceeds as though the key assigned to kswitch_next was pressed.

  • The DataFlex Configuration offers a global autoreturn option. To apply autoreturn selectively, this option must not be in force from Configuration.


Begin_constraints Command

Obsolete

Refer to the OnConstrain event in the DataDictionary class.

See Also

Purpose

To create a constraint or set of constraints for a dataset.

Syntax

Begin_constraints

What It Does

Begin_constraints identifies the beginning of a block of code containing a set of constraints. This command, together with the end_constraints command, can be used as a shortcut to defining constraints within a procedure. For example, the following two sets of code behave identically:

procedure constrain

constrain vndr relates to region

forward send constrain

end_procedure

begin_constraints

constrain vndr relates to region

end_constraints


Call Command

Calc, Calculate Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To evaluate an expression and move the result to an in-memory variable, field, or window.

Syntax

calc{ulate} source_expression to destination

Procedure must be previously defined in the program by the procedure command.

The number of values must match the number of arguments declared for procedure, and the type of each must match that of its respective argument.

What It Does

Calc evaluates an arithmetic expression (source_expression) and places the result in a variable (destination).

calc (23.9 *44.1) to result

Multiply 23.9 by 44.1 and place the product in Variable result.

calc (sales_date +30) to followup_date

Add 30 to the value of the Variable sales_date and place the sum in the Variable followup_date.

calc (parts.on_hand -1) to parts.on_hand

Subtract 1 from the value of the database element parts.on_hand and place the difference in parts.on_hand.

calc ((total +amount) /avrg) to avrg

Add the value of total to the value of amount, divide the sum by avrg, and place the quotient in avrg.

Notes

  • You may use calc, calculate and movenum interchangeably. If the type of destination is Number, the move command will also function similarly. The calc and calculate commands are provided primarily to enhance readability of programs.

  • DataFlex cannot calculate literal dates in expressions correctly.

  • calc (05/12/96 +30) to due_date

  • This command would put 5 divided by 12 divided by 96 plus 30 into due_date, not the desired result. Instead, use a Date-type variable to calculate on a date, as:

  • move 05/12/96 to invoice_date

  • calc (invoice_date +30) to due_date

  • Do not use calc to fill output windows in report programs, because calc does not update window accumulators, which may be needed in the subtotal and/or total sections. Only the print command should be used for this purpose. Print is capable of evaluating expressions.

  • To calculate the value of an expression which is in a String variable, put the name of the string inside of parentheses. Strings so used may contain only numbers and operators, not field, window or variable names.

  • move (3 +4) to astring

  • calc (astring) to anumber

  • Expressions in DataFlex are made up of combinations of operators (+, -, *, /,^), literal numbers, and/or references to database elements, in-memory variables, or windows. DataFlex evaluates expressions from the innermost parentheses outward, from left to right, without regard to any precedence of operators.


Call Command

Obsolete

This command is replaced by the Send command. For Web applications, see the Call function.

See Also

Purpose

To execute a global procedure.

Syntax

call procedure[value ... value]

Procedure must be previously defined in the program by the procedure command.

The number of values must match the number of arguments declared for procedure, and the type of each must match that of its respective argument.

What It Does

The call command executes the user defined procedure named procedure. Values are passed to the arguments peculiar to whatever procedure is called. The number and type(s) of the value(s) depend on those declared for the procedure being called.

call underwrite "male" 12/12/44 "nonsmoker"

In this example, Procedure underwrite is executed with three arguments (male, 12/12/44, and nonsmoker) passed to it.

After execution of the procedure, execution returns to the first line after the call command. Call is for use outside the UIMS (without the use ui command) in procedural (non-object-oriented) DataFlex programs.

Notes

  • Call functions similarly to the gosub command, except that it can pass arguments to the procedure to be executed. Call uses a procedure defined in a procedure ... end_procedure block, while gosub uses a label followed by a return command.


Capslock

Capslock Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To replace lower-case characters in entry items and output windows with upper-case characters.

Syntax

set field_options field file.field to dd_capslock

or

entry_item file.field {capslock}

What It Does

Capslock is used on an entry_item, format, or print command line. It automatically converts any lower-case characters in items to upper case (capital letters). It has no effect on non-alphabetic characters.

entry_item collect.subject {capslock}

format subheader1.3 thru subheader1.7 {capslock}

print employee.pay to body.2 {capslock}

In each of these examples, letters displayed in the value of the item or window(s) identified in the commands would be output in uppercase. In the case of the entry_item example, keyboard entries would be converted to uppercase as they were made.

set field_options field mail.country to dd_capslock

When this option is applied to a field in a DataDictionary object, it does not itself ever change the case of letters in the field data on disk. What it does is: (a) provide for display of the field data in upper case in all items of DEOs using the DataDictionary; and (b) provide for capitalization of all letters entered into such items by users. This second action assures that all input to the field through DEOs using the DataDictionary will reach the disk only with letters in upper case.

Notes

  • Capitalization (what character is the uppercase of which other character, and vice versa) is set in the character-translation function of the Configuration.


Chain

Obsolete

This command is replaced by the runprogram command.

Chain was used frequently in character-mode versions of DataFlex. The use of chain is discouraged in favor of runprogram in Visual DataFlex.

S ee Also

Purpose

Calls one Visual DataFlex program from another.

Syntax

Chain [Wait] {command-line} [Export_Files |Export_Only] [Seq_Export]

where {command-line} is an argument string that contains the name of the chained program and any parameters passed. If the name of the chained program or any of the parameters contain spaces, those arguments must be enclosed in quotation marks.

What It Does

Chain allows execution of an application to continue in another Visual DataFlex program. Chain is typically used to link together separate Visual DataFlex programs that belong to the same project. To call programs that are not Visual DataFlex applications, use the Runprogram command.

The chained program receives the command line passed. The format of the command line is a list of delimited parameters whose first element is the name of the Visual DataFlex program to execute. All parameters on the command line are separated by spaces, so if the parameters themselves have spaces, you will need to enclose these parameters in quotation marks, and the entire command line should be single-quoted.

Valid Windows file names may contain spaces, so the program that you are calling may need to be double-quoted. Here is an example that invokes a program named "New Prog" (note the space between the words), passing two parameters "parameter 1" and param2.

Chain Wait '"New Prog" "parameter 1" param2'

Here is an example that shows how the parameters are extracted from the command line (using the Cmdline command.)

String gsCommandLineParameter

Showln "In chained program."

Cmdline gsCommandLineParameter

Showln "Parameter 1: " gsCommandLineParameter

Cmdline gsCommandLineParameter

Showln "Parameter 2: " gsCommandLineParameter

Chain works in two different modes. Used by itself, chain terminates execution of the current Visual DataFlex program and immediately begins executing the new Visual DataFlex program. Used with the Wait option, Chain executes the new program, leaving the calling program suspended. The user may interact with the chained program. When the chained program finishes, the calling program becomes active again. Execution will continue in the original program at the command line that follows the Chain Wait.

The Export_Files option keeps the files of the calling program open after the chain. This allows file buffers to be shared across chained programs. All files will remain open when execution returns to the original program, including files originally opened in the chained program. To use the Export_Files option, the file needs to be opened in both programs.

Regardless of whether the Export_Files option is used or not, all record buffers active at the time of the chain remain active, with record data in them, while the secondary program is executing. When the chained program finishes, file processing can continue in the calling program. If the chained program deletes the calling program's active record, errors can occur when the calling program regains control.

The Export_Only option works similarly to the Export_Files option. The one difference is that files first opened by the chained program are closed automatically when execution returns to the original program. Files opened in the chained program that were open in the caller are not closed.

If Seq_Export is used, all sequential files opened by the original program remain open (and can be appended) by the chained-to program. If Seq_Export is not used, a sequential file written by the chained program will overwrite a file of the same name created by the original program.

Notes

  • Chain passes all global integer variables to the chained program. Global integers are created in a common area within the chained program and accessed in the order they are declared. Therefore, the first global integer variable in the caller is the same as the first global integer variable in the chained program. The second global integer variable in the caller is the same as the second integer variable in the chained program, and so forth. However, if the wait option is used, and execution returns to the old program, no values of global integer variables are passed back to the old program. The following example shows how the calling program can share an integer variable with the chained program.

Use windows.pkg

// COMMON INTEGER

Integer giParameterCount // Global integers reside in common area.

// END OF COMMON AREA

Object oTest Is A Button

Procedure OnClick

Move 2 To giParameterCount

Chain Wait '"New Prog" "parameter 1" param2'

End_Procedure

End_Object // oTest

Send OnClick Of oTest

Send Stop_Box "End of calling program reached!"

  • Here is a simple chained program that shows how the parameters are extracted from the command line (using the Cmdline command) using the shared integer.

Use windows.pkg

// COMMON INTEGER

Integer giNoParams // This is giParameterCount in the calling program.

// END OF COMMON AREA

Object oTest Is A Button

Procedure OnClick

Integer iCounter

String sCommandLineParameter

Showln "In chained program."

For giCounter From 1 To giNoParams

Cmdline sCommandLineParameter

Showln "Parameter " giCOunter ": " sCommandLineParameter

Loop

End_Procedure

End_Object

Send OnClick Of oTest

Send Stop_Box "End of chained program reached!" "Exiting"

  • If the system cannot find the program to chain to, DataFlex Error 31 (Program file not found) will be declared and the program will terminate.

  • From a program executed by Chain Wait, you may chain wait to another program, and from that to another. The only limit on this process is the amount of memory in your computer to hold all the programs and their associated database files. If you use Export_Files with each chain wait, all database files opened by secondary (and tertiary, etc.) programs will remain open too. If a program chained with the wait option ends with a Runprogram command, execution will still return to the calling program, to resolve the wait.

  • If a chained program executed with Export_Files opens database files, those files will remain open even after execution has returned to the calling program. To cause such files to close when execution leaves the program that opened them, use Export_Only.

  • Global integer variables that are declared for common use should be explicitly documented. The opportunity for error is very high when using global variables for any purpose, especially when the variables are global between programs.


Character (Obsolete Command)

Obsolete

This command is replaced by the Character function.

See Also

Purpose

To convert an integer between 0 and 255 to its equivalent ASCII character, and place the character in a variable.

Syntax

character ascii_num to ascii_char

What It Does

Character converts a number (ascii_num) to the single ASCII character (ascii_char) represented by the number in the ASCII character table. This is often useful for special device controls such as ringing the bell or setting a printer.

string bell 1

character 7 to bell

show bell

This declares a one-character string variable called bell, and moves the "beep" character (ASCII value 7) to bell. The show bell statement will cause the computer to beep anytime thereafter in the program.

Notes

  • The character command is useful for creating strings for printer and other device control, in cases where you can't conveniently create the strings from the keyboard.

  • The ascii command does the reverse of character; it converts the first character of a source string to its ASCII value and places the result in a variable.

  • Most printers and many other devices use the escape character (ASCII value 27) to begin a control sequence. The following example will set an Okidata 192 printer to its double-width printing mode, print one line, and then reset to normal mode:

string esc 1

direct_output "LST:"

character 27 to esc

write esc "W1"//Turn double width on

writeln "LINE OF DOUBLE WIDTH PRINTING"

write esc "W0" //turn double width off

  • ASCII values for the character command must be represented as decimal (not hexadecimal) numbers.

  • Ascii_num and ascii_char may be the same variable.


Cmdline

Obsolete

This command is replaced by the cCommandLine class.

See Also

Purpose

To move arguments from the command line of the current DataFlex program into variables.

Syntax

Cmdline {variable}

What It Does

A command line is a string of arguments that follow the program name when a Visual DataFlex program is executed. The user may enter the command line (e.g., by using the Run Dialog of the Windows Start Menu) or it can be programmatically set (e.g., by using Runprogram or Chain to execute a Visual DataFlex program.)

Command line arguments are space-delimited strings that follow the name of the program. Arguments that contain spaces themselves must be quoted.

Example

Here is a simple program that prints all the command line arguments passed to a program:

Use DFallent

Object oPanel is a Panel

Set Size to 100 100

Object oTest Is A Button

Set Location to 10 10

Procedure OnClick

String sCommandLineParameter

Integer iCounter

Showln "Show command line parameters."

Cmdline sCommandLineParameter

While (sCommandLineParameter <> "")

Showln "Parameter " Counter ": " sCommandLineParameter

Cmdline sCommandLineParameter

Increment iCounter

Loop

End_Procedure

End_Object

End_Object

Start_UI

Assuming the program above is called "Test", the command line…

DFRUN Test "Parameter 1" Parameter2 3

…will return 3 arguments: "Parameter 1", "Parameter2", and "3".

Notes

  • Cmdline retrieves arguments in the order in which they are given on the command line. For example, the third Cmdline command in the program will retrieve the third argument on the command line.

  • If a Cmdline command is executed after all arguments on the command line have been consumed, the {variable} named in the command will be empty.

  • Once all the command line arguments are read by the system, they are no longer available for subsequent Cmdline commands.


DB2_SetConstraint

Obsolete

The DB2_SetConstraint command was introduced in version 1 of the DataFlex Connectivity Kit for DB2. Since then new techniques allow the programmer a better and more controllable interface. The command is still available for backward compatibility reasons. For new logic we recommend the use of the DF_FILE_SQL_FILTER and DF_FILE_SQL_FILTER_ACTIVE attributes or the use of Embedded SQL.

This command was added to give the programmer more control over the Select statement generated by the driver. It will effectively turn off the driver logic, that generates the where clause of a select statement, and replace that with what is passed in the command. Since you are overwriting internal logic, this command has the potential to generate unexpected results when misused. That is why the command must be used in one defined way. You must setup the clause, find records in the result set by the index that you want the result ordered by in forward or backward direction (GT, LT), and remove the clause.

For example, if we want to use this functionality in the Order Entry sample to find all order lines for the MODEMS item, we could do this the following way:

Use DB2_DRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

DB2_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Until [Not Found]

DB2_SetConstraint OrderDtl.File_number ""

This feature can speed up reporting in particular. Sometimes looking for related information is more efficient if the where clause is replaced by a "ChildColumn = ParentValue" construction. The select statements generated by the driver will select the desired record and all that follow according to the index used. By giving it a specific where clause having specific knowledge about the database, you are able to limit the size of the result sets and thereby increase performance.

The DB2_SetConstraint command will reset the DF_FILE_MAX_ROWS_FETCHED attribute when issued. If the command is issued with a clause, the attribute will be set to zero (0). If it is called with no clause (an empty string), the attribute will be reset to its original value.

Please note that you need to use SQL syntax in the where clause that you specify. If you want to select on dates you must use the YYYY-MM-DD format that SQL uses. Normally, this is easiest accomplished by:

Date MyDate

Integer OrgFmt OrgSep

Sysdate MyDate

Get_attribute DF_DATE_FORMAT To OrgFmt

Get_attribute DF_DATE_SEPARATOR To OrgSep

Set_attribute DF_DATE_FORMAT To DF_DATE_MILITARY

Set_attribute DF_DATE_SEPARATOR To (ASCII("-"))

DB2_SetConstraint MyFile.File_number ("MYDATECOLUMN = '" + string(MyDate) + "'")

Set_attribute DF_DATE_FORMAT To OrgFmt

Set_attribute DF_DATE_SEPARATOR To OrgSep

Also note that string constants are placed in single quotes (').

OF SPECIAL NOTE

  • If this command is used on a table you cannot use other finds on that table until ending the DB2_SetConstraint since, as long as the constraint is in force, it will overwrite the find logic of the driver. If, before ending DB2_SetConstraint, we changed the example above to find on OrderDtl by some other index or in a different direction (not gt) on the same index, the result would be unpredictable.

Use DB2_DRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

DB2_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Find Lt OrderDtl By Index.1 // The result of this command is unpredictable

Until [Not Found]

DB2_SetConstraint OrderDtl.File_number ""

  • You cannot change the buffer between finds to re-seed the find logic. Doing that will result in the first record being found again. If we adjust the previous code to the example below, the repeat loop will turn into an endless loop since you are finding the same record repeatedly.

Use DB2_DRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

DB2_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Move SomeValue To OrderDtl.Order_number

Until [Not Found]

DB2_SetConstraint OrderDtl.File_number ""

  • You can use find, save and delete commands on other tables where no DB2_SetConstraint is in force. You could, for example, expand the code above and show the customer names for the customers that bought modems. To achieve this you would need to find an OrderHeader and a Customer record.

  • You can end looping through a DB2_SetContraint block anytime you like. If we wanted to find only two records in the sample above, we could add a counter, increment it for every found record and break the loop when the counter is two.

Use DB2_DRV

String Clause

Integer Counter

Move 0 To Counter

Move "ITEM_ID = 'MODEMS'" To Clause

DB2_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " ;

OrderDtl.Order_Number ", " OrderDtl.Detail_number

Increment Counter

If (Counter >= 2) Break

Until [Not Found]

DB2_SetConstraint OrderDtl.File_number ""

  • You must use SQL syntax in the string that is passed.

  • If you want to write portable applications that support multiple database drivers, you can use the general form of the DB2_SetConstraint command, CLI_SetConstraint. CLI_SetConstraint performs the same functionality. In fact, it is called from the DB2L_SetConstraint command. The CLI_SetConstraint command works exactly as described for DB2_SetConstraint. It gets an extra parameter, the identification of the driver that you want to set the constraint for. If we changed the code above to be more generic, it would look like the sample below.

Use DB2_DRV

String Clause

String DriverId

Move DB2_DRV_ID To DriverId

Move "ITEM_ID = 'MODEMS'" To Clause

CLI_SetConstraint OrderDtl.File_number Clause DriverId

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " ;

OrderDtl.Order_Number ", " OrderDtl.Detail_number

Until [Not Found]

CLI_SetConstraint OrderDtl.File_number "" DriverId

DISCLAIMER

Data Access has done a lot of research into performance issues and design differences between the native DataFlex database and a DB2 database. We found that the DB2_SetConstraint or CLI_SetConstraint command can speed up a connection to a DB2 database considerably. While we are looking into ways to improve internal driver logic to get the kind of result these commands can give, this is not a trivial task and outcome of further research is uncertain. In the meantime, Data Access wants to offer this solution to the DataFlex community.

You should be aware that the misuse of these commands could give unexpected results. It is the developers' responsibility to verify that the results are as expected. All risks associated with the use of these commands are the developer's; Data Access Corporation disclaims any and all liability with respect to the use of the DB2_SetConstraint or CLI_SetConstraint commands.


Debug Command

Obsolete

This option is obsolete. Use the Visual DataFlex Debugger for full source-level debugging.

Purpose

To aid program debugging by displaying to the screen the number of the line being executed as the program is running.

Syntax

debug

What It Does

As a program executes, debug displays program line numbers to the screen.

Notes

  • Debug is a "toggle" which you may switch on and off at various points in your program. The second appearance of debug in your program will discontinue debug output. The third appearance turns it on, the fourth turns it off, and so forth.

  • The effect of debug is normally confusing to program users. Be sure to remove all debugs before delivering or installing your final program.

  • The line numbers displayed are the compiled command line numbers, not the line count in your source code. A printout of the compile time listing will enable you to identify numbers output by debug to command lines.


Dependent_Item (Obsolete Command)

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. The same functionality is achieved in Visual DataFlex by using multiple DEOs for the same table and field in a component (e.g. dbView) that are connected to the same DDO.

See Also

Purpose

To make an item a member of a group of dependent items.

Syntax

item_group

dependent_item {object_id item_number |item_name}

:

end_item_group

What It Does

This command identifies each item to be included in a dependent item group. Each item in the group will have the same value at all times. Dependent_item groups should be declared just prior to the first start_ui statement.

A dependent_item group is created whenever a group of items must always have the same value. For example, when a database field is bound to more than one item (in one or more objects), each item bound to the field must display the same value. To ensure this, you may create a dependent_item group which specifies all equivalent items.

item_group

dependent_item customerform.obj 1

dependent_item paymentform.obj 2

end_item_group

In this example, if the second item in Object customerform and the third item in Object paymentform were both bound to Field customer.customer_name, we would create an item group to ensure that they both always reflect the same value.

Any time data entry is performed on one of the items in the group, all of the other items in the group are set to the value of the edited item once the cursor leaves the item.


Despool Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. This functionality is achieved in Visual DataFlex by closing the output device that is being printed to after printing is complete.

See Also

Purpose

In multi user operations, to cause the print spooler (if there is one) to start printing.

Syntax

despool

What It Does

Despool causes output which you have sent to a "logical" spooled printer to be released to the (physical) printer queue. The command should be placed at the point in processing at which output to the logical printer (typically lst:) is complete, and you wish the spooled output to be actually printed.

A spooler queues concurrent print requests from multiple users in the order in which they are released to the queue, printing each as the previous one is completed. If you're not sure whether your operating system has a spooler, check the manual for your operating system. To use your operating system's spooler, your operating system must be configured (installed) so that the option to do so is on.

direct_output "LST:"

output check_form

close_output

despool

Notes

  • If you have a single user system, you do not have an operating-system spooler, and the despool command has no effect.

  • The DataFlex menu program, MENU.FLX, issues a despool command whenever execution returns to the menu.

  • In some operating systems, DataFlex cannot cause despooling because there is no such function in the operating system. In these cases, the command has no effect. See your installation guide for information on despool in your system.

  • In most systems, despooling is done automatically when the spooler file is closed. The despool command, although not always necessary, will function normally in these systems.


DF_FILE_PRIMARY_INDEX_TRIGGER

Obsolete

The DF_FILE_PRIMARY_INDEX_TRIGGER attribute is obsolete and replaced by the DF_FILE_GENERATE_RECORD_ID_METHOD attribute.


DF_FILE_TRANSLATE_OEM_TO_ANSI

Obsolete

The DF_FILE_TRANSLATE_OEM_TO_ANSI attribute is obsolete and replaced by the DF_FILE_TABLE_CHARACTER_FORMAT attribute.


Directory Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. In Visual DataFlex, you can use the dir: driver of the direct_input command to read the contents of a folder.

See Also

Purpose

To display a directory of disk files to the screen.

Syntax

directory file_spec

Argument Explanation

File_spec May be of any class but must be of Type String. It may contain ambiguous filenames (including * and ?), or it may identify a logical disk drive and/or subdirectory path without any filename.

What It Does

Directory displays to the screen a directory of the disk files specified in file_spec. If a null file_spec (" ") is given, directory outputs the names of all files on the current drive and direc tory.

directory "b:"

This example would display the names of all files on the b: logical disk drive. The drive is identified literally, in quotation marks.

directory "\ops\*.rpt"

This example, using a literal file specification in quotation marks, would display the names of all files whose extensions were rpt in the \ops directory.

directory screen.5

This example would display the names of the file(s) specified by the filename and/or drive and/or directory whose name was in the contents of the fifth window in Image screen.

directory trucks

This example would display the names of the file(s) specified by the filename and/or drive and/or directory whose name was in the contents of Variable trucks.

Notes

  • You do not need to open files to use directory.

  • In applications which may be run in various operating systems, literal file_specs should be avoided in favor of variable file_specs. This is because the syntax of directories and filenames varies from environment to environment, and variable file_specs can be specified in a separate installation program specifically for the target environment.


Displayonly Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To prevent data entry to items connected to a field, and prevent data from the items from being moved into the record buffer.

Syntax

set field_options field file.field to dd_displayonly

or

entry_item file.field {displayonly}

What It Does

When displayonly is on an entry_item command line, it causes the cursor to skip the item and prevents any data in the item from being put into the record buffer. Any data in the buffer pertaining to the item is displayed in the item.

entry_item patient.weight {displayonly}

In this example, the contents of Field weight in Database File patient is displayed. The displayonly option prevents the cursor from stopping at the item, and keeps any data in the item from going into the record buffer.

Applying dd_displayonly to a field in a DataDictionary object causes this same behavior in every item connected to file.field in any DEO that is using the DataDictionary object.

set field_options field patient.weight to dd_displayonly

Data entry to the field can be enabled in selected DEOs (or under selected conditions in the same DEO) by use of the item_option ... displayonly message.

item_option item 4 displayonly false

This example illustrates suspension of the displayonly field property for the fifth item of a DEO.

Notes

  • Displayonly is the equivalent of a combination of the noenter and noput field properties.

  • If an entry_item with a displayonly or noenter option is processed immediately before an entry_item with a retain option, the retain acts as if it were a retainall, and the second item cannot be cleared by any number of presses of the Clear accelerator key.


End_constraints Command

Obsolete

Refer to the OnConstrain event in the DataDictionary class.

See Also

Purpose

To create a constraint or set of constraints for a dataset.

Syntax

end_constraints

What It Does

End_constraints identifies the end of a block of code containing a set of constraints. This command, together with the begin_constraints command, can be used as a shortcut to defining constraints within a procedure. For example, the following two sets of code behave identically:

procedure constrain

constrain vndr relates to region

forward send constrain

end_procedure

begin_constraints

constrain vndr relates to region

end_constraints


End_item_group Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To end the declaration of a group of dependent items.

Syntax

item_group

dependent_item ...

:

dependent_item ...

end_item_group

What It Does

This command may only be used to end a group of dependent items. Dependent item groups should be declared just prior to the first start_ui statement.

A dependent_item group is created whenever a group of items must always have the same value. For example, when a database field is bound to more than one item (in one or more objects), each item bound to the field must display the same value. To ensure this, you may create a dependent_item group which specifies all equivalent items.

item_group

dependent_item customerform.obj 1

dependent_item paymentform.obj 2

end_item_group

In this example, if the second item in Object customerform and the third item in Object paymentform were both bound to Field customer.customer_name, we would create a dependent item group to ensure that they both always reflect the same value.

Any time data entry is performed on one of the items in the group, all of the other items in the dependent group are set to the value of the edited item once the cursor leaves the item.


End_item_list Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. In Visual DataFlex, Item_List and End_Item_List statements are maintained by the Visual DataFlex Studio for objects that use them.

See Also

Purpose

To terminate an item-definition block.

Syntax

end_item_list

What It Does

The end_item_list command ends the item definition block begun with the item_list command. The end_item_list command actually fixes up the item_list command with the total number of items defined for the object.

Every item_list must have a matching end_item_list.


End_Type

Obsolete

This command is obsolete. See the struct command for using structured types in Visual DataFlex.

See Also: Field, Put, Type, Structured Types

Purpose

To declare a structure for the C programming language, for use with DLL calls from Visual DataFlex programs.

Syntax

Type {type-name}

Field {field-name} as {data-type}

:

End_Type

Where {type-name} is the name of the complex data type; {field-name} is the name of a field. There can be as many fields in the type declaration as you wish; and {data-type} is any Visual DataFlex representation of a 'C' data type.

What It Does

Type enables you to create a complex data structure in memory for use in passing parameters for DLL calls from Visual DataFlex programs.

Type tv_item

Field tv_item.mask as DWORD

Field tv_item.hItem as HANDLE

Field tv_item.state as DWORD

Field tv_item.stateMask as DWORD

Field tv_item.pszText as POINTER

End_Type

Note

  • If you declare a structure, the size of the structure is automatically stored in a symbol called <structname>_Size.


Entry_name_item Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To allow the assignment of names to entry items.

Syntax

entry_name_item item_name file.field [[entry_options]]

What It Does

Entry_name_item is a replacement for the entry_item command that permits the assignment of names to object items for easier recognition in source code. Item_name is the name by which you choose to refer to the item, and the remainder of the syntax (file.field and entry_options) is the original syntax of the entry_item command.

Referring to items in objects by their item numbers staightforwardly can result in code that is very difficult to read, as the following example demonstrates. The item list establishes items for price, quantity, and total, and the succeeding procedure calculates the extension to the total.

Object My_Form is an entry_form My_Form Using a_data_dictionary

item_list

entry_item Tran.Id

entry_item Part.Id

entry_item Part.Description

entry_item Part.Amount

entry_item Tran.Qty

entry_item Tran.Total

end_item_list

Procedure Calc_Total Integer Item#

Number A1 A2

Get value item 3 to A1 // this doesn't tell

Get value item 4 to A2 // you a whole lot.

Set value item 5 to (A1 *A2)

end_procedure

end_object

We have to keep track of the item numbers (they are zero-based). This can be difficult. What if we counted wrong? What if we moved the items around (e.g., move description to the end)?

The following example shows how the same would be done using entry_name_item:

Object My_Form is an entry_form My_Form Using a_data_dictionary

item_list

entry_item Tran.Id

entry_item Part.Id

entry_item Part.Description

entry_name_item Amount## Part.Amount

entry_name_item Quantity## Tran.Qty

entry_name_item Total## Tran.Total

end_item_list

Procedure Calc_Total Integer Item#

Number A1 A2

Get value item Quantity## to A1 // much nicer!

Get value item Amount## to A2 // Suddenly I can see!!

Set value item Total## to (A1 *A2)

end_procedure

end_object

In the following discussion we will talk about the entry_name_item command. Everything discussed applies equally to the on_name_item command.

Note that you do not need to use entry_name_item everywhere you would have used entry_item. In fact, it is best to only name the items that you actually need (we will see why later on).

Limitations

1. Global Names

The item_names are global names and must therefore be unique. Ideally, these names would be local to the object containing the items. Therefore, you should use unique names for the items and only name the items that you really need to (entry_name_item and entry_item commands may be intermixed freely). In the above example, we ended each item name with a double pound-sign (##). This makes it less likely that they will be used for other symbols (images, local variables, etc.) and make it easy to recognize as an item name.

2. Forward Referencing

You can't use the item names until you've named them. Therefore you could not do the following:

Procedure Calc_Total Integer Item#

Number A1 A2

Get value item Quantity## to A1 // Hey, who is this quantity##?

Get value item Amount## to A2 // Amount##, what's that?

Set value item Total## to (A1*A2) // Huh?

end_procedure

item_list

entry_item Tran.Id

entry_item Part.Id

entry_item Part.Description

entry_name_item Amount## Part.Amount

entry_name_item Quantity## Tran.Qty

entry_name_item Total## Tran.Total

end_item_list

This suggests that you should place your item_lists towards the top of your objects. Also, you can't reference these names in an earlier object (bad OOP practice to begin with).

If you can't live with this restriction, then you should do the following:

Look at your program. Odds are you are having problems because your code is not OOP-proper. Are you trying to directly access item information for one object from within another object? See if you can correct the problem.

If you can't (or you won't), then use the alternate command, name_items (see below). This command is similar to the name command of DataFlex and can be placed at the top of your program.

Naming Items in Grid Objects

When referencing items in Grid-class objects you need to reference the item number relative to the item number of the current row. This can usually be accomplished by using the base_item property as your item number offset. For example, the above sample could be turned into a grid:

Object My_Table is a grid My_Form ;

main_file Tran by Index.1 ;

Using a_data_dictionary

begin_row

entry_item Tran.Id

entry_item Part.Id

entry_item Part.Description

entry_name_item Amount## Part.Amount

entry_name_item Quantity## Tran.Qty

entry_name_item Total## Tran.Total

end_row

Procedure Calc_Total Integer Item#

Number A1 A2

Integer BI

Get base_item to BI // should be item number of column 0 of current row

Get value item (Quantity## +BI) to A1 // use BI as our offset into

Get value item (Amount## +BI) to A2 // the table.

Set value item (Total## +BI) to (A1 *A2)

end_procedure

end_object


Error_report Command

Obsolete

This command is obsolete. Use the ErrorSystem class for error handling in Visual DataFlex.

See Also

Purpose

To trigger reporting of pending errors through a specified error handler without affecting the program's default error-reporting timing or method.

Syntax

error_report [label]

What It Does

Reporting of errors that occur in procedures and functions (processes) can be deferred by setting the value of predefined variable error_type. If at any point in any process you wish pending errors reported and handled, the error_report command will "flush" any pending errors out to the report handler in effect.

If the label argument is supplied, the code starting at label will be executed to handle the error(s). If the argument is not supplied, the error will be reported according to whatever value of predefined variable error_object_id, if any, is in effect. If an error routine is specified by an on error command, that routine is not used unless it is also named in the error_report command.

procedure fibonacci

:

error_report fibonacci

end_procedure

:

fibonacci:

show "Error in Fibonacci routine: "

:

return

In this example, Procedure fibonacci ends with an error_report command that identifies Label fibonacci as the subroutine to execute if errors are pending when execution of the routine is complete.

Notes

  • If multiple errors are pending, only the first one that occurred will be reported.

  • Error_report does not affect any error object or on error subroutine that may be in effect for general error handling, regardless of whether such error object or error subroutine is used by the error_report itself.

  • The on error command also triggers error reporting, but it must name a label, and any label it names remains in effect after execution of the command.

  • Error_report does not reset the err predefined variable. If you need this indicator set to false after error handling, you must supply explicit code to do so.

  • Any input (entry_item, etc.) command always triggers reporting of all errors prior to accepting input.


Eq Comparison Mode

Obsolete

The EQ find mode is still supported. Refer to the Find command for further details.

For Boolean comparisons you should use the = symbol inside a Boolean expression.

Example

This is obsolete:

If iCount EQ 10

This is correct:

If (iCount = 10)

See Also

Purpose

To specify equality or exact match as the operator for finds and comparisons.

Syntax

Commands and loops can be controlled according to the result of comparison of two values using the eq operator:

indicate indicator as variable eq variable

See Indicate Command for a description of that command.

if variable eq variable command

See If Command for a description of that command.

With the find command, records can be found in a database file according to the result of comparison of a value in the record buffer with values in an index to field values in a database file:

move value to df_filename.field

find eq df_filename.field

See Find Command for a description of that command.

What It Does

Eq returns a result of true when the numeric values of two variables are numerically equal, or when the strings they contain are identical.

indicate senior as years eq 4

This example sets Indicator senior true if the (numeric or string) value of Variable years is 4. If the value of years is other than 4, senior is set false.

if years eq 4 indicate senior true

Like the preceding example, this command sets Indicator senior true if the (string or numeric) value of Variable years is 4. If the value of years is other than 4, however, senior remains unchanged from its status before the command was executed.

move 4 to customer.num

find eq customer.num

In this example, the value of 4 is moved to record buffer Field num for Database File customer after customer has been opened and its record buffer cleared. The subsequent find command finds the record in customer whose num field is equal to 4, using the main index for Field num, which must be a unique index.

When used as a find mode by an index containing one or more segments designated "upper case," eq will find a record containing the same letters in the same order as the search key regardless of capitalization in either the record field or the search key.

Notes

  • For the indicate and if commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match.

  • For find commands, DataFlex uses five Find Mode operators: eq, ge, gt, le, lt.

  • Find eq commands may only be used with unique indexes. If they are used with non unique indexes, they will never find a record.

  • Eq may not be used in logical expressions (comparisons enclosed in parentheses). In expressions, the equals sign (=) is to be used.


External_Function16 Command

Obsolete

This command is replaced by the External_Function command.

See Also

Purpose

To import a function residing in a Dynamic Link Library (DLL) file. This is a version of the external_function command specifically for DLLs made on the 16-bit memory model.


Field

Field Command

Obsolete

This command is obsolete. Use Struct and End_Struct.

See Also

Purpose

To name and assign a data type to a component of a data structure. This command is primarily used to define structures that are passed as parameters to DLLs.

Syntax

Type {type-name}

Field {field-name} As {data-type} [{count}]

:

End_Type

Argument Explanation

{type-name} Is the name of the complex data type.

{field-name} Is the name of the data-structure component.

{data-type} Is the data type of field. Below is a list of valid types and their respective Byte-size.

Type | Size (bytes) | Note
CHAR | 1 | Converted to Integer.
BYTE | 1 | Converted to Integer
WORD | 2 | Converted to Integer
SHORT | 2 | Converted to Integer
DWORD | 4 |
INTEGER | 4 |
HANDLE | 4 |
NUMBER | 4 | Converted to Integer
DATE | 4 | Converted to Integer
POINTER | 4 |
STRING | 4 |

{count} If the field is to contain more than one instance of the data type, this argument may be used to specify how many.

What It Does

In Visual DataFlex, a data structure is defined using the Type…End_Type construction. The data structure is composed of one or more fields that are defined using the Field command to create each of these fields. The Field command specifies how many bytes are in the field, and how its data will be interpreted by Visual DataFlex.

The Field command creates a named part of a complex data structure for passing parameters to DLL procedures from DataFlex programs. Each field thus defined can be accessed using the GetBuff and Put commands.

Example

Below is an example of a simple type definition that defines RGB colors:

TYPE RGB

Field Blue As CHAR

Field Green As CHAR

Field Red As CHAR

Field Reserved As CHAR

END_TYPE

The following example shows how to use types with external functions. It is part of a serial communications class. The commDCB structure represents a communications device control block. It is used in the Win32 API, specifically with the BuildCommDCB and SetCommDCB functions. The contents of a commDCB are serial communications parameters.

// Define 3 external functions we need to access the COM port.

External_Function BuildCommDCB "BuildCommDCBA" Kernel32.DLL ;

String sModeString Address pDCB returns Integer

External_Function SetCommState "SetCommState" Kernel32.DLL HANDLE hComm

Address pDCB Returns Integer

External_Function CreateFile "CreateFileA" Kernel32.DLL String sPortName;

DWORD dwRWOptions DWORD dwSharingOptions DWORD dwSecurityOptions;

DWORD dwCreateOptions DWORD dwAttributes DWORD dwTemplate Returns Integer

// Some Win32 API Constants for CreateFile function.

#Replace GENERIC_RW |CI$C0000000

ENUM_LIST // Create File creation options.

Define CREATE_NEW FOR 1

Define CREATE_ALWAYS OPEN_EXISTING OPEN_ALWAYS TRUNCATE_EXISTING

END_ENUM_LIST

Type commDCB // DataType used by SetCommState and BuildCommDCB

Field cDCBLength As DWORD // Size of commDCB structure.

Field cBaudRate As DWORD // Baud rate of port

Field cfFlags As DWORD // 32 bits of flags

Field cReserved As WORD // not used - do not use.

Field cXonLim As WORD // Transmit X-ON threshold

Field cXoffLim As WORD // Transmit X-OFF threshold

Field cCHARSize As CHAR // Number of bits/CHAR, 4-8

Field cParity As CHAR // 0-4=None,Odd,Even,Mark,Space

Field cStopBits As CHAR // 0,1,2 = 1, 1.5, 2

Field cXonChar As Char // Tx and Rx X-ON character

Field cXoffChar As Char // Tx and Rx X-OFF character

Field cPeChar As Char // Parity error replacement char

Field cEofChar As Char // End of Input character

Field cEvtChar As Char // Received Event character

Field cReserved1 As WORD // not used - do not used.

End_Type

Class cSimpleComm Is A Button

Procedure Construct_Object

Forward Send Construct_Object

Property String psPortName Public "COM2:" // default "COM2:"

Property String psParity Public "n" // default no-parity

Property Integer piDataBits Public 8 // default 8 bits of data

Property Integer piStopBits Public 1 // default 1 stop bit

Property Integer piBaudRate Public 9600 // default 9600 baud rate

Property HANDLE phComm Public 0

End_Procedure

// Build a Mode string that can be used with BuildCommDCB.

Function ModeString Returns String

String sModeString

Move ( psPortName(Self) + " BAUD=" + String(piBaudRate(Self)) + ;

" PARITY=" + psParity(Self) + " DATA=" + ;

String(piDataBits(Self)); + " STOP=" +;

String(piStopBits(Self)) ) To sModeString

Function_Return sModeString

End_Function

// Set up the Com port.

Function CommSetup Returns Integer

String sCommDCB // Buffer for accessing DCB.

Pointer pCommDcb

Integer iBaudRate // For showing extraction.

// Reset the structure. Fill it with nulls.

// Note: The Type command automatically creates the _Size constant.

// Its value is the size of the data structure in bytes.

Move (Repeat( Character(0), commDCB_SIZE )) to sCommDCB

// The commDCB structure requires the size as the first field.

Put CommDCB_Size To sCommDCB At cDCBLength

// Get a pointer to the VDF string.

// Structures must be passed by pointer.

GetAddress Of sCommDCB To pCommDCB

// BuildCommDCB fills a CommDCB, based on a Mode command string.

If (BuildCommDCB( ModeString(Self), pCommDCB )) Begin

// Change the port settings.

If (SetCommState( phComm(Self), pCommDCB )) begin

// Extract out the baud rate from the structure.

// This just shows that extraction works too.

Getbuff From sCommDCB At cBaudRate to iBaudRate

Showln "The Baud Rate is " iBaudRate

Function_Return TRUE

End

End

Function_Return FALSE

End_Function

// Open the communication port.

Function OpenComm Returns Integer

Integer hComm

Move 0 to hComm

Move (CreateFile( psPortName(Self), GENERIC_RW, 0, 0, ;

OPEN_EXISTING, 0, 0)) to hComm

Set phComm to hComm

Function_Return hComm

End_Function

End_Class

Object oTest Is A cSimpleComm

Procedure OnClick

If (OpenComm(Self)) Begin

If (CommSetup(Self));

Send Stop_Box "Com settings changed!" "Success"

Else;

Send Stop_Box ("Cannot Initialize Port " +;

(psPortName(Self))) "Failure"

End

Else;

Send Stop_Box ("Cannot open the communication port"

+psPortName(Self)) "Failure"

End_Procedure

End_Object

Notes

  • The Field command may be used only in a Type . . . End_Type structure-declaration block.

  • If you declare a structure, the size of the structure is automatically stored in a symbol called <structname>_Size.


Fieldindex Predefined Variable

Obsolete

This variable is obsolete.

In character-mode DataFlex, this variable was typically used to loop through all (or a selection of) fields in a given data file. In Visual DataFlex, you can do the same thing using the sample code below.

integer iMaxFields iField

string sFieldVal

handle hoFile

Open Customer

move Customer.File_Number to hoFile

// how many fields are in the Customer data file?

get_Attribute DF_FILE_NUMBER_FIELDS of hoFile to iMaxFields

// find Customer number 10

clear Customer

move 10 to Customer.Id

find eq Customer by Id

if (Found) begin

// loop through all fields in current record of Customer file

// start with field 1 (skip Recnum field)

for iField from 1 to iMaxFields

get_Field_Value hoFile iField to sFieldVal

showln "Value of field " (String(iField)) ": " sFieldVal

loop

end

The example above opens the Customer data file, determines how many fields are in the file using the DF_FILE_NUMBER_FIELDS database API attribute, finds the Customer record with id 10, then loops through all fields in the Customer file (skipping the Recnum field) retrieves the value of each field using the get_Field_Value command and displays the values using the showln command.

See Also

Purpose

To provide indexed addressing of one or more fields in a database file.

Syntax

move int_val to fieldindex

or

df_filename.field&

The ampersand indicates that the field to be addressed is the field whose number is greater than that of df_filename.field by the value of the fieldindex Predefined Variable.

What It Does

A series of fields in a database file may be addressed by a single command in a loop in which the value of fieldindex is controlled. The field which is addressed in each pass is controlled by the value of fieldindex as an offset from the field identified as df_filename.field&. The ampersand (&) is literal and required.

Until it is used, the value of fieldindex is 0. Thus until some other value is moved to fieldindex, df_filename.field& is the same as df_filename.field with no ampersand after it. If fieldindex is 1, then df_filename.field& refers to the next field after df_filename.field.

There are two primary ways of using fieldindex:

a. To select randomly from a range of fields. For example, records in Database File merch might have four fields, as:

  • merch.recnum

  • merch.retail_price

  • merch.dealer_price

  • merch.distrib_price

Records in the customer file, then, might have a terms field containing 1, 2, or 3 which determines which price the customer gets. The following would move the correct price to the variable cost:

move customer.terms to fieldindex

move merch.recnum& to cost

b. To access a range of fields sequentially.

for fieldindex from 1 to 40

showln merch.recnum&

loop

This example displays to the screen the contents of each of the first 40 fields of Database File merch except the record number.

Fields (and fields) can be addressed from running programs by their numbers. This can be done by addressing commands to indirect_file.recnum. At runtime, the number of the desired field must be moved to fieldindex and the number of the desired file to filenumber before the command(s) addressed to the symbol is executed.

Notes

  • Fieldindex may be positive, for a downward offset from df_filename.field&, or negative, for an upward offset.

  • If a value of fieldindex is generated which addresses a nonexistent field, DataFlex Error 77 Field number out of range will be generated.

  • A fieldindex command can address fields whose data types are different from that of df_filename.field. In most cases this causes no problem, but the operation of some commands, like move, depends on the type of the field (String, Numeric, Date), and will malfunction where a field of type different from that of df_filename.field is addressed. Especially where data is being moved, it is good practice to address only fields of a single data type.

  • If a fieldindex command addressing multiple data types is required for moving data, use the movestr command. Since all data types can be represented as a string, data can be moved from fields intact with this command.

  • The ampersand character can't be a field name by itself; it must be appended to the actual name of a field in the file's definition.

  • A similar variable that works on windows instead of fields is windowindex.


File_Size

Obsolete

Use the DF_FILE_RECORDS_USED, DF_FILE_MAX_RECORDS and DF_FILE_NUMBER_FIELDS attributes instead of this command.

See Also

Purpose 1

To retrieve the current number of records, maximum number of records and the defined number of fields for a database file.

Purpose 2

To change the maximum number of records allowed in a database file.

Syntax

File_Size df_filename to curent_size {maximum_size} {field_count}

or

File_Size new_max_size to df_filename

What It Does

Format 1

File_Size places the number of records in df_filename into the variable first named after the to in the command. It places the maximum allowable number of records into the second variable named (if passed) and the number of fields in the definition of the file into the third variable (if passed).

Example

File_Size parts to num_parts max_parts parts_fields

This example moves the number of records currently in database file parts to variable num_parts, the maximum defined size of parts to max_parts and the number of fields in the definition of parts to parts_fields.

Format 2

File_Size changes the number of records which will be allowed in df_filename.

Example

File_Size 2500 to customer

This example gives database file customer a new maximum of 2500 records.

Notes

  • Database files addressed by the file_size command must be open at the time the command is issued.

  • A file_size command addressed to a nonexistent file will generate a runtime error.

  • If you change the maximum number of records of a file that has indexes, you must update its indexes before you can update online or find by the indexes. Indexes can be updated from Database Builder or by using the sort command.


Filenumber Predefined Variable

Obsolete

This variable is replaced by the DF_FILE_NUMBER Database API attribute.

See Also

Purpose

To store the file-list number of a database file to be addressed indirectly.

Syntax

filenumber

What It Does

After any of the following commands is executed, filenumber contains the file-list number of the database file addressed by the command:

entry_item

make_file

Database files can be addressed indirectly from procedures and functions by setting filenumber to the file-list number of the desired file (or using its current value) and addressing the command(s) to indirect_file.recnum. If a command(s) need to address specific fields in the file, it can be made to do so with the same keyword by pre-setting the value of Predefined Variable fieldindex to the number of the desired field.

Notes

  • Filenumber is an Integer variable that does not need to be declared in programs.

  • To address a particular numbered file with a filelist or filelist pathname command, you may move a desired value directly to filenumber.

  • Database files are listed in numerical order in the Database Builder, and their numbers are listed there.


FindErr Predefined Indicator

Obsolete

This indicator is replaced by the Found predefined variable.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To indicate the success or failure of the last find.

Syntax

[finderr] command

What It Does

Whenever a find command is executed, the finderr Predefined Indicator is set. If the find is successful, finderr is set false. If the find is unsuccessful, finderr is set true. This allows you to program the appropriate action when a find command does not find a record.

find eq parts.code

[finderr] goto update

If a record in Database File parts is not found with the value of Field code equalling the value in the buffer, (Finderr is true), execution is passed to Routine update.

Notes

  • Finderr is also set by the string commands replace and pos to indicate that the sub string being searched for was not found.

  • Finderr is also set by the open command.

  • The found Predefined Indicator is set at the same times as finderr, and to the opposite status (true when finderr is false, and false when finderr is true).

  • The constraint_validate command sets finderr.


Fill= Print Format Option

Obsolete

This option is obsolete. This format option is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To fill in the blank spaces in a window with a specified fill character for output.

Syntax

print source [to destination] {fill="*" [..., option]}

{Fill=} may be used only on format or print command lines. The asterisk (*) represents any printable character, literally, desired for filling.

What It Does

When fill= is on a format or print command line, it causes the print command to fill in unused leading or trailing spaces in windows, using the fill character specified in the option.

In numeric windows, the leading spaces to the left of the number are filled with the fill character. In String type windows, the trailing spaces to the right of the contents are filled with the fill character. Spaces embedded within a string are not filled.

format affidavit.2 to affidavit.9 {fill="#"}

In this example, the blank spaces in the second through ninth windows in Image affidavit will be filled with pound signs (#) any time they are output.

print check_amount to check_form.2 {fill="*",points=2}

In this example, the blank spaces in the second window of Image check_form will be filled with asterisks (*) any time it is output. Fractional values will be output only to the second digit to the right of the decimal point.

Notes

  • You may specify no more than eight different fill charac ters in any single program, but you may use the fill= option on as many windows as you wish in a program.

  • If a fill= option is used on a display, entry, or accept command line, it will have no effect, as it is intended only for use with the print and format commands.

  • Fill= is attached permanently to the windows to which it is applied. If another print command addresses a fill= formatted window, the option will still be in effect, even though it is not given on the print command line.


Findreq Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To keep the cursor in an item for a field until a successful find has been performed on the item value (a record is in the buffer), thus preventing the introduction of new values to the field.

Syntax

set field_options field file.field to dd_findreq

or

entry_item file.field {findreq [... , option]}

What It Does

When findreq is applied to a field in a DataDictionary object or on an entry_item command line, it prevents the cursor from going to the next item until a successful find places an active record in the record buffer. An unsuccessful find causes Error 90 (Please enter a valid record ID).

entry_item trucks.id {findreq}

In this example, the cursor is prevented from leaving the item attached to Field id in File trucks until a find on the item value has placed a record into the trucks file buffer. The find would have to be by the Main Index of Field id.

Applying dd_findreq to a field in a DataDictionary object causes this same behavior in every item connected to file.field in any DEO that is using the DataDictionary object.

set field_options field trucks.id to dd_findreq

Data entry to the field can be enabled in selected DEOs (or under selected conditions in the same DEO) by use of the item_option ... findreq message.

item_option item 4 findreq false

This example illustrates suspension of the findreq field property for the fifth item of a DEO.

Findreq has no effect if an active record is already in the buffer for file (previously found from another item).

Notes

  • An autofind option on the same line with a findreq will attempt the required find automatically when a user attempts to move the cursor out of the window. If the automatic find is successful, the cursor will proceed. If it is not, Error 90, Please enter a valid record ID, is declared.

  • A findreq with an autofind_ge is unnecessary. Autofind_ge always finds a record in a non empty database file.

  • If a find is not possible or convenient from an item with findreq, users may use the Previous accelerator key to move the cursor to a previous window whose field is indexed, find through that item, and proceed through the item with the findreq on it.

  • If a find is not possible or convenient from an item with findreq, users may use the Cancel accelerator key to clear all windows, put the cursor in the first item, and "start over" again.


Float$ Print Format Option

Obsolete

This option is obsolete. This format option is valid only in character-mode DataFlex. In Visual DataFlex, you can use the Field_Mask property of the DataDictionary class or the Currency_Mask method.

See Also

Purpose

To place the currency characters ($, etc.) immediately to the left of the contents of windows addressed by the print command.

Syntax

print source [ to destination ] {float$ [..., option]}

What It Does

When float$ is on a format or print command line (the only places it may be used), it places the currency characters immediately to the left of the contents of the destination window(s).

The currency characters ($, etc.) are whatever characters were installed in the DataFlex Configuration to represent money.

format paycheck.2 thru paycheck.5 {float$}

This example would format the second through fifth windows of Image paycheck to place the currency characters immediately to the left of any contents of the windows.

print cust.balance to statement.2 {float$, points=2}

This example would format the second window of Image statement to place the currency characters immediately to the left of the contents of the window, and to display two digits to the right of the decimal point (points=2).

Notes

  • Float$ has no effect on non Numeric windows, and so may be used in format commands addressing a range of windows so long as the format is desired for every Numeric window in the range.

  • When setting the size of a window which will have the float$ option on it, provide an additional space(s) for the currency characters, as well as for other formatting characters such as minus signs, decimal points, and commas.


Forceput Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To put data from an item into the record buffer regardless of whether the item contents were changed since it was origi nally displayed.

Syntax

set field_options field file.field to dd_forceput

or

entry_item file.field {forceput [... , option]}

What It Does

When forceput applies to a field, the contents of the item connected to it are put to the file record buffer when the cursor exits the item even if no keyboard entry was made to the item. Forceput can be applied as an option on the entry_item statements that address file.field, or it can be applied in a DataDictionary object with the field_options property, where it will apply automatically to all DEOs that are using the DataDictionary.

entry_item purchases.ord_date {forceput}

In this example, the data in the item is put to Field ord_date in the record buffer for Database File purchases regardless of whether any keyboard entry is made to the item.

Notes

  • Normally the contents of an entry_item's window are put to the buffer only if its data was changed from what was originally displayed.


Format Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. Refer to the Field_Options property in the DataDictionary class.

Purpose

To apply Window and Print Format Options to a range of windows.

Syntax

format window [thru window] {[format options]}

What It Does

The format command applies one or more Window or Print format options to data output through window. If the optional thru window clause is added, the option(s) may be applied to a range of windows.

format screen.3 {capslock}

This example applies the capslock and option to the third window of Image screen.

format body.2 thru body.8 {signrt,float$}

This command formats the second through the eighth windows of Image body with the signrt and float$ options.

The following are the Print (P) and Window (W) format options. Each is described in its own article in this manual.

  • autoback W

  • autoreturn W

  • capslock W/P

  • fill= P

  • float$ P

  • no_calc W

  • points= W

  • required W

  • signrt P

  • suppress P

Notes

  • You may format no more than 20 windows with a single format command.

  • Print and window format options may be applied to single windows by placing the option on print command lines, as well as by using the format command.

  • Points= may not be used as a format option on entry_item command lines in any class of object that can be scrolled. The option is supported only in the entry_form class. If the option is required in classes of other types, it may be applied to windows through use of the format command.


Formfeed Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To output a pagefeed character to the current output device.

Syntax

formfeed

What It Does

When the pagefeed Predefined Variable is unused, or set zero, the formfeed command outputs a formfeed character to the printer, or to the device or file named in the last direct_output command. In the printer, this will cause the paper to be advanced the number of lines defined in the printer as the height of a page.

If a value of 1 has been moved to pagefeed, a formfeed command will cause output to pause until a key (any key) has been pressed. This is especially suitable to screen output.

If the value of pagefeed is between 2 and 32,767, a formfeed command will output carriage return characters until the value of Predefined Variable linecount equals pagefeed.

move 66 to pagefeed

formfeed

This example would output carriage returns until the number of lines (both blank and those containing data) output since the last formfeed command was equal to 66.

Notes

  • In report programs, you may program the beginning of a new output page manually by combining formfeed with a Predefined Procedure newpage.

formfeed

gosub newpage

These commands would unconditionally start a new page wherever they were placed in a program.

To insert a blank page between printouts, use formfeed either prior to or in the header procedure_section.


Forward_begin_construct Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. See the Class command for information about creating classes in Visual DataFlex.

See Also

Purpose

To pass arguments required by a class's startmac macro from a class definition.

Syntax

forward_begin_construct classname . . .

What It Does

Where a class definition provides for construction of an object of another class that uses arguments in its initialization syntax, forward_begin_construct must be used in the definition of the new class to pass the values of the arguments required by that class. Where the new class's superclass is such a class, forward_begin_construct is required with the superclass as className. Where the new class creates sub-objects of a class requiring initialization syntax, className may be other than the superclass. One forward_begin_construct command is required for every such class of which an object is constructed through a class definition.

Normally, the macro command that is to be called on object (or subclass) creation is identified on the class command line after the keyword startmac. Arguments (. . .) may be values defined within the subclass definition, or they may be values drawn from the object command line of instances of the subclass, in which case the startmac macro_name syntax must be provided on the class command line of the subclass, naming the arguments to be passed to className in the forward_begin_construct command within the subclass's definition.


Forward_end_construct Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. See the Class command for information about creating classes in Visual DataFlex.

See Also

Purpose

To pass arguments required by a class's endmac macro from a class definition.

Syntax

forward_end_construct classname . . .

What It Does

Where a class definition provides for construction of an object of another class that uses arguments in its termination syntax, forward_end_construct must be used in the definition of the new class to pass the values of the arguments required by that class. Where the new class's superclass is such a class, forward_end_construct is required with the superclass as className. Where the new class creates child objects of a class requiring termination syntax, className may be other than the superclass. One forward_end_construct command is required for every such class of which an object is constructed through a class definition.

Normally, the macro command that is to be called on object (or subclass) creation is identified on the class command line after the keyword endmac. The arguments (. . .) may be values defined within the subclass definition, or they may be values drawn from the object command line of instances of the subclass, in which case the endmac macro_name syntax must be provided on the class command line of the subclass, naming the arguments to be passed to className in the forward_end_construct command within the subclass's definition.


Ge Comparison Mode

Obsolete

The GE find mode is still supported. Refer to the Find command for further details.

For Boolean comparisons you should use the >= symbol inside a Boolean expression.

Example

This is obsolete:

If iCount GE 10

This is correct:

If (iCount >= 10)

See Also

Purpose

To specify "greater than or equal to" as the operator for finds and comparisons.

Syntax

With the find command, records can be found in a database file according to the results of comparisons of a value in the record buffer with values in an index to field values in a database file:

move value to df_filename.field

find ge df_filename.field

See Find Command for a description of that command.

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the ge operator:

indicate indicator as variable ge variable

See Indicate Command for a description of that command.

if variable ge variable command

See If Command for a description of that command.

repeat

command

:

command

until variable ge variable

See Repeat Command for a description of that command.

while variable ge variable

command

:

command

end

See While Command for a description of that command.

The values of variables are compared in the order in which they are given in the command "sentence." That is, the first-named variable is tested for being greater than or equal to the second-named.

What It Does

When used with the find command, ge searches for a value in the index to the database file equal to the value in the fields in the record buffer of which the index is composed. If no such value is found, then the value in the index next greater than the buffer value is used to complete the find. If the index contains no value greater than the standard, then the greatest value in the index is used to complete the find.

move "BONAPAR" to emperors.last_name

find ge emperors.last_name

In this example, the value of BONAPAR is moved to record buffer Field last_name for Database File emperors after emperors has been opened and its record buffer cleared. The subsequent find command finds the first record in emperors whose last_name field is equal to or greater than BONAPAR, using the main index for that field. Field last_name must be indexed.

When used as a find mode by an index containing one or more segments designated "upper case," ge will find a record containing greater or equal letter value regardless of capitalization in either the record field or the search key. If one or more segments is designated "descending," find ge will actually find le relative to the record values to produce the desired descending sequence.

When used in comparisons, ge converts the type of the "standard" variable to the same type as the first-named variable and executes the controlled command according to whether the first-named variable is at least equal to the standard.

indicate prospect as income ge 4000

[prospect] gosub mail_adv

In this example, Indicator prospect is set true when the value of Variable income is 4000 or more. The second line executes Labelled Subroutine mail_adv when prospect is true.

while windowindex ge 0

move 0 to form.5&

calc (windowindex 1) to windowindex

loop

In this example, the value of 0 is displayed to windows in Image form in descending order until the first window is reached (inclusive). The loop is executed so long as the value of Predefined Variable windowindex is greater than or equal to zero. Note the calc command, which decrements the value of windowindex so that it does eventually reach zero.

Notes

  • Ge always finds a record unless the file is empty. A find ge even after the last record in the file will still return the last record. It always sets the Predefined Indicators found true, and finderr false. Note that this behavior is different than for le. A find le before the first record in the file will not return a record, and will set the Predefined Indicators finderr true, and found false.

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match.

  • For the find command, DataFlex uses five find Mode operators: eq, ge, gt, le, lt.

  • Ge applies to strings and dates as well as to numeric values. For strings, "greater" means "alphabetically after," and for dates, it means "later than", except for index segments designated "descending," where the opposite occurs.

  • Ge may not be used in logical expressions (comparisons enclosed in parentheses). In expressions, >= is to be used.


GetAddress

GetAddress Command

Obsolete

Refer to the AddressOf function.

See Also

Purpose

The GetAddress Command returns the memory address of a Visual DataFlex string variable. GetAddress is most often used to pass the address of a structure stored in a Visual DataFlex string to an external function.

Syntax

GetAddress Of {variable-name} To {variable}

Argument Explanation

variable_name The name of a string variable.

variable The integer variable that stores the address of the named string variable.

What It Does

This function is used to pass the address of a structure to an external function. The following example is part of the example for the Field command. GetAddress is used to get the address of the string sCommDCB into the pointer pCommDCB that is passed to the Windows Win32 API function BuildCommDCB.

// Set up the Com port.

Function CommSetup Returns Integer

String sCommDCB // Buffer for accessing DCB.

Pointer pCommDcb

// Reset the structure. Fill it with nulls.

// Note: The Type command automatically creates the _Size constant.

// Its value is the size of the data structure in bytes.

Move (Repeat( Character(0), commDCB_SIZE )) to sCommDCB

// The commDCB structure requires the size as the first field.

Put CommDCB_Size To sCommDCB At cDCBLength

// Get a pointer to the VDF string.

// Structures must be passed by pointer.

GetAddress Of sCommDCB To pCommDCB

// BuildCommDCB fills a CommDCB, based on a Mode command string.

If (BuildCommDCB( ModeString(Self), pCommDCB ));

Function_Return TRUE

Else;

Function_Return FALSE

End_Function

Notes

  • GetAddress can only be used with string variables.

  • The AddressOf function is simpler to use and more powerful.


Getbuff

Getbuff Command

Obsolete

This command is obsolete. Use Struct and End_Struct.

See Also

Purpose

To return the value of an integer from a string field.

Syntax

Getbuff From {buffer} At {field} To {variable}

Argument Explanation

iBuffer The name of the complex data structure containing field

iField The name of the field whose value is to be moved to variable

variable Receiving variable.

What It Does

Getbuff retrieves the value of an integer field of a complex data structure. See the Field command for an example that uses the Getbuff command to retrieve the baud rate.

Example

This simple example demonstrates the use of Getbuff to retrieve the version number of Windows:

External_Function GetVersionEx "GetVersionExA" KERNEL32.DLL ;

Pointer lpVersionInformation Returns Integer

Type _OSVERSIONINFO

Field dwOSVersionInfoSize As dWord

Field dwMajorVersion As dWord

Field dwMinorVersion As dWord

Field dwBuildNumber As dWord

Field dwPlatformId As dWord

Field szCSDVersion As Char 128

End_Type // _OSVERSIONINFO

String sVersionInfo

Pointer pVersionInfo

Integer bTest

Integer iSize

Integer iMajorVersionNo

String sDescription

// Initialize buffer. _OSVERSIONINFO_SIZE Is generated by

// the Type/End_Type command automatically.

Move (Repeat( Character(0), _OSVERSIONINFO_SIZE )) to sVersionInfo

Put _OSVERSIONINFO_SIZE to sVersionInfo At dwOSVersionInfoSize

GetAddress Of sVersionInfo To pVersionInfo

Move (GetVersionEx(pVersionInfo)) To bTest

GetBuff From sVersionInfo At dwMajorVersion To iMajorVersionNo

Showln "Major Version Number: " iMajorVersionNo


Getbuff_String

Getbuff_String Command

Obsolete

This command is obsolete. Use Struct and End_Struct.

See Also

Purpose

To return the value of a string field in a complex data structure.

Syntax

Getbuff_String From {buffer} At {field} To {variable}

Argument Explanation

buffer The name of the complex data structure containing field

field The name of the field whose value is to be moved to variable

variable A String variable to contain the value of field.

What It Does

Getbuff_string retrieves the value of a string field in a complex data structure.

Notes

  • This command returns a value in the full length of field. That is, fields in complex data structure are padded out to their full length with ASCII zeroes. These padding characters are returned by this command to variable.


Get_current_colors Command

Obsolete

This command is obsolete. Object colors are accessed via the Color and TextColor properties.

Purpose

To retrieve the current foreground and background colors.

Syntax

get_Current_Colors to foreground background

Argument Explanation

foreground A variable to contain the number of the foreground color.

background A variable to contain the number of the background color.


Get_Current_Lockcount

Obsolete

The get_current_lockcount command is Obsolete. Use the DF_TRAN_COUNT attribute in its place.

See Also: Lock, Reread, Unlock

Purpose

To retrieve the number of locks currently in effect.

Syntax

Get_Current_Lockcount To {variable}

The value of variable would be 0 if no locks are in effect, 3 if three lock or reread commands have been executed with no unlocks in between.

What It Does

The Get_Current_Lockcount returns the number of locks that are currently in effect. A lock occurs when Reread or Lock commands execute. The following program shows how the number of locks can be retrieved.

Example

Integer iLockCount

Integer hInvtFile

// Retrieve the current directory.

Get_Current_Lockcount To iLockCount

Showln "First, there are " iLockCount " Locks."

Open "Invt" As hInvtFile

If (hInvtFile <> -1) Begin

Showln "Locking Invt"

Lock

Get_Current_Lockcount To iLockCount

Showln "Now, there is " iLockCount " Lock."

Showln "Unlocking Invt"

Unlock

Get_Current_Lockcount To iLockCount

Showln "At the end there are " iLockCount " Locks."

End


Get_cursor_visible Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

Refer to the CursorShape class for dealing with cursors in Visual DataFlex.

See Also

Purpose

To return the state (visible or invisible) of the cursor.

Syntax

get_Cursor_Visible variable

Variable will be set to 1 (true) if the cursor is visible when this command is executed, 0 (false) if it is invisible.

What It Does

This command enables you to determine whether the cursor is currently visible, for such purposes as toggling its visibility.

Notes

  • You can set the visibility of the cursor with the set_cursor_visible command.


Get_date_format Command

Obsolete

This command is replaced by the DF_DATE_FORMAT Database API attribute.

Purpose

To retrieve the date format being used by the system.

Syntax

get_date_format to variable

Argument Explanation

variable A variable to contain the Integer value for the date-format property:

  • DF_DATE_ USA is USA format (month/day/year)

  • DF_DATE_EUROPEAN is European format (day/month/year)

  • DF_DATE_MILITARY is Military format (year.month.day).


Get_default_map_mode Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To retrieve the default map mode being used by the system.

Syntax

get_default_map_mode to variable

Argument Explanation

variable A variable to contain the Integer value for the map_mode property:

  • MAP_DEVICE

  • MAP_CHARACTER

  • MAP_DIALOG

What It Does

Get_default_map_mode returns to variable the integer value of the map_mode property for the desktop. This mode applies to all objects that do not set their own map_modes explicitly in either their class definitions or their object definitions. This map_mode is MAP_DIALOG unless a previous set_default_map_mode statement has set it to a different value. See Map_mode Property for explanations of the modes.

integer defMode

get_default_map_mode to defMode

if defMode ne MAP_DIALOG begin

In this example, the default_map_mode is moved to Integer Variable defMode. If the default mode is not MAP_DIALOG, the statements following the last one shown above are executed.

Notes

  • This command is usable only in the Windows 95 operating system or later.


Get_Drive_Directory

Obsolete

This command is replaced by the Get_Directory command.

See Also

Purpose

To read the path of the user's current directory for a specific drive into the program.

Syntax

get_drive_directory drive to variable

Argument Explanation

drive Must be, or contain, an Integer value ordinally identifying the drive.

What It Does

Get_drive_directory returns the current path for the named drive in variable.

string oldDirA

get_drive_directory 1 to oldDirA

In this example, the value of the current directory for the first drive on the system (typically A:) is moved to String Variable astring. If the drive's current directory was \MIKE S\UI\UI_PROG, that would be the value of astring.

The directory returned will be the one that is current for drive. Drive of 0 will return the directory for the user's current drive.

Notes

  • You may provide users the opportunity to change directories while program execution is suspended with runprogram wait, but upon return to the program, the current directory will be the same as it was before runprogram wait.

  • Users' current directories cannot be changed while a DataFlex program is running.

  • The files in a directory can be displayed with the directory command, and can be read into the program with the dir: driver of the direct_input command.


Get_filelist Command

Obsolete

This command is replaced by the DF_FILELIST_NAME Database API attribute.

See Also

Purpose

To return the name of the current file-list file.

Syntax

get_filelist variable

Argument Explanation

variable A String variable to hold the name of the file being used as the file list.

What It Does

Get_filelist will retrieve the name of the file-list file currently being used by DataFlex. It may be the default file list found through the DFPATH environment variable, or it may be one set through the use of the set_filelist command.

string current_filelist

get_filelist current_filelist

This example retrieves the name of the current file-list file into Variable current_filelist.

Notes

  • The default name of the file-list file is FILELIST.CFG.


Get_Foreign_Profile_String

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To return the value of a setting from the Registry.

Syntax

Get_Foreign_Profile_String {key-name} {sub-keyname} {value-name} To {variable}

Argument Explanation

sKeyname The name of a key within the registry. The fully-qualified keyname of the specified key is found by concatenating the branch parameter of the SET_REGISTRY_ROOT command (default = "Software") with the contents of the keyname parameter and the contents of the subkeyname parameter. If the key doesn't exist, "Defaults" is searched for a subkey of subkeyname.

sSubkeyname The name of the subkey within keyname to be set. See the description of keyname for how to assemble the fully-qualified registry key name.

sValuename A value name defined in the key keyname.

variable A string variable into which the content of the registry value is stored

What It Does

Get_Foreign_Profile_String returns a value stored in the registry.

Example

// Strings to hold paths.

String sRegPath sKey sValueName sValueData

// Set the registry root.

Set_Registry_Root to HKEY_LOCAL_MACHINE 'Software'

Move 'Classes' to sRegPath

Move '.Html' to sKey

Move 'Content Type' to sValueName

Get_Foreign_Profile_String sRegPath sKey sValueName to sValueData

Showln "Path = " sRegPath "\" sKey ", Value is " sValueName ;

", Data is " sValueData

// Find a key that's in a little deeper.

Move 'Clients\Mail\Exchange\Shell\Open' to sRegPath

Move 'Command' to sKey

Move '' to sValueName // Get default value.

Get_Foreign_Profile_String sRegPath sKey sValueName to sValueData

Showln "Path = " sRegPath "\" sKey ", Value is " sValueName;

", Data is " sValueData

Notes

  • If no subkey is found for the supplied key sKeyName, the defaults key, [Defaults], is searched.

  • If no value is found in the key specified for the value name specified, an empty string is returned.

  • The system will perform type conversion if the variable that receives the value is not a string.


Get_number_format Command

Obsolete

This command is replaced by the DF_DECIMAL_SEPARATOR and DF_THOUSANDS_SEPARATOR Database API attributes.

Purpose

To retrieve the type of number punctuation in use by the system.

Syntax

get_number_format to number_format

Argument Explanation

number_format A variable to contain the Integer value specifying the number format.

0 in number_format indicates period for the radix, comma for the thousands' separator (9,999.99). 1 indicates comma for the radix, period for the thousands' separator (9.999,99).


Get_Profile_String

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To return the value of a setting from the DataFlex branch under SOFTWARE in the Registry.

Syntax

Get_Profile_String {sub-keyname} {value-name} To {variable}

Argument Explanation

subkeyname The name of a subkey of the default DataFlex path defined as "Data Access Corporation\\Visual DataFlex\\5" for DataFlex 5.

valuename The name of a value defined for the key subkeyname.

variable A string variable into which the contents of the registry value are returned.

What It Does

Get_profile_string returns values from the DataFlex registry settings.

string sVDFfilename

get_profile_string "BIG" "EXE" To sVDFfilename

In this example, the DataFlex branch is searched for a section labeled BIG and within it, an item named EXE. If such is found, the value is returned to string sVdffilename.

Notes

  • If no subkey named keyname is found in the DataFlex branch, the DEFAULTS section is searched for a value named valuename. If valuename is found there, its contents are returned in variable. All other find failures result in a null return value.

  • Variable does not have to be of Type String; however, if it is of any other type, the possibility that the return value may violate the requirements of the type is present, as it is not in Type String.


Get_Program_Key

Obsolete

This command is obsolete. There is no Visual DataFlex equivalent for this option.

See Also

Purpose

To return the name of the registry key (if any) by which the DFRUN command executed the program.

Syntax

Get_Program_Key To {variable}

Argument | Explanation
variable | A variable into which the name of the registry key is returned.

What It Does

This command returns the (registry) program-key name that was used with the DFRUN operating-system command to execute the currently running program. If the program is started with the VDF program name, the program key returns an empty string.

Example

The following example returns the name of the program key used to execute the program. The VDF value for the registry key contains the name of the program to execute.

String sProgram

Get_Program_Key to sProgram

if (sProgram NE "");

Showln "The program key used to execute this program is " sProgram

Else;

Showln "The program was run without a key."


Get_Registry_Root

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To returns the current settings of the registry root and branch that Visual DataFlex uses to search the registry.

Syntax

Get_Registry_Root To {Root} {Branch}

Argument Explanation

sRoot The name of a root in the Windows registry. This may be one of the following values:

  • HKEY_CLASSES_ROOT COM class and file type information. Sub-tree of HKEY_LOCAL_MACHINE.

  • HKEY_CURRENT_USER Sub-tree of HKEY_USERS which corresponds to the information about the current user. This is where user-specific information for an application can be stored.

  • HKEY_LOCAL_MACHINE This is where all global (not user specific) machine information is stored. This tree contains the Software branch where most applications store their global information. This is the default setting for Visual DataFlex.

  • HKEY_USERS This is where all user-specific information is stored. The sub-tree for the current user is better accessed through HKEY_CURRENT_USER.

  • HKEY_PERFORMANCE_DATA Not generally used by applications.

  • HKEY_CURRENT_CONFIG Not generally used by applications.

  • HKEY_DYN_DATA Not generally used by applications.

sBranch The name of a branch under root in the Windows registry. The most common branch for applications is "Software".

What It Does

Returns the registry root and branch settings. Use Set_Registry_Root to change the registry root and/or branch.

Example

Integer iRegistryRoot // Integers (defined in registry.pkg)

String sRegistryBranch // String value that is top branch.

// Set up registry to access user preferences.

Set_Registry_Root to HKEY_USERS "Default"

// Show that it has been changed.

Get_Registry_Root to iRegistryRoot sRegistryBranch

Showln "Root: " iRegistryRoot " Branch: " sRegistryBranch


Gosub Command

Obsolete

You should use procedures and functions instead of subroutines.

See Also

Purpose

To move execution to a part of a program (a subroutine) located under a label and then return execution to the next line after the gosub.

Syntax

gosub label

Argument Explanation

label Must be given literally in the command, without colon or quotation marks.

What It Does

Gosub "stacks" the number of the statement that follows the gosub command line and transfers execution to the part of the program (a subroutine) at label. When a Gosub_Return command is executed in the subroutine, the number is taken off the stack and execution continues at the line following the gosub, unless the Gosub_Return command named a label itself, in which case execution goes there.

showln 1

gosub demo

showln 3

abort

demo:

showln 2

Gosub_Return

This program first displays 1. Then, the gosub command line passes execution to the line labelled demo:. From there the line displaying 2 is executed, and then the Gosub_Return. The Gosub_Return passes execution back to the third line from the beginning, which displays 3. After that, the program terminates.

Labels are any unbroken unique string at the beginning of a command line ending in a colon (:).

Notes

  • DataFlex can "stack" up to 18 line numbers at one time, adding a number each time a gosub is executed, and removing the most-recently added number each time a Gosub_Return is executed. All subroutines must end in a return command.

  • Even if there are no errors at compile time, if your program allows multiple executions of gosub without a Gosub_Return, the maximum "stack depth" may be exceeded at run time, in which case Error 97 (Multiple GOSUBS without RETURN) will be triggered.

  • Gosub command lines may be controlled with conditionals, such as indicators or if tests.

  • The goto command transfers execution to a label, but does not stack the return address as does gosub. You cannot use the Gosub_Return command to return to the command line following a goto command.

  • Labelled subroutines may be located in the program's main path of execution (above the final abort, system, or chain command), but it is preferable to locate them below the terminating command to ensure that they are executed only when intended (by gosub commands).


Gosub_Return Command

Obsolete

You should use procedures and functions instead of subroutines.

Purpose

To specify where execution should continue after execution of a subroutine. Use this command instead of the Return command.

Syntax

Gosub_Return [Return] [{label}]

What It Does

Used with no argument at the end of a labelled subroutine, Gosub_Return moves execution back to the first command following the gosub or on gosub command that executed the subroutine

Used with a {label} argument at the end of a labelled subroutine, Gosub_Return moves execution to the location of a label in the program. Used with an argument of return, the Gosub_Return command moves execution to the first command following the gosub or on gosub command which executed the subroutine which contained the gosub or on gosub command that executed the subroutine.

The stack:

Whenever a gosub is done, the line number of the command after the gosub is "pushed" onto a "stack." A stack is a last in-first-out method of storing return addresses. Whenever a Gosub_Return is done, that addressed is "popped" from this stack and execution continues at that address. There may be up to 20 return values on the stack at any one time. If you do a gosub to a subroutine and then fail to return from it (i.e. by doing a goto somewhere else in the program) you will accumulate values on the gosub stack. This will eventually result in an Error 97 (Too many GOSUBs without RETURN). Therefore be sure to return from a subroutine; do not goto out of it!

gosub delivery

chain invoice

delivery:

showln "We're On Our Way!"

increment sales

Gosub_Return

In this example, the gosub command sends execution to Labelled Subroutine delivery. When delivery has executed (increment), the Gosub_Return command moves execution to the next command after the gosub (chain).

A label argument after a Gosub_Return command sends execution to the location of label.

gosub delivery

chain invoice

cancel:

move (sales 1) to sales

abort

delivery:

showln "We're On Our Way!"

increment sales

if customers eq 0 Gosub_Return cancel

Gosub_Return

In this example, the gosub command sends execution to Labelled Subroutine delivery. When delivery has executed (increment), the conditional (if) Gosub_Return command moves execution to Label cancel if the value of Variable customers is zero. If the value of customers is not zero, execution returns to the first command after the gosub (chain).

When you execute a gosub from within a subroutine, you must not return to a label that is outside the original subroutine (below its return command). This is because the original gosub command places an address on the return address stack when it executes, and the second gosub command places a second address on the stack. If the Gosub_Return from the secondary subroutine does not return to a point inside the primary subroutine, the address left by execution of the primary subroutine is never cleared. If this is done repeatedly, addresses from the primary subroutine eventually accumulate to fill the stack, and a DataFlex Error 97 (Too many GOSUBs without RETURN) is triggered at runtime. The compiler cannot detect this condition, and will not report it at compile time.


Graphics_adjust_coords Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

Purpose

To set the graphics world to match the map mode of the current virtual console (the object you'll be drawing the graphics on - e.g., a BasicPanel object).

Syntax

Graphics_Adjust_Coords pHeight pWidth

Argument Explanation

pHeight and pWidth Are of type Integer

What It Does

Graphics_Adjust_Coords sets the maximum height of the graphic world (in pixels) to the value of pHeight. Likewise, the maximum width is set to pWidth.


Group Command Component

Obsolete

Indicators are obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To set the value of an indicator based on the value of up to six other indicators.

Syntax

indicate indicator group any|all [indicator [indicator] [indicator]] ;

[and|or any|all [indicator [indicator] [indicator]]]

The value of the first-named indicator is set by the values of the succeeding indicators, between two and six of them.

The [brackets] are typed in the command, and each pair delimits one group of indicators, of which the first is required, and the second, optional.

Each group of indicators may contain between one and three indicators.

Each group of indicators must be preceded by either any or all. Any sets the value of the group true if one or more of the indicators is true, while all sets the value of the group true only if all of the indicators are true.

If the command uses the optional second group of indicators, its value must be conjoined with that of the first by the use of either and or or. And sets the value of the two groups true only if both groups evaluate true, while or sets the value of the two groups true if either group evaluates as true.

The value invertor not may be used before any indicator.

The semi colon (;) is shown only to enable the single, long command line to be shown as two physical lines. The semi colon has this effect when used (as many times in one line as required) in actual program source code, up to a maximum command line length of 255 characters.

What It Does

Group evaluates up to two groups of up to three indicators each, conjoining the values of the indicators within each group with any or all, and the values of the groups by and or or. It may be used only with the indicate command, and sets the value of the indicator first named in the command.

indicate good group;

all [kind honest faithful ] and;

any [brave wise fair ]

In this example, if Indicators kind, honest, and faithful are all true and at least one of the Indicators brave, wise, and fair is true, Indicator good will be set true. Good will be set false if either kind, honest, or faithful is false, or if neither brave, wise, nor fair is true. The semi colon line breaks and spacing are only to accommodate physical line length and readability.

indicate bad group;

any [larcenous jealous vicious] or;

any [not good]

In this example, Indicator bad is set true if either Indicator larcenous, jealous, or vicious is true, or Indicator good is false. If larcenous, jealous, and vicious are all false and good is true, bad will be set false.

These are but two of the many possibilities that can be created with various patterns of all, any, and, or, and not.

Notes

  • Group replaces the as in the format of the indicate command.

  • You may have up to two groups of indicators per indicate indicator group command. You can have up to three indicators per group.

  • You must enclose groups of indicators in square brackets ([]), even if the group contains only one indicator. The conjoiner any or all must be used before each group of indicators, even though they have no effect on groups of one indicator.

  • You may use not to reverse the sense of any indicator. You may use the tilde character (~) as a direct replacement for the word not.


Gt Comparison Mode

Obsolete

The GT find mode is still supported. Refer to the Find command for further details.

For Boolean comparisons you should use the > symbol inside a Boolean expression.

Example

This is obsolete:

If iCount GT 10

This is correct:

If (iCount > 10)

See Also

Purpose

To specify "greater than" as the operator for finds and comparisons.

Syntax

With the find command, records can be found in a database file according to the results of comparisons of a value in the record buffer with values in an index to field values in a database file:

move value to df_filename.field

find gt df_filename.field

See Find Command for a description of that command.

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the gt operator:

indicate indicator as variable gt variable

See Indicate Command for a description of that command.

if variable gt variable command

See If Command for a description of that command.

repeat

command

:

command

until variable gt variable

See Repeat Command for a description of that command.

while variable gt variable

command

:

command

end

See While Command for a description of that command.

The values of variables are compared in the order in which they are given in the statement. That is, the first-named variable is tested for being greater than the second-named.

What It Does

When used with the find command, gt searches for a value in the index to the database file equal to the value in the fields in the record buffer of which the index is composed. Then the value in the index next greater than the buffer value is used to complete the find. If the index contains no value greater than the standard, then the find is unsuccessful and Predefined Indicator found is set false.

move "BONAPAR" to emperors.last_name

find gt emperors.last_name

In this example, the value of BONAPAR is moved to record buffer Field last_name for Database File emperors after emperors has been opened and its record buffer cleared. The subsequent find command finds the first record in emperors whose last_name field is greater than BONAPAR, using the main index for that field. Field last_name must be indexed.

When used as a find mode by an index containing one or more segments designated "upper case," gt will find a record containing greater letter value regardless of capitalization in either the record field or the search key. If one or more segments is designated "descending," find gt will actually find lt relative to the record values to produce the desired descending sequence.

When used in comparisons, gt converts the type of the "standard" variable to the same type as the first-named variable and executes the controlled command according to whether the first-named variable is greater than the standard.

indicate prospect as income gt 4000

[prospect] gosub mail_adv

In this example, Indicator prospect is set true when the value of Variable income is more than 4000. The second line executes Labelled Subroutine mail_adv when prospect is true.

while windowindex gt 0

move 0 to form.5&

calc (windowindex 1) to windowindex

loop

In this example, the value of 0 is displayed to windows in Image form in descending order until the first window is reached. The loop is executed so long as the value of Predefined Variable windowindex is greater than zero. Note the calc command, which decrements the value of windowindex so that it does eventually reach zero.

Notes

  • Find gt commands in a loop will "step through" a database file record by record in ascending order by the index in use from the index value of whatever record is in the buffer at the time the loop is started. This is useful for record-by-record reports, and will start at the beginning of the index if the loop is started when the record buffer is clear.

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match.

  • For the find command, DataFlex uses five find Mode operators: eq, ge, gt, le, lt.

  • Gt applies to strings and dates as well as to numeric values. For strings, "greater" means "alphabetically after," and for dates, it means "later than", except for index segments designated "descending," where the opposite occurs.

  • Gt may not be used in logical expressions (comparisons enclosed in parentheses). In expressions, > is to be used.


Ifchange Command

Obsolete

This command is replaced by the DF_FILE_CHANGED Database API attribute.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To execute a command according to whether a change has been made to a record buffer.

Syntax

ifchange df_filename command

Argument Explanation

df_filename Must be named literally (without quotation marks).

command Must be given literally (without quotation marks).

What It Does

Ifchange df_filename executes command if there has been a change to any field of the record buffer for df_filename since the buffer was last filled, as part of a reread, save, clear, or successful find command.

ifchange pay gosub logchange

If any change has been put to the record buffer for Database File pay since the last time its buffer was filled, Subroutine logchange will be executed.

Ifchange df_filename is generally used to take an action when any change is made to a file, such as posting to a log of all changes made to df_filename.

Notes

  • Ifchange operates on a change of value since the last runtime operation which noted that change. Thus, if the same value is entered from the keyboard as was previously in the window or field, no change will be recognized (the command will not be executed).

  • Clearing an existing value from an item does not produce a change in the record buffer. An entry of zero to a Numeric field or spaces to a String field will not cause ifchange commands to be executed.

  • The else command may not be used with ifchange. To control program action on a buffer's not having changed, declare an indicator (or set it false) and reset its value with an ifchange command, as

indicate new_customer false

ifchange customer indicate new_customer true

In this example, Indicator new_customer is set false and then, if a change has occurred in the buffer of File customer, set true.


In Comparison Mode

Obsolete

The In comparison mode is replaced by the Contains operator.

See Also

Purpose

To specify "includes" as the operator for comparisons.

Syntax

( {sub-string} in {host-string} )

where {host-string} is the string being parse; and {sub-string} the string being searched for. {host-string} and {sub-string} can be either a literal or a string variable.

What It Does

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the in operator.

Example

string sSub sAlphabet

move "abcdefgijklmnopqrstuvwxyz" to sAlphabet

move "abc" to sSub

if sSub in sAlphabet send Info_Box sSub "Part of Alphabet"

Example

string sCurrentName sLastName sPhoneNumber

move "Smith" to sLastName

direct_input channel 2 "PhoneBook.txt"

repeat

read channel 2 sLastName sPhoneNumber

until sLastName in sCurrentName

Notes

  • In can be used to determine whether literal numbers and the values of number and date variables are included in the contents of Numeric and Date variables.

  • In is case sensitive.

  • For the if, indicate, until, and while commands, DataFlex uses eight comparison mode operators: eq, ge, gt, in, le, lt, ne, and match. In and match operate according to the character contents of variables, while the other operators deal in sequences and numeric quantities.

  • In is effective where the position of a search substring in the string being checked is unknown, variable, or irrelevant. Where you wish to check only a known position in the string being checked, the "wildcard" characters of the match comparison mode are more useful.

  • In the contains operator, the target substring is given in the second-given argument, rather than in the first, as it is in the in comparison mode. Operators may be used in expressions, and may not be used outside them.


Inactivate Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To render the record in the buffer inactive.

Syntax

inactivate fileName [keep]

What It Does

The inactivate command makes an active record inactive by moving a 0 to the record's recnum. Unlike the clear command, it retains all current field values. Once a record is inactivated, then data may be moved in to the record's fields without the dreaded Edited Record Not Saved error occurring. Inactivate is often used when you need to change a field's value before performing a find (allowing you to jump around in an index, for example).

If the keep parameter is passed, the recnum value is maintained in the record. When keep is used a 0 is moved to the recnum (inactivating the record) and then the original record number is moved back into recnum. The result is an inactive record which still contains the original record number.

Be careful about saving a record that has been inactivated. Once a record is inactivated, the record will be saved as a new record with a new record number (even if you use the keep parameter). This can actually be used as a feature if you need to duplicate a record (assuming that the duplication will not result in a duplicate index error).

You could as easily inactivate a record by entering the statement move 0 to file.field. The advantage of the inactivate command is that it makes the programmer's intent clearer.

Example:Assume that you are performing an update where you are changing all Vendors' status from A to I. The field vendor.status is an indexed field. The quickest way to make this update is to find all vendor.statuses with an A by the vendor.status index. The problem which arises is that each save changes the status index value, which we must then reset so that our finds continue in order. If you reset vendor.status by placing an A back into vendor.status without first inactivating the record, you're going to get an error message!

Clear Vendor // start of file

Move 'A' to Vendor.Status // seed the index

Repeat

Find Gt Vendor.Status // get record

[Found] Ind Found as Vendor.Status eq 'A' // is it A?

[Not Found] Break // If not 'A' or no rec.. exit.

Move 'I' to Vendor.Status // change status

SaveRecord Vendor // save it

Inactivate Vendor KEEP // now..restore index for

Move 'A' to Vendor.Status // the next find

Loop


Ind Command

Obsolete

Indicators are obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To set an existing indicator.

Syntax

ind indicator as test

The ind command is identical to the indicate command except that an error will be declared if the named indicator does not exist. The indicate command automatically defines indicator if it does not yet exist. The ind command will generate a compiler error if indicator has not been previously declared by either an indicator or an indicate command. Use the ind statement if you would prefer to discover your spelling errors during compilation and not after the program is in the field!

ind add_mode as file.field eq 'Y'


Indicate Command

Obsolete

Indicators are obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To set an indicator true or false based on a logical test or the value(s) of other indicator(s).

Syntax

Literal:

indicate indicator true|false

Comparison:

indicate indicator as variable lt|le|eq|ge|gt|ne|in|match variable

One other indicator:

indicate indicator as [indicator]

Multiple other indicator(s):

indicate indicator group any|all [indicator [indicator] [indicator]]

[and|or any|all [indicator [indicator][indicator]]]

Expression:

(expression)

Buffer status:

indicate indicator status df_filename

When indicator is the first-named (set) indicator, it must not have brackets [] around it, and when it is (one of the) later-named (setting) indicator(s), it (they) must have brackets around it (them).

What It Does

Indicate sets the value (true or false) of the first-named indicator according to: a literal true or false; the results of a comparison of the values of two variables; the value of one second-named indicator; the values of several later-named indicators; or the status of a record buffer.

The word not before the name of any indicator inverts the result of the command (from true to false and from false to true). When an indicator is used in brackets [], the not must also be within the brackets.

The value of an indicator may be set to a literal true or false unconditionally:

indicate purchase false

In this example, Indicator purchase is set false. The value of purchase remains false until another indicate command sets it true.

The value of an indicator may be set according to the results of a comparison of the values of two variables:

indicate in_stock as sale_quan lt on_hand

In this example Indicator in_stock is set true if the value of variable sale_quan is less than (lt) the value of variable on_hand.

The value of an indicator may be set according to the value of another indicator:

indicate approved as [credit_checked]

In this example, Indicator approved is set true if Indicator credit_checked is true. If credit_checked is false, approved will be set false.

The value of an indicator may be set according to combinations of the value of one or two groups of indicators:

indicate good group;

all [kind honest faithful ] and;

any [brave wise fair ]

In this example, if Indicators kind, honest, and faithful are all true and at least one of the Indicators brave, wise, and fair is true, Indicator good will be set true. Good will be set false if either kind, honest, or faithful is false, or if neither brave, wise, nor fair is true. The semi colon line breaks and spacing are only to accommodate physical line length and readability.

See Group Command Component for explanations of the all and any indicator conjoiners, and the and and or group conjoiners.

The value of an indicator may be set according to whether a record in the record buffer for a database file is active:

indicate ready status vendor

In this example, Indicator ready is set true if the record buffer for the vendor file contains an active record.

This is useful when you are doing successive finds in several files, and need program action which depends on whether the find for a particular file was successful.

Indicator can be driven by the Boolean value of a logical expression.

indicate warm as (temperature >=35)

In this example, Indicator warm is set true if the value of Variable temperature is greater than or equal to 35. If the value of temperature is less than 35, Indicator warm is set false.

Indicator can be driven by the value of a mathematical variable or expression. The integer value zero (0) is Boolean false, while any other value, positive or negative, is true.

indicate leapyear as not (mod(year, 4))

In this example, if the modulo (remainder) of dividing the value of integer Variable year by 4 is 0 (false), Indicator leapyear is set true. If the value of year is not evenly divisible by 4, leapyear would be set false. By itself, this test would yield a wrong result for years evenly divisible by 100 (which are not leap years).

Using Indicators:

Indicators are used to make execution of a command line conditional on the value of the indicator. Used this way, they are placed at the beginning of a command line, in brackets []:

[bird] showln "Good chance it can fly!"

In this example, the showln command is executed if Indicator bird is true. If bird is false, the command is skipped.

Indicators can be notted in the command line:

[not bird] showln "Can't fly without an airplane!"

In this way, up to three indicators may be combined to control a command line:

[active credit_ok not delinquent] begin

accept amount to trans.amount

save trans

end

In this example the begin ... end block is executed if Indicators active and credit_ok, are true and delinquent is false. If either active, or credit_ok is false or delinquent is true, execution skips to the first command after the end command. As shown, not can be used among multiple indicators to invert the value of any of the indicators.

The following commands provide exactly the same action as the example above, without the begin ... end block:

[active credit_ok not delinquent] entry_item trans.amount

[active credit_ok not delinquent] save trans

Notes

  • You may reverse the sense of most forms of the indicate command by using the word not.

indicate out as [not credit_check]

This sets Indicator out true if Indicator credit_check is false.

  • You can even invert the value of an indicator unconditionally without having to determine its value:

indicate invert as [not invert]

or:

indicate not invert as [invert]

  • You may also reverse the value of individual indicators within groups by using not.

indicate bird group any [chicken flamingo not bat]

Bird is true if Indicator chicken is true, or flamingo is true or bat is false.

Once indicators are set, they may be used at the beginning of any command line to make that command line execute conditionally on the value of the indicator(s).

  • Rule of thumb: when there are three or fewer successive commands to be controlled by the same indicator(s), use the indicator(s) on each line. When there are more than three successive commands, use a begin . . . end block with the indicator(s) only on the begin. When commands to be controlled are not successive, direct use of the indicator(s) is called for.

  • Indicators can be used to control indicate command lines the same as any other command line:

[go_ahead] indicate done as balance eq 0

In this example, Indicator done is set true if Variable balance equals 0, but only if Indicator go_ahead is true. If go_ahead is false, the command is not executed (done remains unchanged).

  • A variable or expression with a value of zero (0) or blank provides a setting value of false. A variable or expression with a value other than zero provides a setting value of true.


Indicator Command

Obsolete

Indicators are obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To declare indicators.

Syntax

indicator indicator [... indicator]

The first indicator is required. Up to nine indicators may be declared on one command line, with their names separated from each other by spaces. Indicator names may be between 1 and 80 characters in length, must start with a letter, and may not contain spaces.

What It Does

The indicator command establishes up to nine indicators. Upon declaration, every indicator is false.

DataFlex uses indicators to determine whether to execute command lines which begin with indicators in brackets []. If the indicator is false, the command is not executed; if it is true, the command is executed. See Indicate Command.

Indicators should be declared with the indicator command and their values set true or false by program action before they are used to control execution of commands.

indicator fried boiled scrambled hard

In this example, four indicators, fried, boiled, scrambled, and hard are established. Upon execution of this command, they are all false.

Notes

  • While it is absolutely necessary to declare the other types of variables (Date, Integer, Numeric, and String), indicators may be declared without the indicator command.

indicate new_indicator as [not old_indicator]

  • If Indicator old_indicator had not been declared previously, this command would trigger an error at compile time, but Indicator new_indicator would, if it did not previously exist, be created as a result of execution of this command.

  • The main reason for declaring indicators is to make the source code clearer to anyone reading it. For that reason we recommend that you do declare indicators with the indicator command.

  • At run time, indicators are more efficient for controlling execution of commands than if test commands, because if tests require more processing than true/false evaluation of indicators.


Insert Command

Obsolete

This command is replaced by the Insert function.

See Also

Purpose

To insert one string into another.

Syntax

insert source in destination [at position]

Argument Explanation

source May be of any class.

destination May not be a constant or an expression.

What It Does

Insert places source inside destination at the character position in destination designated by the value of position. The value of Predefined Variable strmark will be set to that of position.

string city

move "Niagara, NY" to city

insert " Falls" in city at 8

In this example, string Variable city is declared, and Niagara, NY is moved to it. The value of Predefined Variable strmark is set to 8. The insert command would change the value of city to Niagara Falls, NY by inserting .Falls at the 8th position in the original value of city. Note the space between the first quotation mark and the F in Falls; without it, the result would be NiagaraFalls, NY.

If position is omitted from the command, the value of Predefined Variable strmark will be used for the function. Strmark is set by the preceding left, mid, pad, pos, and replace command.

string city

move "Niagara, NY" to city

pos "," in city

insert " Falls" in city

This example yields the same results as the one above. The pos command moves the position (8) of the first comma in city to strmark. The following insert command, lacking an at position argument, inserts .Falls at the position of the comma.

If the length of destination is set in the string command which established it to a length (###) shorter than the combined inserted length, then only the first ### characters of the combined inserted value remains in destination. No error is declared if this occurs.

Notes

  • You can use insert to place blank spaces in a string, for centering, or for other purposes.

  • If position is greater than the length of destination, insert will append source to destination just as if you had used the append command.

  • If position is less than 2, insert will insert source at the beginning (left end) of destination.

  • If either source or destination is not of Type String, it will be converted internally to a string for the insert operation.

number num

move 12 to num

insert 3 in num at 2

The result of this command would be a value of 132 in num.


Item_group Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To begin the declaration of a group of items to have the same value as each other at all times.

Syntax

item_group

dependent_item ...

:

dependent_item ...

end_item_group

What It Does

This command is used to begin the list of a group of dependent items. Dependent-item groups should be declared just prior to the first start_ui statement.

A dependent-item group is created whenever a group of items must always have the same value as each other. For example, when a database field is bound to more than one item (in one or more objects), each item bound to the field must display the same value as the other items. To ensure this, you may create a dependent-item group that specifies all equivalent items.

item_group

dependent_item customerform.obj 1

dependent_item paymentform.obj 2

end_item_group

In this example, if the second item in Object customerform and the third item in Object paymentform object were both bound to Field customer.customer_name, we would create a dependent item group to ensure that both items always have the same value.

Any time data entry is performed on one of the items in the group, all of the other items in the group are set to the value of the edited item once the cursor leaves the item.


Item_list Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. In Visual DataFlex, Item_List and End_Item_List statements are maintained by the Visual DataFlex Studio for objects that use them.

See Also

Purpose

To begin the list defining the items of a menu-, entry-, or list-class object.

Syntax

item_list

entry_item . . .

:

on_item . . .

:

end_item_list

What It Does

Item_lists are used each time a menu-, entry-, or list-class object is defined. The items that are defined in the item_list will be added to the object and become part of its data structure.

Menu- and entry-class objects use a static item structure. The items in the structure may be defined only within the item_list, and may not be added to later.

List-class objects use a dynamic item structure, and uses the item_list as a convenience. List objects may add items at any time, and any on_item commands used in list objects' item lists are converted to add_item messages by the system.

For every item_list, there must be a matching end_item_list command to terminate the list.


LastErr Predefined Variable

Obsolete

This predefined variable is obsolete. Use the ErrorSystem class for error handling in Visual DataFlex.

Refer to the If command for properly structured If .. Else statements.

See Also

Purpose

To return the number of the last error triggered in the program.

Syntax

lasterr

What It Does

Each time an error is triggered, the number of the error is moved to lasterr.

You can use it with an if command to help recover from specific errors in specific places in a program.

In a place in a program where a particular error is likely to be caused by a particular program, you can provide a custom prompt to appear if that error is triggered in that place:

if lasterr eq 81 showln "RUN REINDEX"

In this example, if the value of lasterr is 81 when this line is executed, the message RUN REINDEX will be displayed on the highest unused screen line available.

Similarly, if the occurrence of a particular error in a particular place requires specific program action, that action can be provided by a command executed conditionally on the value of lasterr:

if lasterr eq 23 goto retry

In this example, if the number of the last error triggered is 23 when this line is executed, execution goes to the label retry.

The number of triggered errors depends on either of two things: (a) the number (1 through 100) of the internally set DataFlex error; or (b) the number given as the argument of an error command executed as a consequence of program action. Error commands are provided by the programmer to trigger error-handling action under circumstances not covered by the DataFlex errors. The DataFlex errors cannot be altered, and although their action can be suppressed with the on error gosub command, their being triggered will still change lasterr.


Le Comparison Mode

Obsolete

The LE find mode is still supported. Refer to the Find command for further details.

For Boolean comparisons you should use the <= symbol inside a Boolean expression.

Example

This is obsolete:

If iCount LE 10

This is correct:

If (iCount <= 10)

See Also

Purpose

To specify "less than or equal to" as the operator for finds and comparisons.

Syntax

With the find command, records can be found in a database file according to the results of comparisons of a value in the record buffer with values in an index to field values in a database file:

move value to file.field

find le file.field

See Find Command for a description of that command.

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the le operator:

indicate indicator as variable le variable

See Indicate Command for a description of that command.

if variable le variable command

See If Command for a description of that command.

repeat

command

:

command

until variable le variable

See Repeat Command for a description of that command.

while variable le variable

command

:

command

end

See While Command for a description of that command.

The values of variables are compared in the order in which they are given in the command "sentence." That is, the first-named variable is tested for being less than or equal to the second-named.

What It Does

When used with the find command, le searches for a value in the index to the database file equal to the value in the fields in the record buffer of which the index is composed. If no such value is found, then the value in the index next less than the buffer value is used to complete the find. If the index contains no value less than the standard, then the find le will fail.

open TEST

clear TEST

move 1 to test.emp_id

find le test.emp_id

[not found] showln "No record found"

For this example, if the lowest emp_id in the file TEST is 2 (or greater), then the find will fail, setting the Predefined Indicator found false. The line No record found will be printed to the screen.

move "BONAPARZ" to emperors.last_name

find le emperors.last_name

In this example, the value of BONAPARZ is moved to record buffer Field last_name for Database File emperors after emperors has been opened and its record buffer cleared. The subsequent find command finds the first record in emperors whose last_name field is equal to or less than BONAPARZ, using the main index for that field. Field last_name must be indexed.

When used as a find mode by an index containing one or more segments designated "upper case," le will find a record containing lesser or equal letter value regardless of capitalization in either the record field or the search key. If one or more segments is designated "descending," find le will actually find ge relative to the record values to produce the desired descending sequence.

When used in comparisons, le converts the type of the "standard" variable to the same type as the first-named variable and executes the controlled command according to whether the first-named variable is at least equal to the standard.

indicate reject as income le 4000

[reject] gosub next_one

In this example, Indicator reject is set true when the value of Variable income is 4000 or less. The second line executes Labelled Subroutine next_one when reject is true.

while windowindex le 5

move 0 to form.1&

increment windowindex

loop

In this example, the value of 0 is displayed to windows in Image form in ascending order until the fifth window is reached (inclusive). The loop is executed so long as the value of Predefined Variable windowindex is less than or equal to 5. Note the increment command, which increments the value of windowindex so that it does eventually reach 5.

Notes

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match.

  • For the find command, DataFlex uses five find Mode operators: eq, ge, gt, le, lt.

  • Le applies to strings and dates as well as to numeric values. For strings, "less" means "alphabetically before," and for dates, it means "earlier than", except for index segments designated descending, where the opposite occurs.

  • Le may not be used in logical expressions (comparisons enclosed in parentheses). In expressions, <= is to be used.


Left Command

Obsolete

This command is replaced by the Left function.

See Also

Purpose

To move the leftmost characters of a value to a variable.

Syntax

left value to variable [length]

What It Does

Left moves the number (counted from the left) of characters from value given in length to variable. The value of length is moved to Predefined Variable strmark.

string state abbreviation

move "CALIFORNIA" to state

left state to abbreviation 2

In this example, the left command places the first two characters (CA) into string Variable abbreviation.

If length is omitted from the command, the value of Predefined Variable strmark is used for the function. Strmark is set by the insert, mid, pad, pos, replace, and sysdate commands.

string name last_name

move "Schweitzer, Albert" to name

pos "," in name

left name to last_name

In this example, the pos command determines the position (11) of the comma in String Variable name. The left command, lacking a length argument, uses this value to extract Schweitzer, (including the comma) to move to String Variable last_name.

Notes

  • If length is less than 1, left will output no characters.

  • If length is greater than the length of value, left will output all of value.

  • Although left can be used on Date, Integer, and Number type variables, it is typically used on String type variables.

  • Value and variable may be the same variable. Used this way, left simply truncates string on the right:

left state_name to state_name 2

In this example, all characters after the second (counted from the left) are removed from the value of Variable state_name.


Length Command

Obsolete

This command is replaced by the Length function.

See Also

Purpose

To move the number of characters in a value to a variable.

Syntax

length value to variable

What It Does

Length counts the number of characters, including embedded spaces, in value and puts the result in variable.

The way it deals with leading and trailing spaces varies according to the class of value:

  • For database fields, length returns the defined length of the field.

  • For constants, length returns all characters, including all spaces, between the quotation marks.

  • For windows, length returns all characters, including leading spaces, except for trailing spaces.

  • For variables, length returns whatever was moved to the variable (see rules above for the possible sources of data in any variable). Length does not return the defined length of the variable unless it is full of characters, as all String type variables are immediately after being declared (they are full of spaces).

string riches

number digits

move "great, vast " to riches

length riches to digits

In this example, the string great, vast (with one trailing space) is moved to String-type Variable riches. The length command would put a value of 12 into digits.

Notes

  • Although length can be used on Date-, Integer-, and Number-type variables, it is typically used on String-type variables.


Local Command

Obsolete

Variables declared inside a procedure or function are automatically assumed to be local. See the declaring variables section in the Language Guide for more information.

See Also

Purpose

To define local variables for procedures and functions.

Syntax

local type name [...name]

Name is the name(s) of the local variables.

Type is the declaration command for the data type of the variable(s) being declared.

What It Does

Local variables may be declared in any procedure or function. When declared with the local keyword, such variables' names may be duplicated in other functions and procedures, facilitating internal consistency among procedures and functions that do similar things. References to local variables from outside the procedure or function in which they were defined are invalid.

Variables declared without the local keyword are said to be "global" variables. Their names may not be duplicated anywhere else in the program, not even by local variables.

Type may be any type (String, Number, Date, Integer, or Real) except Indicator, and several variables of the same type may be listed on the same command line. Declarations of local Strings do not have a length parameter. Local strings grow dynamically on demand, unlike global strings, which are of static length.

Local symbols may be used just as any other variable in DataFlex. They can be used as arguments to any of the DataFlex commands. The only difference is that they are destroyed when the procedure or function is terminated.

Notes

  • Variables may not be declared as local outside functions and procedures, regardless of whether use ui is executed.


Lt Comparison/Mode

Obsolete

The LT find mode is still supported. Refer to the Find command for further details.

For Boolean comparisons you should use the < symbol inside a Boolean expression.

Example

This is obsolete:

If iCount LT 10

This is correct:

If (iCount < 10)

See Also

Purpose

To specify "less than" as the operator for finds and comparisons.

Syntax

With the find command, records can be found in a database file according to the results of comparisons of a value in the record buffer with values in an index to field values in the database file:

move value to file.field

find lt file.field

See Find Command for a description of that command.

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the lt operator:

indicate indicator as variable lt variable

See Indicate Command for a description of that command.

if variable lt variable command

See If Command for a description of that command.

repeat

command

:

command

until variable lt variable

See Repeat Command for a description of that command.

while variable lt variable

command

:

command

end

See While Command for a description of that command.

The values of variables are compared in the order in which they are given in the command "sentence." That is, the first-named variable is tested for being less than the second-named.

What It Does

When used with the find command, lt searches for a value in the index to the database file equal to the value in the fields in the record buffer of which the index is composed. Then the value in the index next less than the buffer value is used to complete the find. If the index contains no value less than the standard, then the find is considered unsuccessful, and Predefined Indicator found is set false.

move "BONAPARZ" to emperors.last_name

find lt emperors.last_name

In this example, the value of BONAPARZ is moved to record buffer Field last_name for Database File emperors after emperors has been opened and its record buffer cleared. The subsequent find command finds the first record in emperors whose last_name field is less than BONAPARZ, using the main index for that field. Field last_name must be indexed.

When used as a find mode by an index containing one or more segments designated "upper case," lt will find a record containing lesser letter value regardless of capitalization in either the record field or the search key. If one or more segments is designated "descending," find lt will actually find gt relative to the record values to produce the desired descending sequence.

When used in comparisons, lt converts the type of the "standard" variable to the same type as the first-named variable and executes the controlled command according to whether the first-named variable is less than the standard.

indicate reject as income lt 4000

[reject] gosub next_one

In this example, Indicator reject is set true when the value of Variable income is less than 4000. The second line executes Labelled Subroutine next_one when reject is true.

while windowindex lt 5

display 0 to form.1&

increment windowindex

loop

In this example, the value of 0 is displayed to windows in Image form in ascending order until the fifth window is reached. The loop is executed so long as the value of Predefined Variable windowindex is less than 5. Note the increment command, which increments the value of windowindex so that it does eventually reach 5.

Notes

  • Find lt commands in a loop will "step through" a database file record by record in descending order by the index in use from the index value of whatever record is in the buffer at the time the loop is started. This is useful for record by record reports, and will start at the end of the index if the loop is started when the record buffer is clear.

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match.

  • For the find command, DataFlex uses five find Mode operators: eq, ge, gt, le, lt.

  • Lt applies to strings and dates as well as to numeric values. For strings, "less" means "alphabetically before," and for dates, it means "earlier than", except for index segments designated descending, where the opposite occurs.

  • Lt may not be used in expressions (comparisons enclosed in parentheses). In expressions, < is to be used.


Match Comparison Mode

Obsolete

This comparison mode is not supported in Visual DataFlex versions 7.0 and beyond. Use the contains operator or pos function.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

Purpose

To specify "matching" as the operator for comparisons.

Syntax

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the match operator:

indicate indicator as variable match variable

See Indicate Command for a description of that command.

if variable match variable command

See If Command for a description of that command.

repeat

command

:

command

until variable match variable

See Repeat Command for a description of that command.

while variable match variable

command

:

command

end

See While Command for a description of that command.

Match allows the use of the question mark (?) and asterisk (*) "wildcard" characters so that varying strings having specified characters in common may match. As in many operating system directories, the question mark may be placed in the "standard" string in any position where any single character is acceptable, and the asterisk may be placed where any series of characters of any length is acceptable.

Thus, the following comparisons are true:

if "Mac?ntosh" match "MacIntosh" . . .

if "Mac?nt*" match "MacIntosh" . . .

if "????ntosh" match "MacIntosh" . . .

if "*Intosh" match "MacIntosh" . . .

The "standards" (Mac?ntosh, Mac?nt*, and *Intosh) would accept successively larger subsets of data from a database. *Intosh, in fact, would accept everything in a database (would never be false), because the initial asterisk would accept all entries and the "Intosh" after it would have no effect. Asterisks, then, are useful only as a way of accepting trailing substrings, as used in the second example above.

Wildcards may be used only in the first variable. When used in the second variable, asterisks and question marks are treated as literal characters. Thus, the following test is true:

if "ABC*" match "ABCD" . . .

while the following test is false:

if "ABCD" match "ABC*" . . .

When seeking a match for strings containing literal question marks and asterisks, you should place the "standard" string in the second variable, where they are treated as literal characters. By the same token, where a loop is "cycling" database values which might contain asterisks and question marks into a match test, those values must be "cycled" into the match in the second position in order to make a coincidental wildcard match impossible.

Notes

  • Match with wildcards can be used to determine whether literal numbers and the values of number and date variables are within the contents of numeric and date variables. Thus, the following sequences result in true comparisons:

move (3 /2) to a_number

if "1.5" match a_number . . .

if "?.*" match a_number . . .

move 12/24/44 to a_date

if "12/24/*" match a_date . . .

move "12/24/*" to a_string

if a_string match a_date . . .

  • Match is case sensitive. Thus, the following comparison would be false:

if "abc" match "ABC" . . .

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match. In and match operate according to the character contents of variables, while the other operators deal in numeric quantities and sequences.

  • The eq comparison/find mode can be used to detect exact matches of strings, but it does not accommodate the * and ? "wildcard" characters.

  • The "wildcard" characters in match are useful for detecting the presence of substrings in a known position in the string being checked. The in comparison mode is more effective where the position of a search substring is unknown, variable, or irrelevant.

  • In the matches Operator, the wildcard characters are effective in the second-given argument, rather than in the first, as they are in the match comparison mode. Operators are used in expressions, and may not be used outside them.


Memory

Obsolete

This command is valid only in character-mode DataFlex. It has no real meaning in the Windows environment.

Purpose

To aid program development by outputting the amount of unused memory in the computer as the program runs.

Syntax

Memory {variable}

What It Does

Memory places the number of bytes of memory in the computer which is not being used at the time the command is executed in variable.

When a program runs out of memory at run time, it reports DataFlex Error 10 (Out of memory) and aborts the program. Memory commands at key points "upstream" of the point at which this happens can help you pinpoint what commands or errors are producing the excessive consumption of memory.

Because the Out of memory error is provided, displays of available memory are usually of little use or interest to operators of programs. Memory commands are typically removed from programs before they are released for general use.

Notes

  • Memory is consumed by images, commands, in memory variables, constants, database files opened and objects.

  • The maximum value returned by the memory command is 64 Megabytes (67,108,864 bytes). This is due to the extremely high amount of memory that a UNIX or an OS/2 system may report as being available. If less than 64 Megabytes of memory is available on the system, the actual value is reported by this command.


Mid Command

Obsolete

This command is replaced by the Mid function.

See Also

Purpose

To move a specified number of characters, starting at a specified position, from a variable to a variable.

Syntax

mid value to variable [length[start_position]]

Start_position may be specified only if length is specified.

What It Does

Mid copies length characters from value starting at start_position and puts them in variable.

mid "NEW HAMPSHIRE" to part 3 5

The above command puts HAM (the three characters starting at Position 5) in part. The value 3 is moved to Predefined Variable strlen, and 5 to Predefined Variable strmark.

Either of the numeric arguments may be variables.

string phone_number area_code

number start

pos "(" in phone_number to start

mid phone_number to area_code 3 (start +1)

In this example, the position of the first open-parenthesis is determined in the value of String phone_number and moved to Number Variable start. Then the 3 characters following the open-parenthesis (start +1) are moved to area_code.

If start_position is omitted, the value of Predefined Variable strmark is used for the function. If both start_position and length are omitted, the value of Predefined Variable strlen will be used for length and of strmark, for start_position. Strmark is set by the previous insert, left, pad, pos, replace, or sysdate command. Strlen is set by the previous pos, right, or sysdate command.

Notes

  • If length is less than 1, mid will empty variable.

  • If length is greater than the length of value, mid will return the rightmost portion of value, starting at start_position.

  • If start_position is less than 1, mid will empty variable.

  • If start_position is greater than the length of value, mid will empty variable.

  • Although mid can be used on Date, Integer, and Number type variables, it is typically used on String type variables.

  • Value and variable may be the same variable. Used this way, mid simply truncates value to the left of start_position and to the right of start_position plus length:

mid account_number to account_number 3 8

In this example, all characters before the third (counted from the left) and after the eleventh are removed from the value of Variable account_number.


Movedate Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To check data to make sure it is a valid date, and move it to a variable.

Syntax

movedate value to variable

What It Does

Movedate checks the value of value to make sure it is a valid date, evaluates it as a date, and moves it to variable. If the data in value is not a valid date, DataFlex Error 16 (Please enter a valid date) is triggered, but the data is still evaluated (probably incorrectly) and moved.

When a move command addresses an explicit variable of Type Date, the compiler automatically replaces the move command with a movedate command. Where you know that data is being moved to a variable of Type Date, use of movedate instead of move can save a very small amount of time per command at compile time.

Notes

  • Movedate checks eligibility of data for the Date type, so if you movedate a value such as 12/42/44 or 24 December, DataFlex Error 16 (Please enter a valid date) will be triggered, regardless of the actual type of variable.

  • Movedate disables DataFlex's automatic type checking of variables, so if you movedate a valid date to an Integer, Number, Real, or String type variable, no error will be declared at compile time, nor will one be declared at runtime. This effect is harmless, so long as you intend it. A String type variable will contain the date in string format, and Integer, Numeric, and Real type variables will contain the date expressed as the number of days since Year Zero (Julian format).


Moveint Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To check data to make sure it is a valid Integer, and move it to a variable.

Syntax

moveint value to variable

What It Does

Moveint checks the value of value to make sure it is a valid Integer, evaluates it as an integer, and moves it to variable.

If the data in value is not a valid Integer, DataFlex Error 51, 52 or 54 is triggered (depending on the type of error—see below), and the data is not evaluated. Moveint does evaluate expressions.

When a move command addresses an explicit variable of Type Integer, the compiler automatically replaces the move command with a moveint command. Where you know that data is being moved to a destination of Type Integer, use of moveint instead of move can save a very small amount of time per command at compile time.

Notes

  • Moveint checks eligibility of data for the integer type, so if you moveint a value such as 2*(2, DataFlex Error 51 (Bad format in expression (operand)) will be triggered, if you moveint an expression such as 2 2, DataFlex Error 52 (Bad format of expression (operator)) will be triggered, and if you moveint an expression such as +2, DataFlex Error 54 (Invalid symbol in expression) will be triggered, regardless of the actual type of variable.

  • Moveint disables DataFlex's automatic type checking of variables, so if you moveint to a Date, Number, Real, or String type destination, no error will be declared at compile time, nor will one be declared at runtime. This effect is harmless, so long as you intend it.

  • If you wish to strip fractional (decimal) components from the value of any variable of Type Number, you can moveint variable to variable, where variable is the same Number type variable.


Movenum Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To check data to make sure it is a valid Number, and move it to a variable.

Syntax

movenum value to variable

What It Does

Movenum checks the value of value to make sure it is a valid Number, evaluates it as a Number, and moves it to variable.

If the data in value is not a valid Number, DataFlex Error 51, 52 or 54 is triggered (depending on the type of error—see below), and the data is not evaluated. Movenum does evaluate expressions.

When a move command addresses an explicit variable of Type Number, the compiler automatically replaces the move command with a movenum command. Where you know that data is being moved to a variable of Type Number, use of movenum instead of move can save a very small amount of time per command at compile time.

Notes

  • Movenum checks eligibility of data for the Number type, so if you movenum a value such as 2*(2, DataFlex Error 51 (Bad format in expression (operand)) will be triggered, if you movenum an expression such as 2 2, DataFlex Error 52 (Bad format of expression (operator)) will be triggered, and if you movenum an expression such as +2, DataFlex Error 54 (Invalid symbol in expression) will be triggered, regardless of the actual type of variable.

  • Movenum disables DataFlex's automatic type checking of variables, so if you movenum to a Date, Integer, Real, or String type variable, no error will be declared at compile time, nor will one be declared at runtime. This effect is harmless, so long as you intend it.

  • If you movenum a valid date to a Number, Integer, or Real-type destination, it will be expressed as the number of days since Year Zero (Julian format).

  • Internally, the calc command is actually a movenum command.


Movereal Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To check data to make sure it is a valid floating point number and move it to a variable.

Syntax

movereal value to variable

What It Does

Movereal checks the value of value to make sure it is a valid floating point number, evaluates it as a floating point number, and moves it to variable.

If the data in value is not a valid floating point number, DataFlex Error 51, 52 or 54 is triggered (depending on the type of error—see below), and the data is not evaluated. Movereal does evaluate expressions.

When a move command addresses an explicit variable of Type Real, the compiler automatically replaces the move command with a movereal command. Where you know that data is being moved to a variable of Type Real, use of movereal instead of move can save a very small amount of time per command at compile time.

Notes

  • Movereal checks eligibility of data for the Real type, so if you movereal a value such as 2 *(2e3, DataFlex Error 51 (Bad format in expression (operand)) will be triggered, if you movereal an expression such as 2e 3, DataFlex Error 52 (Bad format of expression (operator)) will be triggered, and if you movereal an expression such as +2e3, DataFlex Error 54 (Invalid symbol in expression) will be triggered, regardless of the actual type of variable.

  • Movereal disables DataFlex's automatic type checking of variables, so if you movereal to a Date, Integer, Number, or String type variable, no error will be declared at compile time, nor will one be declared at runtime. This effect is harmless, so long as you intend it.


Movestr Command

Obsolete

This command is replaced by the Move command.

See Also

Purpose

To move data to a variable without evaluation or any checking as to its eligibility for a particular data type.

Syntax

movestr value to variable

What It Does

Movestr moves the value of value to variable. Since any string of characters qualifies as a string, it does no type checking or evaluation. Movestr does not evaluate expressions, although it can move strings that are expressions.

When a move command addresses an explicit variable of Type String, the compiler automatically replaces the move command with a movestr command. Where you know that data is being moved to a variable of Type String, use of movestr instead of move can save a very small amount of time per command at compile time.

Notes

  • Movestr never generates a type checking error such as DataFlex Error 51 (Bad format in expression (operand)), regardless of the actual type of variable.

  • Movestr disables DataFlex's automatic type checking of variables, so if you movestr to a Date, Integer, Real, or Number type variable, no error will be declared at compile time, nor will one be declared at runtime. This effect is harmless, so long as you intend it.


MSSQL_SetConstraint

Obsolete

The MSSQL_SetConstraint command was introduced in version 1 of the SQL Server Connectivity Kit. Since then new techniques allow the programmer a better and more controllable interface. The command is still available for backward compatibility reasons. For new logic we recommend the use of the DF_FILE_SQL_FILTER and DF_FILE_SQL_FILTER_ACTIVE attributes or the use of Embedded SQL.

This command was added to give the programmer more control over the Select statement generated by the driver. It will effectively turn off the driver logic, that generates the where clause of a select statement, and replace that with what is passed in the command. Since you are overwriting internal logic, this command has the potential to generate unexpected results when misused. That is why the command must be used in one defined way. You must setup the clause, find records in the result set by the index that you want the result ordered by in forward or backward direction (GT, LT), and remove the clause.

For example, if we want to use this functionality in the Order Entry sample of VDF to find all order lines for the MODEMS item, we could do this the following way:

Use MSSQLDRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

MSSQL_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Until [Not Found]

MSSQL_SetConstraint OrderDtl.File_number ""

This feature can speed up reporting in particular. Sometimes looking for related information is more efficient if the where clause is replaced by a "ChildColumn = ParentValue" construction. The select statements generated by the driver will select the desired record and all that follow according to the index used. By giving it a specific where clause having specific knowledge about the database, you are able to limit the size of the result sets and thereby increase performance.

The MSSQL_SetConstraint command will reset the DF_FILE_MAX_ROWS_FETCHED attribute when issued. If the command is issued with a clause, the attribute will be set to zero (0). If it is called with no clause (an empty string), the attribute will be reset to its original value.

Please note that you need to use SQL syntax in the where clause that you specify. If you want to select on dates you must use the YYYY-MM-DD format that SQL uses. Normally, this is easiest accomplished by:

Date MyDate

Integer OrgFmt OrgSep

Sysdate MyDate

Get_attribute DF_DATE_FORMAT To OrgFmt

Get_attribute DF_DATE_SEPARATOR To OrgSep

Set_attribute DF_DATE_FORMAT To DF_DATE_MILITARY

Set_attribute DF_DATE_SEPARATOR To (ASCII("-"))

MSSQL_SetConstraint MyFile.File_number ("MYDATECOLUMN = '" + string(MyDate) + "'")

Set_attribute DF_DATE_FORMAT To OrgFmt

Set_attribute DF_DATE_SEPARATOR To OrgSep

Also note that string constants are placed in single quotes (').

OF SPECIAL NOTE

  • If this command is used on a table you cannot use other finds on that table until ending the MSSQL_SetConstraint since, as long as the constraint is in force, it will overwrite the find logic of the driver. If, before ending MSSQL_SetConstraint, we changed the example above to find on OrderDtl by some other index or in a different direction (not gt) on the same index, the result would be unpredictable.

Use MSSQLDRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

MSSQL_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Find Lt OrderDtl By Index.1 // The result of this command is unpredictable

Until [Not Found]

MSSQL_SetConstraint OrderDtl.File_number ""

  • You cannot change the buffer between finds to re-seed the find logic. Doing that will result in the first record being found again. If we adjust the previous code to the example below, the repeat loop will turn into an endless loop since you are finding the same record repeatedly.

Use MSSQLDRV

String Clause

Move "ITEM_ID = 'MODEMS'" To Clause

MSSQL_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Move SomeValue To OrderDtl.Order_number

Until [Not Found]

MSSQL_SetConstraint OrderDtl.File_number ""

  • You can use find, save and delete commands on other tables where no MSSQL_SetConstraint is in force. You could, for example, expand the code above and show the customer names for the customers that bought modems. To achieve this you would need to find an OrderHeader and a Customer record.

  • You can end looping through an MSSQL_SetContraint block anytime you like. If we wanted to find only two records in the sample above, we could add a counter, increment it for every found record and break the loop when the counter is two.

Use MSSQLDRV

String Clause

Integer Counter

Move 0 To Counter

Move "ITEM_ID = 'MODEMS'" To Clause

MSSQL_SetConstraint OrderDtl.File_number Clause

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " ;

OrderDtl.Order_Number ", " OrderDtl.Detail_number

Increment Counter

If (Counter >= 2) Break

Until [Not Found]

MSSQL_SetConstraint OrderDtl.File_number ""

  • You must use SQL syntax in the string that is passed.

  • If you want to write portable applications that support multiple database drivers, you can use the general form of the MSSQL_SetConstraint command, CLI_SetConstraint. CLI_SetConstraint performs the same functionality. In fact, it is called from the MSSQL_SetConstraint command. The CLI_SetConstraint command works exactly as described for MSSQL_SetConstraint. It gets an extra parameter, the identification of the driver that you want to set the constraint for. If we changed the code above to be more generic, it would look like the sample below.

Use MSSQL_DRV

String Clause

String DriverId

Move MSSQLDRV_ID To DriverId

Move "ITEM_ID = 'MODEMS'" To Clause

CLI_SetConstraint OrderDtl.File_number Clause DriverId

Repeat

Find Gt OrderDtl By Index.1

[Found] Showln "Order detail for a modem is: " OrderDtl.Order_Number ", " OrderDtl.Detail_number

Until [Not Found]

CLI_SetConstraint OrderDtl.File_number "" DriverId

DISCLAIMER

Data Access has done a lot of research into performance issues and design differences between the native DataFlex database and a SQL Server database. We found that the MSSQL_SetConstraint or CLI_SetConstraint command can speed up a connection to an SQL Server database considerably. While we are looking into ways to improve internal driver logic to get the kind of result these commands can give, this is not a trivial task and outcome of further research is uncertain. In the meantime, Data Access wants to offer this solution to the DataFlex community.

You should be aware that the misuse of these commands could give unexpected results. It is the developers responsibility to verify that the results are as expected. All risks associated with the use of these commands are the developer's; Data Access Corporation disclaims any and all liability with respect to the use of the MSSQL_SetConstraint or CLI_SetConstraint Command.


Multiuser Predefined Indicator

Obsolete

This command is valid only in character-mode DataFlex. All Visual DataFlex runtimes are multi-user.

Purpose

To indicate whether the runtime in use is single-user or multi-user.

Syntax

[multiuser] command

What It Does

Whenever the runtime is first executed, this indicator is set true if the runtime is multi-user and false if the runtime is single-user. A number of commands use this indicator in their definitions, including lock, reread, and unlock. You should not set the value of this indicator in your programs, but you may wish to use it to disable or modify certain functions according to whether the license in use is single-user or multi-user.

[not multiuser] showln "The Hash Module is not needed for single-user DataFlex."

In this example, the legend, The Hash Module is not needed for single-user DataFlex displays when the program is executed by a single-user runtime.

Notes

  • Predefined Indicator multiuser is not affected by the file mode in which database files are opened.


Name Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To permit reference in programs to windows, fields, and constants by names assigned in the program.

Syntax

name [pagename[.###]] name[... name]

[name name ... name]

name [pagename[.###]] name [...name]

Pagename may be given either on the name command line or in a preceding autopage command. .### identifies a particular window in pagename to rename. If ### is given in a preceding autopage command instead of in the name command, it must there be preceded by a space instead of a period.

Name must not have been previously used (declared) as a name for any other variable.

What It Does

Name allows you to address pagename.### as name throughout the portion of your program which comes after the name command line.

name screen.5 turkeys_on_hand_

In this example, the fifth window in Image screen is named turkeys_on_hand_. Below this line, the window may be addressed as either screen.5 or as turkeys_on_hand_.

Use of name does not affect addressing pagename.### as pagename.###, nor does it affect windowindex addressing of the window(s).

Where only pagename is given in the command, nameing starts with the first window in pagename:

name screen chickens_ ducks_ capons_ pheasants_ turkeys_on_hand_

In this example, the first five windows of Image screen are named chickens_, ducks_, capons_, pheasants_, and turkeys_on_hand_ respectively. The trailing underscores are not required; they are used only so that it can be seen in lower parts of the program that the names are those of renamed windows.

If an autopage command is in effect, it may be used to imply the windows to be addressed by succeeding name commands which omit all pagename.### references:

autopage screen

name chickens_ ducks_ capons_

name pheasants_ turkeys_on_hand_

This example is the exact equivalent of the name command given in the preceding example, nameing the first five windows of Image screen.

Where all the names desired for windows in pagename will not fit on one command line, additional name command lines may be used to name the rest of the windows. In these cases, the introductory autopage pagename command line is required, and the .### specifier may not be used.

Autopage can be started at specific windows other than the first:

autopage screen 3

name capons_ pheasants_ turkeys_on_hand_

In this example, the third window in Image screen is named capons_, the fourth, pheasants_, and the fifth, turkeys_on_hand_.

Notes

  • If needed, the original pagename.### form of reference to renamed windows may be used, even after a new name has taken effect.

  • Names assigned to windows can substitute for all references to the windows, including the arguments to accept, blankform, clearform, display, and entry commands, and for references on which windowindex loops are based.

name maint_log.6 maint_date_

for windowindex from 0 to 3

move today to maint_date_&

loop

In this example, the value of Variable today is moved to Windows 6 through 9 of Image maint_log, the sixth window having been renamed maint_date_.

  • The name substitutions are done at compile time. Use of name does not involve any processing, or performance cost, whatsoever at run time.

  • Name affects only the part of your program which is below the name command line. If you desire to use consistent names throughout your program, it is recommended that you place your name command lines at the beginning of your program.

  • With name, you can give names to windows which are indistinguishable from the names of in memory variables. Where you wish to keep renamed windows distinguishable as windows, it is recommended that you use some naming convention to maintain the distinction, such as a trailing underscore.

name address.5 city_

In this example, the fifth window of Image address is renamed city_, with a trailing underscore to make it evident throughout your program that city_ is a renamed window.

  • Name can, in fact, rename any type of DataFlex variable or constant, instead of just windows. For example, if you wished to rename a frequently-referred-to field named application_date in Database File personnel, this command would enable you to refer to it as apda throughout your program below the command:

name personnel.application_date apda

References to personnel.application_date would continue to work, as well as apda, below the name command line.

  • Where the window number (###) is specified in the name command, only one pagename.### may be renamed.


Name_item Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To permit naming of object items beyond the 250-character capacity of a command line.

Syntax

name_item symbolicName [[item] #] itemName [... itemName]

SymbolicName is the name for the object whose items are to be named, as defined in a preceding name_object command.

Item is optional. # is the optional item number to begin naming with. If # is omitted, naming begins with the first item not yet named in a preceding name_object or name_item command. ItemNames must be unique in the list for the object.

What It Does

Name_item is intended for use immediately after a name_object command in which the 250-character command line capacity is insufficient for naming all items.

name_object myObject child anObject x y z

name_item myObject a b c

In this example, the name_object command assigns x, y, and z respectively as the names of the first three items of Object anObject. The succeeding name_item command names the fourth through sixth items of anObject (through its symbolic name, myObject) a, b, and c, respectively.

Where more properties and/or child objects are to be named in an object than can be named in the 250-character capacity of a single name_object command, additional name_object commands may be used for the additional properties and/or child objects. If name_object item is repeated for a given object, however, item renaming restarts with the first item, in contrast to name_item, which by default starts with the first item not yet named.


Name_items Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To associate names with items.

Syntax

name_items [item {next |item_number}] name [... name]

What It Does

Without the optional modifiers, this command assigns the first name to Item 0, the second to Item 1, and so on.

You can continue naming on a new command line from the preceding name_items command with the item next modifier, as many times as you like).

name_items alpha## bravo## charlie##

name_items ITEM NEXT delta## echo## foxtrot##

You can name an item starting at a specific item with the item item_number modifier. Remember that the item number is zero-based (the first item is Item 0).

name_items item 5 foxtrot## golf##

The following two lines are identical:

name_items Quantity## Amount## Price##

name_items item 0 Quantity## Amount## Price##

Of course, with this method you have to make sure that your item names are ordered correctly, just as with the old name command. If you change your items around, you'll have to change your name_items command. Entry_name_item is better at handling these kinds of changes.

The above program could be changed to:

name_items TrID## PartID## Desc## Amount## Quantity## Total##

or

name_items item 3 Amount## Quantity## Total##

:

Object My_Form is an entry_form My_Form ;

Using whatever Updating whichever

Procedure Calc_Total Integer Item#

Number A1 A2

Get value item Quantity## to A1

Get value item Amount## to A2

Set value item Total## to (A1 *A2)

end_procedure

item_list

entry_item Tran.Id {Autofind}

entry_item Part.Id {AutoFind,FindReq,iExit =MSG_Calc_Total}

entry_item Part.Description {DisplayOnly}

entry_item Part.Amount {DisplayOnly}

entry_item Tran.Quantity {iExit =MSG_Calc_Total}

entry_item Tran.Total {DisplayOnly}

end_item_list

end_object

Don't use name_items where you could use entry_name_item or on_name_item. It is too easy to get the item names in the wrong order. If you really want to use this command, you can employ a double-check capability. You can use name_items and entry_name_item or on_name_item to name the same item. As long as the item numbers and names agree, all will be well. If they do not agree, you will get a compiler error (which is exactly what you want).

This would work:

name_items TrID## PartID## Desc## Amount## Quantity## Total##

item_list

entry_item Tran.Id

entry_item Part.Id

entry_item Part.Description

entry_name_item Amount## Part.Amount

entry_name_item Quantity## Tran.Qty

entry_name_item Total## Tran.Total

end_item_list

This would generate a compiler error:

name_items TrID## PartID## Desc## Amount## Quantity## Total##

item_list

entry_item Tran.Id

entry_item Part.Id

entry_name_item Amount## Part.Amount

entry_name_item Quantity## Tran.Qty

entry_name_item Total## Tran.Total

entry_item Part.Description

end_item_list


Name_object Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To allow objects and their items and properties to be referred to in get, set, and send commands and in expressions by simple names rather than by access method. Use of this command can impair the integrity of your application's object structure. Its use is not recommended.

Syntax

name_object symbolicName ;

[global |child parentObjectName |access_method] ;

[column columnName ... columnName] ;

[[[item] #] itemName ... itemName] ;

[property propertyName ... propertyName] ;

[[[item] #] itemName ... itemName] ;

[property propertyName ... propertyName]

Argument Explanation

symbolicName Symbolic name for objectName. The name created will have the form symbolicName.obj. The symbolicNames of objects must be unique throughout the program, while the names of items need be unique only within any one object. When symbolicName is different from the actual object name, the symbolic name must be initialized at the top of the object's creation block as move current_object to symbolic_name.obj.

global| child parentObjectName| access_method If none of these terms is used, only items, columns, and/or properties will be named. No object will be named.

global Define symbolicName as a global object. Name_object global is normally used prior to all procedures, objects, and classes which use or define the object (at the front of the program). If there are no earlier references to the object you may name a global object at the beginning of its definition.

child parentObjectName Define symbolicName as a child object of parentObjectName. Registers the object (if not already registered).

access_method An expression for the access method of the object. Creates a symbolicName.obj symbol. This term may be current_object. Current_object is sometimes used inside a class definition to make all access to the object relative.

item itemName ... itemName Creates names for items in the form symbolicName.itemName. Items are named starting at Item 0 unless an item number (#) is specified. Specified item numbers must be integer constants. There may be as many item clauses in a single name_object command as desired, intermingled, if desired, with property clauses. May be used to name items absolutely across, and then down, the rows of a grid-based object. ItemName must begin with a letter. If it is a number, it will be taken as a new starting item number (#).

column itemName ... itemName Column is used the same way as item, except that the itemNames refer to the first, second, and so on items in the current row in a grid-based object, rather than to absolute items. This amounts to a "column" name. If the keyword column is omitted for a grid-based object, item will be inferred, and all references will be to absolute items starting with the first item on the first row. Starting item number (#) may not be used with column. There may be only one column clause in a single name_object command.

property propertyName ... propertyName Creates names for properties in the form symbolicName.propertyName. This may also be used to name child objects, since they amount to properties of the object. There may be as many property clauses in a single name_object command as desired, intermingled, if desired, with item clauses. PropertyName must match the name of the property as given in its property command, or the name of the child object as given in its object command.

What It Does

Name_object may be used to forward-reference objects and item names. The name_object command must precede the first reference in the program to the named object or any of the named items, properties, or child objects. Otherwise, the typical location for a name_object command is at the top of an object's object-creation block.

The .obj extension is required when symbolicName is used in expressions. It may be omitted in get, set, and send commands. Object and item symbolicNames can only be used inside appropriate get, set, and send commands or inside expression functions. Use of item symbolicNames in other places will usually generate an error which lists "ITEM" as an illegal parameter.

Examples

name_object myObject (anObject(desktop))

In this example, myObject.obj becomes the name for global Object anObject. The command move current_object to myObject.obj must be present at the top of the creation block of anObject.

name_object myObject item x y z

In this example, myObject.x becomes the name for Item 0 of Object myObject, myObject.y becomes the name for Item 1, and myObject.z for Item 2.

name_object myObject column a b c

In this example, myObject.a becomes the name for (base_item(myObject.obj)), myObject.b becomes the name for (base_item(myObject.obj) +1), and myObject.c for (base_item(myObject.obj) +2).

name_object myObject property myButton

In this example, myObject.myButton becomes the name for (myButton(myObject.obj)).

name_object myObject (anObject(current_object)) x y z

In this example, myObject.obj becomes the name for the current child object of Object anObject, myObject.x becomes the name for Item 0 of that object, myObject.y becomes the name for Item 1, and myObject.z becomes the name for Item 2.

name_object myObject child anObject x y z

In this example, myObject is registered, myObject.obj becomes the name for (myObject(anObject.obj)), myObject.x becomes the name for Item 0 of Object myObject, myObject.y becomes the name for Item 1, and myObject.z becomes the name for Item 2.

name_object myObject item 2 i3 i4 i5 item 9 fred property myButton

In this example, myObject.i3 becomes the name for the third item (#2) of global Object myObject, myObject.i4 becomes the name for the fourth item, myObject.i5, the name for the fifth object, fred becomes the name for the tenth item (#9), and myObject.myButton becomes the name for (myButton(myObject.obj)).

name_object myObject global item 2 i3 i4 i5 item 9 fred property myButton

In this example, a global integer value for Object myObject is created, myObject.i3 becomes the name for the third item (#2) of global Object myObject, myObject.i4 becomes the name for the fourth item, myObject.i5, the name for the fifth object, fred becomes the name for the tenth item (#9), and myObject.myButton becomes the name for (mybutton(myObject.obj)).

Examples of using named objects and items:

get value of myObject.x to i

In this example, the value of the item of Object myObject named x is moved to Variable i.

set value of myObject.y to i

In this example, the value of the item of Object myObject named y is set to the value of Variable i.

set focus_mode of myObject.obj to focusable

In this example, the focus_mode of Object myObject is set to focusable.

showln (value(myObject.x))

In this example, the value of the item of Object myObject named x is displayed to the screen.

showln (parent(myObject.obj))

In this example, the object_id of the parent object of Object myObject is displayed to the screen.

Where more properties and/or child objects are to be named in an object than can be named in the 250-character capacity of a single name_object command, additional name_object commands may be used for the additional properties and/or child objects. If the command line capacity is insufficient for the naming of all items that it you wish to name, use the name_item command.


Ne Comparison Mode

Obsolete

For Boolean comparisons you should use the < symbol inside a Boolean expression.

Example

This is obsolete:

If iCount NE 10

This is correct:

If (iCount <> 10)

See Also

Purpose

To specify "not equal to" as the operator for comparisons.

Syntax

Commands and loops can be controlled according to the results of comparisons of the values of two variables using the ne operator:

indicate indicator as variable ne variable

See Indicate Command for a description of that command.

if variable ne variable command

See If Command for a description of that command.

repeat

command

:

command

until variable ne variable

See Repeat Command for a description of that command.

while variable ne variable

command

:

command

end

See While Command for a description of that command.

Notes

  • Ne is case sensitive. Thus, the following comparison would be true:

if "aBC" ne "ABC" . . .

  • For the if, indicate, until, and while commands, DataFlex uses eight Comparison Mode operators: eq, ge, gt, in, le, lt, ne, and match. In and match operate according to the character contents of variables, while the other operators deal in numeric quantities and sequences.


No_calc Window Format Option

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

Purpose

To defeat the default action of the Calculate accelerator key.

Syntax

entry_item file.field [no_calc [..., option]]

What It Does

When users press the Calculate accelerator key, the cursor drops to the bottom of the screen and the expression evaluator is activated. Users may at this point enter expressions including operators (*, , +, /, ^) and parentheses. Then upon pressing Calculate or Accept again, the result is entered to the window and the cursor advances from the window. When an entry_item command includes no_calc, the Calculate accelerator key functions no differently from the Accept accelerator key. No expression evaluation is done for the window.

entry_item unit.serial {no_calc}

In this example, when the cursor is in the item attached to the serial field of the unit file, the Calculate accelerator key is disabled.


Noenter Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To prevent data entry to a field and entry items attached to it.

Syntax

set field_options field file.field to dd_noenter

or

entry_item file.field [{noenter [, ... , option]}]

What It Does

When an entry_item with noenter on it is executed, the item is filled with data from file.field, but the cursor does not enter the item, preventing data entry through the item.

entry_item vendor.balance {noenter}

In this example, the contents of Field balance in Database File vendor are displayed, but the cursor does not stop in the item window.

When dd_noenter is applied to a field in a DataDictionary object with the field_options property, this behavior is manifested by every item addressing the field in a DEO that is using the DataDictionary.

Notes

  • The skipfound field property has a similar effect, except that it allows the cursor to go to the item only if no record is found. Noenter skips the item regardless of whether a record is found.

  • The displayonly field property is a combination of noenter and noput.

  • Although data cannot be entered from the keyboard to an item controlled by noenter, data can still be moved to the item. Such data changes will be moved to the record buffer, unlike the displayonly or noput field properties.


Noput Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To prevent data entered through an entry_item from being moved into the record buffer.

Syntax

set field_options field file.field to dd_noput

or

entry_item file.field [{Noput [, ... , option]}]

What It Does

When an entry_item with a noput is executed, data from the item is not put back to the record buffer for file.field, even if new data is entered from the keyboard. Noput is useful for allowing data to be entered into an item for finding, where you do not wish to allow the field to be changed.

entry employee.num {noput}

In this example, data from Field num in Database File employee is displayed to the item on finds, and keyboard entry to the window is allowed, but data from the window is never put back to employee.num in the record buffer.

When dd_noput is applied to a field in a DataDictionary object using the field_options property, this behavior will be manifested in every DEO that is using the DataDictionary. It can be suspended in any DEO by use of the item_option ... noput message.

set item option item some_item noput false

In this example, the noput property the item identified in the value of some_item is suspended for the DEO containing the item addressed.

Notes

  • Use the noput field property when you want to prevent users from changing data.

  • The displayonly field property is a combination of the noput and noenter field properties.


Not Command Component

Obsolete

This command component is replaced by the Not function.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To invert the logical value of an expression or an indicator or group of indicators, controlling, or being set by, a command.

Syntax

not expression

or Legacy Syntax

not indicator

What It Does

The word not in front of the name of an indicator being set by a command causes the value of indicator to be set to the inverse of the result of the test. If the test is true, indicator is set false. If the test is false, indicator is set true.

indicate not good as group any [evil vicious]

In this example, if either indicator evil or vicious is true, indicator good is set to False.

In front of the name of an indicator which controls a command, the command is executed if the indicator is false, and not executed if the indicator is true.

[not rainy not dark] gosub fishing

In this example, if both indicators rainy and dark are false, subroutine fishing will be executed.

Not may be placed before the name of any indicator within a set of brackets.

Not also inverts the Boolean value of expressions.

if not (females > males) gosub nextparty

In this example, if the value of variable females is not greater than the value of variable males, subroutine nextparty is executed.

Not also inverts the Boolean values of variables. A variable value of 0 or blank is Boolean value false, and any there value, positive or negative, is true.

indicate leapyear as not (mod(year,4))

In this example, indicator leapyear is set true if the modulo 4 of the value of variable year is 0 (false), and false if the integer expression is other than 0 (true).

Notes

  • The value of an indicator may be reversed by use of not with the indicate command.

indicate true as not tru

  • In this example, the value of indicator tru is changed to false if it is true, or true if it is false.


On ... Gosub Command

Obsolete

This command is replaced by the Case command.

See Also

Purpose

To select one of a series of subroutines to execute, based on the numeric value of a variable or expression.

Syntax

on variable gosub label [...label]

One label is required, and additional labels may be provided, separated by spaces. Each label must exist in the program.

What It Does

The numeric value of variable is used as an index to select for execution one of the subroutines whose label is listed. If the value of variable is 1, the first label is executed; if the value of variable is 2, the second is executed, and so forth. When the subroutine has been executed, execution returns to the command line next after the on ... gosub command.

If the value of variable is less than 1 or greater than the number of labels listed, no subroutine will be executed.

on time gosub early on_time late

In this example, when the value of Variable time is 1, DataFlex executes Subroutine early. When the value is 2, it executes on_time, and when it is 3, it does late. When time has any other value, execution passes to the line after on ... gosub.

Notes

  • You must provide a subroutine under label for every label in every on ... gosub command you use. The labelled routine must end with a return command.

  • If the value of variable is less than 1 or greater than the total number of labels on the on ... gosub command line, no subroutine will be executed. If you want this to constitute an error in your program, declare the error as follows:

on music gosub rock country jazz

if music gt 3 error 198 "INVALID MUSIC TYPE SELECTED"

If the value of music is greater than 3, DataFlex declares Error 198.

  • You may precede on ... gosub with indicators and if tests.

  • The on ... goto command is similar to the on ... gosub command with the exception that the on ... goto command does not return to the line after the on ... goto command.

  • If variable is a number that includes a fractional (decimal) value, the value will be truncated to an integer value before the on ... gosub selection is made.


On ... Goto Command

Obsolete

This command is replaced by the Case command.

See Also

Purpose

To select one of a series of labels to pass execution to, based on the numeric value of a variable or expression.

Syntax

on variable goto label [...label]

Argument Explanation

variable May not be a constant or of Type String, and must have positive numeric values.

label Required, and additional labels may be provided, separated by spaces.

What It Does

The numeric value of variable is used as an index to select one of the listed labels to pass execution to. If the value of variable is 1, execution is passed to the first label; if the value of variable is 2, execution passes to the second, and so forth.

If the value of variable is less than 1 or greater than the number of labels listed, execution will go to the line following the on ... goto command.

on time goto early on_time late

In this example, when the value of Variable time is 1, DataFlex passes execution to Label early. When the value is 2, it goes to on_time, and when it is 3 it goes to late. When time has any other value, execution passes to the line after on ... goto.

Notes

  • You must provide a label in your program for every label in every on ... goto command you use.

  • If the value of variable is less than 1 or greater than the total number of labels on the on ... goto command line, no goto will be executed. If you want this to constitute an error in your program, declare the error as follows:

on music goto rock country jazz

if music gt 3 error 198 "INVALID MUSIC TYPE SELECTED"

If the value of music is greater than 3, DataFlex declares Error 198.

  • You may precede on ... goto with indicators and if tests.

  • The on ... goto command is similar to the on ... gosub command with the exception that the on ... goto command does not return to the line after the on ... goto command.

  • If variable is a number which includes a fractional (decimal) value, the value will be truncated to an integer value before the on ... goto selection is made.


On Error Command

Obsolete

This command is obsolete. Please see the documentation listed in the See Also section for error handling in Visual DataFlex.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To execute a subroutine whenever an error occurs at runtime.

Syntax

on error {off | gosub label}

Label is the name of a subroutine in the program.

Off is a reserved word.

What It Does

On error gosub executes the subroutine, which you must provide in your program under label, to be executed whenever a non-fatal DataFlex error occurs at runtime. This allows you to provide corrective actions or user prompts in your program rather than relying only on the standard DataFlex error message to handle the situation. On error and on error off may be used as many times as desired in a program.

Your program may have any number of on error gosub commands, calling different subroutines, or sharing subroutines, but only the most recent on error gosub command is in effect at any given time. If you wish no on error gosub command to be in effect, use on error off.

on error gosub no_customer

In this example, Subroutine no_customer is executed whenever a runtime error occurs after this command has been executed (so long as no subsequent on error command has been executed).

The Error-Handling Subroutine:

The subroutine specified by the on error command is a true subroutine, that is, it must be located under a label (with a colon (:) at the end), and it must be terminated by a return command.

Inside your error handling subroutine you may reference the line number on which the error occurred through the value of the errline Predefined Variable, and the number of the error triggered through Predefined Variable lasterr. These can be used to fine-tune your error handling subroutine to handle specific errors.

Finally, your error handling subroutine should set Predefined Indicator err false. Err is set true anytime an error is triggered. Subroutines called by on error gosub are not executed when err is true. This prevents the endless loop which would occur if an error occurred inside your subroutine, and it called itself. When an error is triggered while your subroutine is being executed, the normal (DataFlex) error routine is executed. The command indicate err false should be placed at the end of the subroutine, just prior to the return.

string discard 1

indicate err false

on error gosub wrong_disk

restart:

open datafile

command

:

command

abort

wrong_disk: //subroutine

if lasterr eq 75 begin //if error 75, do display

showln "DATAFILE.DAT isn't on the drive."

showln "Please insert the DATAFILE disk."

showln "Press <RETURN> when done."

inkey discard //input a string

indicate err false

return restart //go to RESTART:

end

else error lasterr //if not 75, do normal MESSAGE

indicate err false

return //display other errors

This example shows an on error command together with the command (open datafile) whose error it is intended to trap, and the subroutine (wrong_disk), which executes in case the error occurs. Note that the on error command is above the open command whose error it is intended to trap. If the on error command were below the open command, errors triggered by the open command would execute before the on error command executed. If an error occurs, Subroutine wrong_disk is executed. Wrong_disk allows all types of errors to execute normally except for Error 75 (Can't open data file (.DAT)). The if lasterr eq 75 executes a begin ... end block if that error occurs (likely as a result of the wrong disk being in the drive). If Error 75 occurs, a message advising the operator that the wrong disk is in the drive is displayed, and execution returns to Label restart after the operator has changed disks and pressed a key. If the error is other than Error 75, the else error lasterr command executes the standard routine for that error, the next line sets Predefined Indicator err false, and execution returns to wherever it was when the error occurred.

Notes

  • If you wish the routine for the triggered error to be executed as though unaffected by your subroutine (instead of trapped), provide the command error lasterr in your subroutine, as shown above.

  • You cannot use on error gosub to trap window-entry Errors 13, 15, 17 (findreq), or 16 (date format).

  • Always indicate err false before every on error gosub command to guard against err having been left true by a previous error.

  • In programs using procedures and functions in which error reporting is deferred, execution of an on error command when there is an error pending results in the reporting of the error.


On_name_item Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To replace the on_item command.

Syntax

on_name_item item_name [value] ... (standard on_item syntax)

What It Does

On_name_item is a version of the on_item command that permits the assignment of names to object items for easier recognition in source code. Item_name is the name by which you choose to refer to the item, and the remainder of the syntax (starting with value) is the syntax of the original on_item command.

Referring to items in objects by their item numbers staightforwardly can result in code that is very difficult to read, as the following example demonstrates.

Object My_Form is a Form

item_list

on_item '' Send None

on_item '' Send None

on_item '' Send None

end_item_list

Procedure Run_report

String IODevice FileName

Integer Index_Order

Get value item 1 to FileName

Get value Item 0 to IODevice

Get value item 2 to Index_Order

Send Run_Report IODevice FileName Index_Order

end_procedure

end_object

We have to keep track of the item numbers (they are zero-based). This can be difficult. What if we counted wrong? What if we moved the items around?

The following example shows how the same would be done using on_name_item:

Object My_Form is a Form

item_list

on_name_item Form_IODevice## '' Send None

on_name_item Form_FileName## '' Send None

on_name_item Form_Index## '' Send None

end_item_list

Procedure Run_report

String IODevice FileName

Integer Index_Order

Get value item Form_FileName## to FileName

Get value Item Form_IODevice## to IODevice

Get value item Form_Index## to Index_Order

Send Run_Report IODevice FileName Index_Order

end_procedure

end_object

Note that you do not need to use on_name_item everywhere you would have used on_item. In fact, it is best to only name the items that you actually need. Certain limitations of on_name_item are described in the article above on the entry_name_item command, as well as techniques for using the command to address items in Grid objects.


Pad Command

Obsolete

This command is replaced by the Pad function.

See Also

Purpose

To make a string a specified length by either truncating it on the right, or appending spaces on the right.

Syntax

pad value to variable [length]

What It Does

Pad moves data from value to variable so as to yield length characters in variable. If value is shorter than length, pad adds spaces to the right to make up a length of length in variable. If value is longer than length, pad truncates value on the right to produce a length of length in variable.

string country

number column_width

pad "France" to country 10

move 10 to column_width

pad "United States" to country column_width

In the example above, padding France to a length of 10 would produce France plus 4 spaces in Variable country. Padding United States to the same length would produce United Sta in country. In the second command, Number Variable column_width is used to set the paddedlength to 10. In both cases, 10 is moved to Predefined Variable strmark.

If length is left off, the value of Predefined Variable strmark is used for the function. Strmark is set by the last previous insert, left, mid, pos, replace, or sysdate command.

Notes

  • If you want to truncate strings that exceed a certain length, but not pad them when they are under that length, use the left command.

  • If length is less than 1, pad will output an empty string.

  • It is unnecessary to pad to a field since fields are automatically padded or truncated to the field length.

  • It is ineffectual to pad to a window, since spaces are automatically stripped from the contents of windows.

  • The opposite of pad is trim, which removes trailing blanks. Trim, however, does not truncate strings.

  • Dates, Numbers, and Integers are suitable as values, but pad will not add spaces to the values of those types of variables as variables. It will, however, truncate them.

  • Value and variable may both be the same String-type variable.


Pos Command

Obsolete

This command is replaced by the Pos function.

See Also

Purpose

To return the position of the beginning of one string of characters within another string that includes the value of the first string.

Syntax

pos subString in hostString [to variable]

What It Does

Pos scans hostString for subString. If subString is in hostString, pos moves the position (counted from the left) of the first character in subString to Predefined Variable strmark and to variable, if specified, and sets Predefined Indicator found true. If subString is not in source, zero is moved to strmark and variable, and found is set false.

string whole

number place

move "abcdefgh" to whole

pos "def" in whole to place

In this example, pos searches for subString def in the value of String Variable source. It will place a value of 4 in Predefined Variable strmark and Number Variable place, and set Predefined Indicator found true.

Pos sets the value of Predefined Variable strmark, which is used by the mid and right commands when those commands omit a variable specification. This is intended to facilitate implicit positioning illustrated by the following example:

string alpha_suffix

pos "A" in "123ABC"

[found] right "123ABC" to alpha_suffix

In this example, the pos command places 4 (the position of A in 123ABC) in strmark. The succeeding right command will use 4 as the position specification, and move the subString (ABC) beginning at that position to String Variable alpha_suffix. The action would not be affected if the pos command had a variable specifier, but it would be defeated if the right command had one.

Notes

  • Pos is case-sensitive. Thus, the value of place in the following example is 0, and found is set false:

pos "DEF" in "abcdefgh" to place


Points= Window/Print Format Option

Obsolete

This option is obsolete. This format option is valid only in character-mode DataFlex. In Visual DataFlex, you can use the Field_Mask property of the DataDictionary class or the Currency_Mask method.

See Also

Purpose

To restrict keyboard input to a window to numeric characters and operators, and to specify the number of places to the right of the decimal point to be contained in the window.

Syntax

entry_item file.field {points=# [ , ..., options]}

# is a literal number from 0 to 8.

What It Does

When points= is used on an entry_item, format, or print command line, it rejects non numeric keyboard entries to the item and displays numbers with n places to the right of the decimal.

Using {points=#} makes window numeric. If you subsequently try to input letters to window, the computer will beep.

entry_item empl.pay {points =2}

In this example, an entry to the item connected to Field pay in Database File empl is truncated to two digits to the right of the decimal point.

format history.2 thru history.4 {points=2}

In this example, the second through fourth windows in Image history are defined to truncate all entries in them to two decimals to the right of the decimal point.

Points= does not round numbers—it truncates. Entry_item and print commands, however, handle expressions, so an expression to round can be included in such commands.

Notes

  • The value points= 0 will cause window to accept Integer values only. This is the easiest way to create a single-character numeric window.

  • Points= may not be used as a format option on entry_item command lines in any class of object that can be scrolled. The option is supported only in the entry_form class. If the option is required in classes of other types, it may be applied to windows through use of the format command.


Put

Put Command

Obsolete

This command is obsolete. Use Struct and End_Struct.

See Also

Purpose

To store data into a field in a complex data structure (which is declared within a Type...End_Type block).

Syntax

Put {value} To {buffer} at {field}

Argument Explanation

value Any valid data, or variable, which matches the size (in bytes) of the field.

buffer The name of the complex data structure.

field The field within buffer into which value is stored.

What It Does

Put sets the part of the complex data structure buffer named field to value.


Put_String

Put_String Command

Obsolete

This command is obsolete. Use Struct and End_Struct.

See Also

Purpose

To put a string value to a string field in a complex data structure.

Syntax

Put_String {value} To {buffer} At {field}

Argument Explanation

value Any valid data or variable.

buffer The name of the complex data structure.

field The field within buffer into which value is stored.

What It Does

Put_string fills the named field in the complex data structure buffer with value. If value is shorter than field, field is padded out to its full length with ASCII zeroes.

Notes

  • This command is exclusively for String fields and values. For all other data types, use the put command.


Read_dfini Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To configure the keyboard and other user-interface attributes according to the contents of a file identified in the program.

Syntax

read_dfini path\ fileName

Argument Explanation

path\filename May be of any class, but must be of Type String.

What It Does

Read_dfini identifies a file and directory path to be used by the program as its DFINI.CFG file. DFINI.CFG is the name of the file created by the DataFlex Configuration to contain a number of specifications of the user interface, including accelerator (function) keys, screen display colors, scroll bar position, mouse parameters, icon strings, and a number of other factors described in the tool and its documentation.

read_dfini "\dataflex\chess\chessini.cfg"

In this example, File CHESSINI.CFG in Directory \DATAFLEX\CHESS is identified as the file from which user interface defaults for the program are to be taken.

The DataFlex Configuration loads files named DFINI.CFG by default, but permits saving files of different names if you so elect. Differing versions of files of this name can be kept in different directories and found through the value of the HOME environment variable, and configuration files with different names can be found through the value of the DFINI environment variable. Read_dfini commands always override the effects of environment variables.

If no path is given, the directory(ies) named in the DFPATH environment variable will be searched for fileName.

If fileName is not found, the command has no effect, and no error is declared.

Notes

  • Read_dfini should not be used to change the user interface as a program runs, since most user interface attributes can be changed by use of individual commands in the program. Read_dfini should be used only once in a program, at its beginning.

  • When execution chains from a program that has a read_dfini command in it to another that does not, the DFINI.CFG version used by the first program will continue to be used by subsequent programs. By placing read_dfini in a menu program, you can cause a particular DFINI.CFG version to be used by an entire application.

  • Differing versions of initialization files can be accessed from within programs through use of the HOME environment variable. The value of this variable also affects where the TERMLIST.CFG file is found.

  • Read_dfini is useful where DataFlex programs that use the DataFlex UIMS are in use concurrently with other DataFlex programs that use the Flex Keys of non UIMS (procedural) earlier revisions. Each of these two types is best used with its own definition of function keys, which in turn requires at least two different initialization files. With the appropriate initialization file, the current DataFlex runtime will support both modes.


Reg_Close_Key

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

To close a registry key named hKey.

Syntax

REG_CLOSE_KEY hKey TO bValue

What It Does

This command closes an open registry key. Use REG_CREATE_KEY or REG_OPEN_KEY to open the registry key.

Example

Handle hKey

Reg_Open_Key ;

"HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\Print\Printers\HP LaserJet 4M/Plus";

To hKey

Reg_Close_Key hKey


Reg_Create_Key

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

To create a registry key named sNewKeyName, where sNewKeyName is a pathname of a registry key.

Syntax

Reg_Create_Key sNewKeyName TO hKey

What It Does

Reg_Create_Key creates a registry key beneath the current registry root node. Registry keys are the principal means of storing application and system configuration information in Windows. You may access the contents of a registry key by using Get_Profile_String or Get_Profile_Dword. Unlike Set_Profile_String and Set_Profile_Dword (which also create keys), this command does not allow you to create a value within a key.

sNewKeyName must be a fully qualified key name, not including the root node name.

For example, the fully qualified path name to the VDF7 root is:

Software\Data Access Corporation\Visual DataFlex\7

hKey will return as Zero if the key cannot be constructed. Invoke the Win32 API function GetLastError to get the error code.

Example

Procedure OnClick

End_Procedure

Object oCurrentConfigRegistry Is A Array

Function CreateCurrentConfigKey String sKey Returns Integer

Handle hKey

Handle hRegRoot

String sDefaultPath

// Create a key within the HKEY_CURRENT_CONFIG tree.

// Save off current root settings for later restore.

Get_Registry_Root To hRegRoot sDefaultPath

Set_Registry_Root To HKey_Current_Config ""

Reg_Create_Key sKey To hKey

Set_Registry_Root to hRegRoot sDefaultPath

Function_Return hKey

End_Function

Procedure Test

Handle hRegKey

Move (CreateCurrentConfigKey;

(current_object, "System\CurrentControlSet\Control\Print\Printers\My Printer"));

To hRegKey

if (hRegKey <> 0) Begin

Showln "The created key is " hRegKey

Reg_Close_Key hRegKey

End

Else Showln "Reg_Create_Key failed!"

End_Procedure

End_Object

Notes

  • Reg_Create_Key requires KEY_CREATE_SUB_KEY rights.

  • Do not forget to close the key using the Reg_Close_Key command.

  • The key is created in the current root. To change the registry root node, use SET_REGISTRY_ROOT. The default value is HKEY_LOCAL_MACHINE.


Reg_Enum_Key

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

Allows for enumeration of registry subkeys.

Syntax

Reg_Enum_Key hKey bRecursionFlag

What It Does

Reg_Enum_Key provides an easy, object-oriented mechanism for enumerating registry subkeys. To enumerate subkeys of a registry key use Reg_Open_Key to obtain the hKey handle, assign an object to the enumeration (using Reg_Enum_Key_Info), and then invoke Reg_Enum_Key.

The function Reg_Key_Enum will be sent to the object for every subkey of the given key, hKey. The recursion flag, bRecursionFlag, allows for recursion of all levels. Returning the value 0 from the function Reg_Key_Enum will stop the enumeration. A non-zero value will continue enumeration.

hKey must be a handle of a valid registry key. Use Reg_Open_Key to obtain the handle of the registry key.

bRecursionFlag may be either 0 (FALSE) or 1 (TRUE).

Example

Procedure OnClick

End_Procedure

Object oRegistryEnumeration Is A cArray

Property Integer piKeyCount

Function Reg_Key_Enum Integer hSubKey String sSubKeyName Returns Integer

Integer iKeyCount

Get piKeyCount to iKeyCount

Showln "Enumerating Through Registry Key: "sSubKeyName

Set piKeyCount to (iKeyCount + 1)

Function_Return 1 // continue with this pass of enumeration.

End_Function

Procedure Test

Handle hKey

// Reset counter.

Set piKeyCount to 0

Move (OpenCurrentConfigKey;

(current_object, "System\CurrentControlSet\Control\Print\Printers"));

To hKey

if (hKey <> 0) Begin

Showln "The opened key is " hKey

// Set up enumeration so that it calls back into this object.

Reg_Enum_Key_Info (object_id(self))

// Enumerate the registry starting at hKey.

Reg_Enum_Key hKey 0 // Enumerate, but do not recurse.

Reg_Close_Key hKey

End

Else Showln "Reg_Open_Key failed!"

Function_Return (piKeyCount(Self))

End_Procedure

End_Object


Reg_Enum_Key_Info

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

To assign a callback object for registry enumeration.

Syntax

Reg_Enum_Key_Info hoEnumerationCallBackObject

What It Does

Reg_Enum_Key_Info assigns the given object, hoEnumerationCallbackObject, to be the target object of the registry enumeration messages: Get_Reg_Key_Enum, Get_ Reg_String_Value_Enum, and Get_Reg_Integer_Value_Enum.

Example

Please refer to the Reg_Enum_Key command for an example of how to use this command together with the other registry enumeration commands.


Reg_Enum_Value

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

Allows for enumeration of the values of a registry subkey.

Syntax

Reg_Enum_Value hKey

What It Does

Reg_Enum_Value enumerates the values of a registry subkey. To enumerate subkeys of a registry key use Reg_Open_Key to obtain the hKey handle, assign an object to the enumeration (using Reg_Enum_Key_Info), and then invoke Reg_Enum_Value.

The function Reg_String_Value_Enum will be sent for every string value of the given key, hKey, and Reg_Integer_Value_Enum will be sent for every other value of the given subkey. Returning the value 0 from the function Reg_Key_Enum will stop the enumeration. A non-zero value will continue enumeration.

hKey must be a handle of a valid registry key. Use Reg_Open_Key to obtain the handle of the registry key. You may also use Reg_Enum_Key to obtain subkey handles.

Example

Procedure OnClick

End_Procedure

Object oRegistryEnumeration Is A cArray

Property Integer piValueCount

Function Reg_String_Value_Enum String sSubKeyName String sData Returns Integer

Integer iValueCount

Get piValueCount to iValueCount

Showln "String Value name: " sSubKeyName " It's Data: [" sData "]"

Set piValueCount to (iValueCount + 1)

Function_Return 1 // continue with this pass of enumeration.

End_Function

Function Reg_Integer_Value_Enum String sSubKeyName Integer iValue Returns Integer

Integer iValueCount

Get piValueCount to iValueCount

Showln "Integer Value name: " sSubKeyName " It's Data: [" IValue "]"

Set piValueCount to (iValueCount + 1)

Function_Return 1 // continue with this pass of enumeration.

End_Function

Procedure Test

Handle hKey

// Reset counter.

Set piValueCount to 0

Move (OpenCurrentConfigKey;

(current_object, "Display\Fonts"));

To hKey

if (hKey <> 0) Begin

Showln "The opened key is " hKey

// Set up enumeration so that it calls back into this object.

Reg_Enum_Key_Info (object_id(self))

// Enumerate the registry starting at hKey.

Reg_Enum_Value hKey // Enumerate, but do not recurse.

Reg_Close_Key hKey

End

Else Showln "Reg_Open_Key failed!"

Function_Return (piValueCount(Self))

End_Procedure

End_Object


Reg_Get_Access_Rights

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

To query the access rights of the registry.

Syntax

Reg_Get_Access_Rights To dwAccessRights

What It Does

This command gets the access rights used when invoking all registry commands, such as Get_Profile_String and Set_Profile_String. The dwAccessRights value is a bitwise combination of any of the following values. The default rights for Visual DataFlex and Web App Server are KEY_WRITE.

KEY_QUERY_VALUE | Allows the values of a registry key to be queried.
KEY_SET_VALUE | Allows the values of a registry key to be changed.
KEY_CREATE_SUB_KEY | Allows subkeys to be created within a registry key.
KEY_ENUMERATE_SUB_KEYS | Allows subkeys to be enumerated.
KEY_CREATE_LINK | Allows symbolic links to be created from points within the registry.
KEY_WRITE | Combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY
KEY_READ | Combination of all read-only access options, including enumeration.
KEY_ALL_ACCESS | Allows for reading and writing registry options and also allows symbolic links to be created.

Example

This command is especially useful when temporary changes to registry rights are required. The following case shows how the ability to create subkeys in the registry can be restricted to one section of an application. Suppose that the rights are originally set (using Reg_Set_Access_Rights) to KEY_READ.

// Change the rights to allow sub key creation

Reg_Get_Access_Rights To dwOldRights

Reg_Set_Access_Rights To (KEY_CREATE_SUB_KEY IOR REG_SET_VALUE IOR KEY_READ)

// Go create sub keys.

Reg_Set_Access_Rights to dwOldRights


Reg_Open_Key

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

To open a registry key named sNewKeyName, where sNewKeyName is a pathname of a registry key.

Syntax

Reg_Open_Key sNewKeyName To hKey

What It Does

Reg_Open_Key opens a registry key with the current registry root tree. Registry keys are the principal means of storing application and system configuration information in Windows. You may access the contents of a registry key by using Get_Profile_String or Get_Profile_Dword.

sNewKeyName must be a fully qualified key name, not including the root node name.

For example, the fully qualified path name to the VDF7 root is:

Software\Data Access Corporation\Visual DataFlex\7

hKey will return as Zero if the key cannot be accessed. This may be because you do not have appropriate rights to the key or because the key does not exist. Invoke the Win32 API function GetLastError to get the error code.

Example

Procedure OnClick

End_Procedure

Object oCurrentConfigRegistry Is A Array

Function OpenCurrentConfigKey String sKey Returns Integer

Handle hKey

Handle hRegRoot

String sDefaultPath

// Create a key within the HKEY_CURRENT_CONFIG tree.

// Save off current root settings for later restore.

Get_Registry_Root To hRegRoot sDefaultPath

Set_Registry_Root To HKey_Current_Config ""

Reg_Open_Key sKey To hKey

Set_Registry_Root to hRegRoot sDefaultPath

Function_Return hKey

End_Function

Procedure Test

Handle hRegKey

Move (OpenCurrentConfigKey;

(current_object, "System\CurrentControlSet\Control\Print\Printers "));

To hRegKey

if (hRegKey <> 0) Begin

Showln "Opened key " hRegKey

Reg_Close_Key hRegKey

End

Else Showln "Reg_Open_Key failed!"

End_Procedure

End_Object

Notes

  • Reg_Open_Key requires KEY_READ rights.

  • The key is opened in the current registry root tree. To change the registry root node, use SET_REGISTRY_ROOT. The default value is HKEY_LOCAL_MACHINE.

  • Do not forget to close the key using the Reg_Close_Key command.


Reg_Set_Access_Rights

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

Purpose

Sets the access rights of the registry.

Syntax

Reg_Set_Access_Rights To dwAccessRights

What It Does

This command sets the access rights used when invoking all registry commands, such as Get_Profile_String and Set_Profile_String. The dwAccessRights value is a bitwise combination of any of the following values. IOR may be used to build the desired level of rights. The default rights for Visual DataFlex and Web App Server are KEY_WRITE.

KEY_QUERY_VALUE | Allows the values of a registry key to be queried.
KEY_SET_VALUE | Allows the values of a registry key to be changed.
KEY_CREATE_SUB_KEY | Allows subkeys to be created within a registry key.
KEY_ENUMERATE_SUB_KEYS | Allows subkeys to be enumerated.
KEY_CREATE_LINK | Allows symbolic links to be created from points within the registry.
KEY_WRITE | Combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY
KEY_READ | Combination of all read-only access options, including enumeration.
KEY_ALL_ACCESS | Allows for reading and writing registry options and also allows symbolic links to be created.

Example

dword dwKeyRead

Reg_Set_Access_Rights to dwKeyRead

Notes

  • Setting the registry rights to a value outside of the user's allowed rights will cause a security error (rights violation) under Windows NT or Windows 2000, and your application will generate an error.


Register_Resource

Obsolete

This command is obsolete. This command is a legacy command intended for use in character-mode DataFlex.

This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources into your application.

See Also: Include_Resource

Purpose

To define the resource name and resource ID of a resource before its definition, or before it is included.

Note

This command is a character-mode legacy command that handles embedding of files as resources. This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources.

Syntax

Register_Resource {resourceName}

Argument Explanation

resourceName The name by which to address the resource in the program.

What It Does

This command reserves a slot for a resource named resourceName and defines a resource ID symbol: resourceName.RSC. This allows the resource to be referenced in source code without causing a symbol-undefined error at compile time. Resources that are registered but never defined or included do not cause an error at compile time, but any attempt to access them during runtime will result in an error.


Repeat_item Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex. There is no Windows equivalent for this option.

See Also

Purpose

To duplicate an item a specified number of times.

Syntax

repeat_item count times item_syntax

What It Does

Items in objects whose base class is menu and that use the on_item command may be created en masse with the repeat_item command. The command generates the number of on_item commands given in the value of count.

The command is provided as a convenience when creating a group of blank items or items having a common message and value (represented by item_syntax).

Repeat_item may be used only in an item definition block begun by either item_list or the begin_pull_down option of the on_item command.


Replace Command

Obsolete

This command is replaced by the Replace function.

See Also

Purpose

To search a string for a substring, and if the substring is present, to replace the first occurrence of the substring with a different substring.

Syntax

replace oldSubstring in hostString with newSubstring

Argument Explanation

hostString May be of any class except constant or expression.

What It Does

Replace scans hostString for oldSubstring. If oldSubstring is in hostString, oldSubstring is removed, and newSubstring is inserted into hostString, Predefined Indicator found is set true, and the position at which oldSubstring began is moved to Predefined Variable strmark. If oldSubstring is not found, no deletion or insertion occurs, found is set false, and zero is moved to Predefined Variable strmark.

string park

move "Everglades National Park" to park

replace "Everglades" in park with "Yellowstone"

In this example, String Variable park is searched for the substring Everglades. Where Everglades is found (at the beginning in this case), it is removed, and the word Yellowstone inserted in its place.

Replace sets the value of Predefined Variable strmark, which is used by the mid and right commands when those commands omit a position specification. This is intended to facilitate implicit positioning illustrated by the following example:

string alpha_suffix

replace "A" in "123ABC" with "Z"

[found] right "123ZBC" to alpha_suffix

In this example, the replace command places a value of 4 (the position of A in 123ABC) in strmark. The succeeding right command will use 4 as the position specification, and move the substring (ZBC) beginning at that position to String Variable alpha_suffix. The action would be defeated if the right command had a position specifier.

If you wish to simply remove a substring from a hostString, replace it with "" (two quotation marks).

Notes

  • Replace is case-sensitive. Thus, the following newSubstring would not be executed, and found is set false:

replace "DEF" in "abcdefgh" with "xyz"


Required Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To prevent the cursor from leaving an item attached to a field until data has been entered to it.

Syntax

set field_options field file.field to dd_required

or

entry_item file.field [{required [, ..., option]}]

What It Does

Required checks whether data has been entered to the current item and keeps the cursor in the current item until either data has been entered, or the Exit Application accelerator key has been pressed, terminating the program. As long as Exit Application is being used for its normal purpose of aborting the progam and closing any open files, this will cause no problem. Leaving the item by any other means without entering data results in Error 13 An entry is required on this window.

The usual way of applying this property to a field would be in a DataDictionary object using the field_options property, so that this behavior would be manifested by every item addressing file.field in every DEO using the DataDictionary.

set field_options field trucks.id to dd_required

In this example, the cursor is kept in every item attached to Field id in File trucks until data has actually been entered to it from the keyboard. This property can also be applied on an exception basis through a specific DEO by placing required on the entry_item statement.

entry_item trucks.id {required}

In this example, the cursor is kept in an item attached to Field id in File trucks until data has actually been entered to it from the keyboard.

Notes

  • Any character or characters entered to the item will allow the cursor to move on to the next item.

  • Only Exit Application will allow users to exit a required field without data, and it will normally terminate the program running.

  • You cannot trap Error 13 An entry is required on this window by required or any other means for use in on error gosub.


Resident Image Name Option

Obsolete

This option is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

Purpose

To hold an image in memory, improving performance by eliminating the need for a disk access when the image is to be output or displayed.

Syntax

/pagename resident

The keyword resident follows the image name given at the beginning of the image. It need not be delimited by spaces, nor given last.

What It Does

Resident holds an image in memory. This improves processing speed because it makes it unnecessary to access the disk to output or display the image.

Use of resident is recommended primarily for the body image of report programs and for subtotal# and subheader# images where these may appear many times in the output. It is normally not effective on data-entry images since the occasional disk read to display the image is not perceptible to the user.

/screen resident

In this example, Image screen is held resident in memory.

/body resident

In this example, Image body of a report program is held resident in memory.


Resource Image Name Option

Obsolete

This command is obsolete. This command is a legacy command intended for use in character-mode DataFlex.

This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources into your application.

See Also

Purpose

To embed sequential data in a program as a line-delimited resource instead of a display image.

Note

This command is a character-mode legacy command that handles embedding of files as resources. This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources.

Syntax

/resourceName resource

:

/*

Argument Explanation

resourceName The name of the resource to be embedded in the program.

What It Does

Resource causes the text that follows the name line to be embedded as a resource instead of including the image as an image for data entry or for (report) output. (None of the standard image-oriented symbols are defined for a resource.) The name of the resource is the image name. The resource can be treated as a sequential file in all respects; i.e. the direct_input command is used to open a resource just like any other sequential file.

You may not specify the resident or help image name options for resource images. However, you may specify the resident: option in a direct_input statement when opening the resource for sequential input.

A resource ID is also defined for the resource based on the resourceName plus a suffix of .RSC—a resource named account_defaults has a resource ID defined as account_defaults.rsc. This resource ID is a constant Integer value that can be used at runtime to refer to a resource dynamically. The direct_input and get_resource_type commands support the use of resource names directly in their syntax; any other reference to a resource must use the resource ID (or its integer value).

The type of a resource is defined during compilation and cannot be reset at runtime. Resources defined using the resource image option use a resource type of DF_RESOURCE_TYPE_LINE. The get_resource_type command is used to determine the type of a resource.

In cases where you need to refer to a resource in source code prior to the point where the resource is included, you can use the register_resource command to cause the resource name and resource ID to be defined.

The bottom border line may contain the name of the next resource to be designed or, if it is desired to begin program code, the bottom border line may contain only an asterisk after the diagonal (/*).


Retain Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To keep data in a window as an aid to data entry through an entry_clear message or a single press of the Clear Panel accelerator key, requiring a second press to clear it.

Syntax

set field_options field file.field to dd_retain

or

entry_item file.field [{retain [..., option]}]

What It Does

When retain is on an entry_item, it prevents the item from clearing when an entry_clear is received, or when the Clear Panel or Clear All Panels accelerator keys are pressed. Items in the same object without retain will be cleared. Either key will, however, will clear items with retain on them as well after the initial message.

entry_item candidat.city {retain}

In this example, data in the item connected to Field city in Database File candidat is retained through a single clearing message.

Field properties may be applied directly to a field using the field_options property in the define_fields procedure of a DataDictionary object.

set field_options field candidat.city to dd_retain

In this example, all DEOs using the DataDictionary containing this line and addressing Field city in File candidat will apply the dd _retain field property to the connected items.

Notes

  • If an entry_item with a displayonly or noenter field property is processed immediately before an entry_item with a retain field property, the retain acts as if it were a retainall, and the item cannot be cleared by any number of presses of Clear Panel.

  • The entry_clear_all message clears items to which retain applies, as well as those to which it does not.

  • If you want to prevent Clear Panel from ever clearing the item, use the retainall entry_item field property.


Retainall Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To keep data in an item as an aid to data entry through all clearing operations.

Syntax

set field_options field file.field to dd_retainall

or

entry_item file.field [{retainall [..., option]}]

What It Does

When retainall is on an entry_item, it prevents clearing of the contents of the item by such messages as entry_clear and entry_clear _all, or pressing of the Clear Panel or Clear All Panels accelerator keys.

entry_item this_co.name {retainall}

In this example, data shown through the item attached to Field name in File this_co is retained in the item regardless of how many times the Clear Panel key is pressed.

Field properties may be applied to fields using the field_options property in the define_fields procedure of a DataDictionary object.

set field_options field this_co.name to dd_retainall

In this example, every DEO with an item addressing Field name in File this_co and using the DataDictionary in which this line is coded, will apply the dd_retainall field property to such item.

Notes

  • Even though users cannot clear the item with Clear Panel, they still may erase it manually (character-by-character).

  • If you want to be able to clear the item by pressing Clear Panel, use the retain field property.


Return Command

Obsolete

From Visual DataFlex version 6.0 and beyond, the Gosub_Return command must be used to return execution from a subroutine call.

From Visual DataFlex version 7.0 and beyond the Return command will be used to terminate procedures and functions.


Right Command

Obsolete

This command is replaced by the Right function.

See Also

Purpose

To move the rightmost characters of a variable to a variable.

Syntax

right string to variable [length]

What It Does

Right moves the number (counted from the right) of characters from string given in length to variable.

string team score

move "MIAMI DOLPHINS 34" to team

right team to score 2

In this example, the rightmost two characters of the contents of String Variable team (34) are moved to String Variable score.

Length may be given in the command as a variable, or it may be omitted, in which case the value of Predefined Variable strlen will be used. Strlen is output by pos and other string processing commands.

string team score

move "MIAMI DOLPHINS 43" to team

pos " " in team

right team to score

while strmark gt 0

right score to score (strlen 1)

pos " " in score

end

In this example, the portion of the value of String Variable team beginning with the first space is moved to Variable score. The first pos command above detects the position of the leftmost space in team and moves it implicitly to Predefined Variable strmark. If a space is found (strmark gt 0), the while ... end loop is executed, truncating the portion of score to the left of the leftmost space until there are no spaces left in score. In the example above, score would contain 43 when the loop stopped executing.

Notes

  • If length is less than 1, right will output no characters.

  • If length is greater than the length of string, right will output all of string.

  • Although right can be used on Date, Integer, and Number type variables, it is typically used on String type variables.

  • String and variable may be the same variable. Used this way, right simply truncates string on the left:

right suffix to suffix 2

In this example, the rightmost 2 characters are removed from the value of Variable suffix.


Set_App_Profile_String

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also: Set_Profile_String

Purpose

This command is used to implement optimizations in set profile_string. It should not be used by applications.

Syntax

set app_profile_string ValueName Value

Argument Explanation

ValueName Name of one of the values to set.

Value The string contents of the value ValueName.


Set_cursor_visible Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

Refer to the CursorShape class for handling cursors in Visual DataFlex.

See Also

Purpose

To return the state (visible or invisible) of the cursor.

Syntax

set_cursor_visible visible

Visible should be 0 (false) to set the cursor invisible, any other value (true) to set it visible.

What It Does

This command enables you to specify whether the cursor is to be visible.

Notes

  • You can get the visibility of the cursor with the get_cursor_visible command.


Set_default_map_mode Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To set the default map mode to be used by the system.

Syntax

set_default_map_mode to value

Argument Explanation

value An Integer value for the map_mode property:

  • MAP_DEVICE

  • MAP_CHARACTER

  • MAP_DIALOG

What It Does

Set_default_map_mode sets the value of the map_mode property for the desktop. This mode applies to all objects that do not set their own map_modes explicitly in either their class definitions or their object definitions. This map_mode is MAP_DIALOG unless a previous set_default_map_mode statement has set it to a different value. See Map_mode Property for explanations of the modes.

set_default_map_mode to MAP_DIALOG

In this example, the default map_mode is set to MAP_DIALOG.


Set_dfpath Command

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To identify the directories to be searched when file commands are executed on filenames that do not themselves specify the directory.

Syntax

set_dfpath to directory(ies)

What It Does

Set_dfpath replaces the value (if any) of the DFPATH environment variable with the directory(ies) identified in directory(ies).

set_dfpath to postInventory

In this example, the value of the DFPATH environment variable is replaced by the value of String Variable postInventory.

To suppress DataFlex pathing entirely, execute set_dfpath "". Set_dfpath must be used in the program above all file commands that are to make use of it. Set_dfpath may be used multiple times in a program, but it should not be changed while any file is open.

The value of directory(ies) specifies the directory or directories that are to be searched whenever a DataFlex command calls for the opening, creation, deletion, renaming, or copying of a file, including database (.dat) files. The directories are searched in the order in which they are named.

The current directory will not be searched unless it is named in directory(ies) (or directory(ies) is empty). The current directory may be placed in the search path by using a period (.) as a pathname.

DFPATH is used only for files that are named without path specification. Where a statement includes a directory path with the filename, or the directory name of a database file in the file list contains a directory, DFPATH will have no effect.

Different commands use DFPATH somewhat differently:

Erasefile and renamefile search only the first directory path named.

Copyfile searches only the first directory path, and places the copy in the first directory path.

Open, make_file, and direct_input open the first file with the specified name found in the directories.

Append_output, and direct_output open the first file with the specified name found in the directories to which the user has write privileges and, if none is found, a new file is created in the first directory in which the user has write privileges.

Notes

  • When directory(ies) contains directory paths that do not exist, most operating systems report an error. The error reported in such cases will vary by operating system, and will not be generated until a file command makes use of the value of directory(ies).

  • Set_dfpath does not change the value of the DFPATH environment variable—it merely replaces the value for purposes of the program by setting the DF_OPEN_PATH attribute, which you can access with the get_attribute command. If you wish to restore the value from the environment variable, you can do so with the get_environment command.


Set_filelist Command

Obsolete

The set_filelist command Obsolete. Use the DF_FILELIST_NAME Database API attribute in its place.

See Also

Purpose

To identify the path and filename of the file to be used as the file list.

Syntax

set_filelist file_name

Argument Explanation

file_name The pathname of the file to set as the file list.

What It Does

This command sets the file list to be used by DataFlex until it is reset, either by another set_filelist command or the program ends. This allows you to easily switch between groups of files and file lists within a running program.

File_name must be a valid file list. The DataFlex compiler does not check this name to ensure that it is actually a file list. If file_name is not a file list, then the program will terminate abnormally.

set_filelist "c:\test\filelist.cfg"

This example sets the file list to FILELIST.CFG in the C:\TEST directory.

Notes

  • Be aware that if you change file lists within a running program, DataFlex no longer automatically protects against deadlock. DataFlex opens and locks files in order of their file-list numbers. By changing file lists, it becomes possible for deadlock to occur, so you must consider how to handle possible deadlock. The same thing is true when using the Open . . . as command.

  • You cannot have two files open under the same number at the same time. For example, assume you are using these two file lists:

FILELIST.CFG FL2.CFG

: :

4. Employee 4.TestData

5. OrdEntry 5. TestRslt

6. Details 6. TestSpec

: :

Now the following code executes while FILELIST.CFG is the file list:

open OrdEntry

set_filelist "FL2.CFG"

:

open TestRslt

The open TestRslt statement will fail, since DataFlex sees that File Number 5 is already open. No error will be reported, since DataFlex has no way of knowing that you are trying to open a different File Number 5 from the one already open.

  • It is recommended that a given file have the same number in every file list in which it appears. This can avoid many problems, such as the one described above.


Set_Foreign_Profile_String

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To set the contents of a value of a key in a branch of the registry, creating new branches, keys, and values if they do not already exist.

Syntax

set_foreign_profile_string keyname subkeyname valuename to value

Argument Explanation

keyname The name of a key in the registry.

subkeyname The name of a subkey in key keyname.

valuename The name of a value defined in key subkeyname.

value The new string contents for the value named valuename.

What It Does

Set_foreign_profile_string sets the contents of the value valuename under subkey subkeyname in the key keyname.

set_foreign_profile_string "Microsoft\Windows\CurrentVersion\Time Zones" ;

"Atlantic" "Dlt" to "Data Access Daylight Time"

This example sets the name of Atlantic Daylight Time to "Data Access Daylight Time".

Windows will create a path to the value, adding branches of keys and subkeys and value names to satisfy the call. Make certain the registry root branch is also set correctly before executing SET_FOREIGN_PROFILE_STRING.


Set_Profile_String

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To set the contents of a value of a key in the Visual DataFlex (current version) branch in the Registry, creating new keys and values if they do not already exist.

Syntax

set_profile_string subkeyname valuename to value

Argument Explanation

subkeyname The name of a subkey in the Visual DataFlex default section of the Registry. Visual DataFlex 9.1 points to "Data Access Worldwide\Visual DataFlex 9.1" by default.

valuename The name of a value defined in subkeyname.

value The new contents of the value valuename.

Alternate Syntax

set_profile_string keyname subkeyname ;

[valuename value[, ... ..., valuename value]]

Argument Explanation

keyname The name of a key in the Visual DataFlex (current version) default branch of the Registry.

subkeyname The subkey that contains the values to set.

valuename The name of a value defined in subkeyname.

value The new contents of the value valuename.

What It Does

Set_profile_string sets the contents of one or more values in a subkey of the Visual DataFlex default branch of the Registry.

Set_Profile_String "APPLICATION_LINKS" "CrystalRWPath" To ;

"C:\Program Files\Crystal Decisions\Crystal Reports 9\crw32.exe"

In this example, the Registry value CrystalRWPath in key HKey_Local_Machine\Data Access Worldwide\Visual DataFlex \9.1\APPLICATION_LINKS is set to the location of the Crystal Reports 9 report writer.

The Visual DataFlex default branch of the registry is Software in the HKEY_LOCAL_MACHINE root. This can be changed in and for a running Visual DataFlex program with the set_registry_root command. If the default is so changed, all set_profile_string commands will address the redefined default until an additional set_registry_root statement restores it to the original default.

Notes

  • If no key called keyname is found in the Visual DataFlex default branch, and/or no value called valuename is found under keyname, keyname and/or valuename is (are) created, and set to the contents of value.

  • Using the alternate format, multiple valuenames can be set for the same subkeyname, but subkeyname and keyname must be named. Further, the to keyword is not used between items and their values. The item/value pairs are separated from each other by commas.


Set_Registry_Root

Obsolete

This command is obsolete. Use the cRegistry class for accessing the Windows Registry in Visual DataFlex.

See Also

Purpose

To change the registry root and branch used by the profile-string getting and setting commands.

Syntax

set_registry_root to root branch

Argument Explanation

root The name of a root in the Windows registry. This may be one of the following values:

HKEY_CLASSES_ROOT COM class and file type information. Sub-tree of HKEY_LOCAL_MACHINE.

HKEY_CURRENT_USER Sub-tree of HKEY_USERS which corresponds to the information about the current user. This is where user-specific information for an application can be stored.

HKEY_LOCAL_MACHINE This is where all global (not user-specific) machine information is stored. This tree contains the Software branch where most applications store their global information. This is the default setting for Visual DataFlex.

HKEY_USERS This is where all user-specific information is stored. The sub-tree for the current user is better accessed through HKEY_CURRENT_USER.

HKEY_PERFORMANCE_DATA Not generally used by applications.

HKEY_CURRENT_CONFIG Not generally used by applications.

HKEY_DYN_DATA Not generally used by applications.

branch The name of a branch under root in the Windows registry.

What It Does

This command sets the default root and branch (top two keys) of the Windows registry to access control panel settings for the current user.

Set_Registry_Root TO HKEY_CURRENT_USER "Control Panel"

get_foreign_profile_string "International" "" "sShortDate" to sValData

showln "The short date format is " sValData

In this example, the registry access root and branch are changed to, respectively, HKEY_CURRENT_USER and "Control Panel". Then get_foreign_profile_string is used to return the short date format setting as defined in the date settings of the control panel.

Whenever a branch does not exist, set_foreign_profile_string will create the necessary access members (keys and values) the first time a registry value is written with set_foreign_profile_string.

The default DataFlex root and branch are used by the get_profile_string, set_profile_string, get_foreign_profile_string, and set_foreign_profile_string commands.


Set_Resource_Library Command

Obsolete

This command is obsolete. This command is a legacy command intended for use in character-mode DataFlex.

This command does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources into your application.

See Also

Purpose

To enable DataFlex programs to address resources at run time that are in other programs or files.

Syntax

set_resource_library to fileName

Argument Explanation

fileName The name of the compiled file containing resources desired for the currently running program.

What It Does

Set_resource_library identifies the compiled file that contains resources desired for the currently running program. The resource library in effect for any program that has not used this command is the currently running program itself. Once this command has set the library to some other file, resources of the running program cannot be opened (assigned to an input channel by the direct_input command). If they were already open at the time this command was executed, however, they may continue to be accessed until they are closed.

FileName may be another, runnable DataFlex program, but does not have to be. It need only contain a resource, either in its own source code or through the include_resource command.

When one program chains to another with the wait option, resources already open in the calling program remain open in the called program, but the resource library changes to the contents of the called program. If the seq_export option of chain is used, however, the resources of both programs remain available in the called program.

Notes

  • FileName must be compiled by the DataFlex compiler before it can be addressed by this command. By default, the compiler produces files with the extension .EXE. FileName need not have this or any particular extension, and so may be renamed after compilation if it is not in fact a runnable program, so as to avoid confusion with other compiled files that are runnable programs.

  • The statement set_resource_library to "" will always set the resource library to the .VDF file of the running program that contains the statement (the default).


Signrt Print Format Option

Obsolete

This option is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To place a minus sign on the right side of negative values in report output.

Syntax

print variable [to window] [{signrt [..., option]}]

What It Does

When signrt is on a format or print command line, negative numbers displayed through window are shown with the minus sign to the right instead of to the left, as they are otherwise.

format image.3 thru image.6 {signrt}

In this example, Windows 3 through 6 of Image image are formatted to place the minus sign on the right of numbers.

print parts.cost to screen.2 {signrt, points =2}

In this example, the value of Field cost in Database File parts is printed to the second window of Image screen with negative numbers to the right, and with only the first two decimal places to the right of the decimal point displayed.

Notes

  • Signrt has no effect on non-Numeric windows, and so may be used in format commands addressing a range of windows so long as the option is desired for every Numeric window in the range.

  • When setting the size of a window that may display negative numbers, remember to provide an additional space for the minus sign (whether it is on the left or the right), as well as for other formatting characters such as decimal points and commas.

  • If a signrt option is used on an entry_item command line, it will have no effect, as it is intended only for use with the print and format commands.

  • Do not address signrt-formatted windows in expressions, since the misplaced minus sign may corrupt the value of the windows.


Skipfound Field Property

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To prevent data entry to an item if the buffer for the database file has an active record in it.

Syntax

set field_options field file.field to dd_skipfound

or

entry_item file.field [{skipfound [..., option]}]

What It Does

When skipfound is on an entry_item and a record is already in the file buffer (has been found), the cursor skips the item.

This enables programs to prohibit changes to certain fields in existing records.

If the buffer for file is clear (as after the Clear Panel accelerator key has been pressed), the cursor will stop at the item and allow data entry. A subsequent save will create a new record.

entry_item photo.photographer {skipfound}

In this example, the item is skipped when an active record is in the buffer for Database File photo. When no active record is in the buffer, the cursor stops there.

Field properties can be applied directly to fields in DataDictionary objects using the field_options property.

set field_option photo.photographer to dd_skipfound

This example would apply dd_skipfound to every item addressing Field photographer in File photo from a DEO using the DataDictionary containing it. This option can be suspended in individual DEOs by provision of an item_options ... skipfound message in them, as:

item_options item 8 skipfound false

This example would suspend dd_skipfound for the ninth item of the DEO containing it.

Notes

  • Skipfound positively prohibits entry to an item when an active record is in the buffer. Users cannot get into the item with the Previous accelerator key when an active record is in the buffer.

  • Skipfound operates according to the state of Predefined Indicator found. It skips when found is true.

  • Noenter is a similar field property. However, it skips the item in all cases, regardless of whether an active record is in the buffer.


Size_of_Field

Obsolete

This command is obsolete. Use the DF_FIELD_LENGTH and DF_FIELD_PRECISION attributes instead.

See Also: Field, Put_String, Type

Purpose

To return the size of a field in a complex data structure in bytes.

Syntax

size_of_field field to variable

Argument Explanation

field The field in a complex data structure whose size is to be returned.

variable The name of a variable to which the value of field is to be moved.

What It Does

Size_of_field returns the number of bytes occupied by Field field in a complex data structure.

Notes

  • The value returned by this command is not affected by the length of field's contents, as fields in complex data structures are always padded out to their full lengths with ASCII zeroes to the extent their contents fall short


SQLBindFetchFile Command

Obsolete

Refer to the SQLBindFile method in the cSQLStatement class.

SQLBindFetchFile hstmt|hdbc FileNumber|FileName

The SQLBindFetchFile command allows the programmer to setup a default file for a connection or statement. If the default is setup, no arguments need to be passed to the SQLFileFetch command. This is normally only used when a file connection has been opened using the SQLConnect command (as opposed to the SQLFileConnect command).

SQLSetConnect "DB2_DRV"_ID "DSN=CompanyServer;UID=John;PWD=Secret"

SQLConnect To hdbc

SQLOpen hdbc To hstmt

SQLBindFetchFile hstmt Customer // set default file for fetches

SQLExecDirect hstmt "SELECT * FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFileFetch hstmt

If (SQLResult) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))

When a file connection is opened using SQLFileConnect, the default file is automatically set to the file number passed with this command. Normally, this will be the file you will want to use as bind file. Therefore, if SQLFileConnect is used you will rarely need to execute the SQLBindFetchFile command.

Open Customer

SQLFileConnect Customer To hdbc // this will bind Customer as fetch file

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFileFetch hstmt

If (SQLResult) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))

If you use the SQLConnect command to create a connection, no default file is set. In such a case, using the SQLBindFetchFile command would allow you to set a default file. If you do not set a default file, you must pass a file name with the SQLFileFetch command.

SQLSetConnect "DB2_DRV"_ID "DSN=CompanyServer;UID=John;PWD=Secret"

SQLConnect To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFileFetch hstmt to Customer

If (SQLResult) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))


sqlcall_command

Obsolete

Refer to the SQLCall method in the cSQLStatement class.

SQLCall sProcName sSchema [Arg1…] [To Retval]

The SQLCall command allows the programmer to call stored procedures. The number of arguments and return value depend on the procedure definition. Stored procedures in general can have three different types of arguments: in, out and in/out. All these types are supported.

It is possible for stored procedures to contain select statements and thus return one or more result sets next to the out arguments and return value. Conceptually, the out arguments and return value are also a result set. Some back ends will fill the arguments and return value immediately. Others will always return other result sets before filling the arguments and return value. Microsoft SQL Server for example always returns arguments and return value as the last result set. In this case the arguments need to be requested from the statement in a separate call using the SQLGetArguments command. Multiple result sets can be handled by switching to the next result set using the command SQLNextResultSet.

SQLConnect "MSSQLDRV" "SERVER=(Local);Trusted_Connection=yes;DATABASE=Order" To hdbc

SQLOpen hdbc To hStmt

SQLCall hStmt "sp_MonthlyBatch" "bpo" nTotalAmount To iSuccess

If (iSuccess) ;

Showln "The total amount of the monthly batch is: " nTotalAmount

Else ;

Showln "The monthly batch did not succeed."


SQLClose Command

Obsolete

Refer to the SQLClose method in the cSQLStatement class.

SQLClose hstmt

The SQLClose command closes the statement and frees all associated resources.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "UPDATE CUSTOMER SET AccntMngr = 'John' WHERE AccntMngr = 'Mary'"

SQLClose hstmt


SQLColumnMap Command

Obsolete

Refer to the SQLColumnMap method in the cSQLStatement class.

SQLColumnMap hstmt sColName To iColNumber

The SQLColumnMap command maps a column name to a column number.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM Customer"

SQLColumnMap "Picture" To iColNum

Repeat

SQLFetch hstmt

Move SQLResult To FetchResult

If (FetchResult) Begin

Repeat

SQLGetData hstmt iColNum Length 1024 To sPictureChunck

If (SQLResult) ;

Send HandlePictureChunk sPictureChunk

Until (SQLResult <> SQLSuccess)

End

Until (Not(FetchResult))


SQLConnect Command

SQLConnect

Obsolete

Refer to the SQLConnect method in the cSQLHandleManager class.

SQLConnect [sDriver sConnectString] To hdbc

The SQLConnect command will return a handle to a database connection (hdbc). You need to specify the driver to use and the server to connect to. If the driver and or connect string were already specified in SQLSetConnect they may be omitted.

To get a handle to a connection to a DB2 server you could:

SQLSetConnect "DB2_DRV" DSN=CompanyServer;UID=John;PWD=Secret"

SQLConnect To hdbc

SQLConnect "DB2_DRV" "DSN=CompanyServer;UID=John;PWD=Secret" To hdbc


SQLDisconnect Command

SQLDisconnect

Obsolete

Refer to the SQLDisconnect method in the cSQLConnection class.

SQLDisconnect hdbc

The SQLDisconnect command closes a connection.

If it was created by the SQLConnect command all associated resources will be freed and the connection is actually closed.

If the connection was already in use, i.e. SQLFileConnect was used to obtain the handle, the embedded SQL resources of the connection are freed but the connection itself will not be closed.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "UPDATE CUSTOMER SET AccntMngr = 'John' WHERE AccntMngr = 'Mary'"

SQLClose hstmt

SQLDisconnect hdbc


SQLExecDirect Command

SQLExecDirect

Obsolete

Refer to the SQLExecDirect method in the cSQLStatement class.

SQLExecDirect hstmt sStatement

The SQLExecDirect combines the SQLPrepare and SQLExecute into one command.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "UPDATE CUSTOMER SET AccntMngr = 'John' WHERE AccntMngr = 'Mary'"


SQLExecute Command

SQLExecute

Obsolete

Refer to the SQLExecute method in the cSQLStatement class.

SQLExecute hstmt

Execute a prepared statement.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLPrepare hstmt "UPDATE CUSTOMER SET AccntMngr = 'John' WHERE AccntMngr = 'Mary'"

SQLExecute hstmt


SQLFetch Command

SQLFetch

Obsolete

Refer to the SQLFetch method in the cSQLStatement class.

SQLFetch hstmt [To Var1 [Var2 …]]

The SQLFetch command will fetch the next row of a statements result set. The columns are placed in the variables passed as argument.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT Name, Address FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFetch hstmt To Customer.Name Customer.Address

If (SQLResult = SQLSuccess) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT count(*) FROM CUSTOMER WHERE AccntMngr = 'Mary'"

SQLFetch hstmt To iCount

If (SQLResult) ;

Showln "There are " iCount " customers for account manager Mary"

Else ;

Showln "There are no customers for account manager Mary"


SQLFetchActivatesBuffer Command

SQLFetchActivatesBuffer

Obsolete

Refer to the SQLFetchActivatesBuffer method in the cSQLStatement class.

SQLFetchActivatesBuffer hstmt FileNumber|FileName bState

The SQLFetchActivatesBuffer can be used to connect a buffer's status to Embedded SQL. Normal execution of Embedded SQL will never set the buffer status to active. By using this command this link can be provided.

It is possible to link multiple buffers to one statement by subsequently issuing SQLFecthActivatesBuffer statements for every buffer to link. Linked buffers can be removed from a statement by passing false, when passing true the buffer will be added to the statement.

The Embedded SQL engine adjusts the status of all linked file buffers automatically directly after the fetch inside a SQLFetch or SQLFileFetch command. The status is set to active if the fetch was successful; otherwise the status is not adjusted.

Warning: Linking buffers will negatively affect optimization of the Find logic within the Connectivity Kit. It is recommended to only link buffers when needed and unlink as soon as possible.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM Customer WHERE City = 'Amsterdam'"

SQLFetchActivatesBuffer hstmt Customer True

Repeat

SQLFileFetch hstmt To Customer

If (SQLResult) Begin

Reread Customer

Move "(+31) 020" To Customer.AreaCode

Saverecord Customer

Unlock

End

Until (Not(SQLresult))

SQLFetchActivatesBuffer hstmt Customer False


SQLFileConnect Command

SQLFileConnect

Obsolete

Refer to the SQLFileConnect method in the cSQLHandleManager class.

SQLFileConnect FileName|FileNumber To hdbc

The SQLFileConnect will return a handle to the connection of a table that is already open in the program. If you already connected to a server by opening tables on it, you can use that connection without repeating the login information.

Open Customer

SQLFileConnect Customer To hdbc


SQLFileFetch Command

SQLFileFetch

Obsolete

Refer to the SQLBindFile method in the cSQLStatement class.

SQLFileFetch hstmt [To FileNumber1|FileName1 [Filenumber2|FileName2…]]

The SQLFileFetch command will fetch the next row of a statement's result set. The columns are placed in the file buffers passed as argument. If no argument is passed the command will attempt to use a default file buffer. If the connection was opened using the SQLFileConnect command, the file used for this connection will be the default file. If the connection is opened using SQLConnect the default file can be set using the SQLBindFetchFile command, or, the file can be explicitly passed in the SQLFileFetch command.

Open Customer

SQLFileConnect Customer To hdbc // this will bind Customer as fetch file

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFileFetch hstmt // if no file, use default

If (SQLResult) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))

The Embedded SQL engine will use the base column and table names to determine if columns of a file are used. If the table and column name match, the column will be filled with the value from the result set. Some back ends do not support returning base table names. In that case only the column name will be matched. This scheme allows the programmer to use statements that only select a limited number of columns from a table. The Embedded SQL engine will make sure the correct mapping is performed.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM CUSTOMER WHERE AccntMngr = 'Mary'"

Repeat

SQLFileFetch hstmt To Customer

If (SQLResult) ;

Showln Customer.Name ", " Customer.Address

Until (Not(SQLResult))


SQLGetArguments Command

SQLGetArguments

Obsolete

Refer to the SQLGetArgument method in the cSQLStatement class.

SQLGetArguments hstmt [Arg1…] [To Retval]

The SQLGetArguments command can be used for back ends that return the out arguments and return value of a stored procedure as the last result set.

SQLConnect "MSSQLDRV" "SERVER=(local);Trusted_Connection=yes;DATABASE=Order" To hdbc

SQLOpen hdbc To hstmt

SQLCall hstmt "sp_MonthlyBatch" nTotalAmount To iRetval

Move False To bNoMoreSets

Repeat

SQLStmtAttribute giHstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumColumns

If (iNumColumns) Begin

SQLFetch hstmt

While SQLResult

For iCount From 1 To iNumColumns

SQLGetData hstmt iCount To sColValue

Show sColValue

If (iCount < iNumColumns) ;

Show ", "

Loop

Showln

SQLFetch hstmt

Loop

End

SQLNextResultSet hstmt

If (Not(SQLResult)) ;

Move True To bNoMoreSets

Until bNoMoreSets

SQLGetArguments hstmt nTotalAmount To iRetval

Showln "Total amount: " nTotalAmount

Showln "Retval is : " iRetval


SQLGetData Command

SQLGetData

Obsolete

Refer to the SQLGetData method in the cSQLStatement class.

SQLGetData hstmt iColumnNumber [Length iLen] To Var

The SQLGetData command allows a programmer to get data from an individual column by its number. The command can be used to traverse a results set of which the number of columns is unknown when creating the program. It can also be used when a column is too large to get in one time. In that case you can use the SQLGetData command to get the column in chunks.

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM Customer"

SQLStmtAttribute hstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumColumns

If (iNumColumns) Begin

SQLFetch hstmt

While SQLResult

For iCount From 1 To iNumColumns

SQLGetData hstmt iCount To sColValue

Show sColValue

Loop

Showln

SQLFetch hstmt

End

End

Else ;

Showln "NO columns in result!"

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT Picture FROM Customer"

Repeat

SQLFetch hstmt

Move SQLResult To FetchResult

If (FetchResult) Begin

Repeat

SQLGetData hstmt 1 Length 1024 To sPictureChunck

If (SQLResult) ;

Send HandlePictureChunk sPictureChunk

Until (SQLResult <> SQLSuccess)

End

Until (Not(FetchResult))


SQLNextResultSet Command

Obsolete

Refer to the SQLNextResultSet method in the cSQLStatement class.

SQLNextResultSet hstmt

The SQLNextResultSet will advance the current result set. The command is used when a statement returns multiple result sets. Multiple result sets can be returned by a stored procedure or by using a batch of statements.

SQLConnect "MSSQLDRV" "SERVER=(local);Trusted_Connection=yes;DATABASE=Order" To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM salesp; SELECT * FROM orderhea"

Move False To bNoMoreSets

Repeat

SQLStmtAttribute giHstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumColumns

If (iNumColumns) Begin

SQLFetch hstmt

While SQLResult

For iCount From 1 To iNumColumns

SQLGetData hstmt iCount To sColValue

Show sColValue

If (iCount < iNumColumns) ;

Show ", "

Loop

Showln

SQLFetch hstmt

Loop

End

SQLNextResultSet hstmt

If (Not(SQLResult)) ;

Move True To bNoMoreSets

Until bNoMoreSets


SQLOpen Command

SQLOpen

Obsolete

Refer to the SQLOpen method in the cSQLConnection class.

SQLOpen hdbc To hstmt

The SQLOpen command will return a handle to a statement.

SQLConnect "DB2_DRV" "DSN=CompanyServer;UID=John;PWD=Secret" To hdbc

SQLOpen hdbc To hstmt

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt


SQLPrepare Command

SQLPrepare

Obsolete

Refer to the SQLPrepare method in the cSQLStatement class.

SQLPrepare hstmt sStatement

The SQLPrepare statement will prepare a statement for execution. This will enable the DataFlex programmer to prepare once and run many times.

It is possible to pass a so-called batch of statements. Multiple statements must be separated by a semicolon (';').

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLPrepare hstmt "UPDATE CUSTOMER SET AccntMngr = 'John' WHERE AccntMngr = 'Mary'"


SQLSetConnect Command

SQLSetConnect

Obsolete

Refer to the SQLSetConnect method in the cSQLHandleManager class.

SQLSetConnect sDriver sConnectString

The SQLSetConnect command allows the programmer to setup a default driver and connection for embedded SQL commands that follow. It is expected that using more than one driver in an environment, although possible, will not be very common.

The second argument is a connect string that identifies the connection to use in embedded SQL commands that follow. If you are always using the DB2 on your company server you could set this up once by:

SQLSetConnect "DB2_DRV" "DSN=CompanyServer;UID=John;PWD=Secret"


SQLStmtAttribute Command

Obsolete

Refer to the SQLStmtAttribute method in the cSQLStatement class.

SQLStmtAttribute hstmt iAttribId To sAttribValue

The SQLStmtAttribute command allows the programmer to get statement attributes.

Attribute | Description
COLUMNCOUNT | The number of columns in the result set of the statement.
ROWCOUNT | The number of rows in the result of the statement. For update, delete or insert statement this attribute returns the number of rows affected by the statement.
ROWCOUNT_TYPE | The accuracy of the rowcount attribute. This attribute can be: 1 The rowcount returns the exact number of rows 0 The rowcount does not return a meaningful value -1 The rowcount is approximate The rowcount type depends on the type of cursor used for the Embedded SQL statement. Some back ends will automatically adjust cursor types. SQL Server for example does not support all cursor types to use certain statements. If a statement is issued for a non supported cursor type the cursor type will be adjusted.

The attribute described above can be accessed through predefined constants. These constants have the SQLSTMTATTRIB_ prefix. So to get the number of columns of a statement one would program:

SQLStmtAttribute hstmt SQLSTMTATTRIB_COLUMNCOUNT ;

To iNumColumns

A full source example of getting the column count of a select statement is:

Open Customer

SQLFileConnect Customer To hdbc

SQLOpen hdbc To hstmt

SQLExecDirect hstmt "SELECT * FROM Customer"

SQLStmtAttribute hstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumColumns

Showln "The statement has " iNumColumns " columns."


Status Command Component

Obsolete

This command is valid only in character-mode DataFlex.

Refer to the HasRecord function and Current_Record property of the DataDictionary class.

Indicators are also obsolete, with the exception of predefined indicators that already exist in the language. Among the reasons for this is the limit of 89 user-defined indicators per program and that indicators are global.

Use the Boolean command to declare Boolean variables instead or declare properties in classes and objects. You can use the move command to set and retrieve the value of indicators.

See Also

Purpose

To indicate whether the buffer for a specific database file is active (contains an existing record for editing).

Syntax

indicate indicator status df_filename

if status df_filename statement

Argument Explanation

df_filename The name of the database file whose status is to be checked.

statement Any line of DataFlex code containing a command.

What It Does

Status df_filename may be used as though an indicator to set the values of other indicators or as an if test to control commands according to whether df_filename has the status of an active record in the buffer. A file's record buffer is active after a successful find, and remains active until either it is cleared, or a value is moved to its recnum.

indicate cust_found status customer

In this example, Indicator cust_found is set true. This sets the Indicator cust_found to true if an active record is in the customer record buffer. Otherwise, cust_found is set false.

Note that the as normally used in indicate commands is not used with status.

if status customer gosub sale

In this example, Labelled Subroutine sale is executed if the record buffer for Database File customer contains an active record. Otherwise, the gosub is not executed.

Note that the if test for status contains no operator (eq active), as other if tests do.

Status may be thought of as a found indicator which you can query for any df_filename open in the program at any time, regardless of finds which may have been done in other files since the find or relate in other files.

Notes

  • The value of Predefined Indicator found is set by the most recent find, regardless of what database file it was in. status, however, retains its value until a change (clear, delete, save) has occurred in the buffer for df_filename.


Strlen Predefined Variable

Obsolete

This variable is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To hold the length of the substring found in the last string-manipulating command.

Syntax

strlen

What It Does

Strlen is used, and set, by the index_def, mid, pos, right, and sysdate commands. In the right command, for example, the ending length argument is optional. If it is not used, the value of strlen from the last previous index_def, mid, pos, right, or sysdate command will be used for the value of length.

string sighting type

move "10 Bombers" to sighting

pos " " in sighting

right sighting to type

In this example, the pos command determines the position of the length of the substring in the value of Variable sighting which begins with the space (8) and puts the value to strlen (regardless of whether any position argument was included in the command). The succeeding right command, since it has no length argument, relies on the value of strlen to extract the eight-character substring " Bombers" (including the leading space) from Variable sighting and move it to Variable type.

If, on the other hand, the right command had given a length specification, that value would become the new value of strlen.

The mid command uses both a position and a length specification. If the command is given with neither specification, it uses the value of strlen for length and the value of strmark (also set by pos) for position (see strmark Predefined Variable).

string sighting type

move "10 Bombers" to sighting

pos " " in sighting

mid sighting to type

This example would produce exactly the same results as the right example above. The pos command determines the length of the substring in the value of Variable sighting which starts with the space (8) and puts the value to strlen, and it puts the position of the space as counted from the left (3) to strmark (and also puts three to any optional position argument). The succeeding mid command, since it has no length or position arguments, relies on the value of strmark (3) for its starting point, and on strlen for the length of the substring, to extract the eight-character substring Bombers (including the starting space) from Variable sighting and move it to Variable type.

Use of strlen is entirely optional. Your own explicit arguments may be used to hold the same values, and produce the same results.

Notes

  • The sysdate command outputs the minutes of the time to strlen, so do not allow sysdate commands to intervene among other commands which depend on the value of strlen.

  • Functions having the same names as commands that move a value to strlen, do not affect the value of strlen.


Strmark Predefined Variable

Obsolete

This variable is obsolete. This command is valid only in character-mode DataFlex.

See Also

Purpose

To hold the position of the substring found in the last string-manipulating command.

Syntax

strmark

What It Does

Strmark is used, and set, by the insert, left, mid, pad, pos, and replace commands. In the left command, for example, the ending length argument is optional. If it is not used, the value of strmark from the last previous insert, left, mid, pad, pos, replace, or sysdate command will be used for the value of length.

string sighting count

move "10 Bombers" to sighting

pos " " in sighting

left sighting to count

In this example, the pos command determines the position of the space in the value of Variable sighting (3) and puts the value to strmark (and would put the same value to any optional position argument included in the command). The succeeding left command, since it has no length argument, relies on the value of strmark to extract the three-character substring "10 " (including the ending space) from Variable sighting and move it to Variable count.

If, on the other hand, the left command had given a length specification, that value would become the new value of strmark.

The mid command uses both a position and a length specification. If the command is given with neither specification, it uses the value of strlen (also set by pos) for length (see strlen Predefined Variable) and the value of strmark for position. If the command is given with one specification, it uses that specification for length and strmark for position.

string sighting type

move "10 Bombers" to sighting

pos " " in sighting

mid sighting to type 5

This example would move the string Bomb (including the leading space) to Variable type. The pos command determines the position of the space as counted from the left (3) and puts it to strmark (and also puts three to any optional position argument). The succeeding mid command, since it has no position argument, relies on the value of strmark (3) for its starting point, and on the literal argument (5) for the length of the substring, to extract the five-character substring Bomb.

Use of strmark is entirely optional. Your own explicit arguments may be used to hold the same values, and produce the same results.

Notes

  • The file_size, page and sysdate commands also change the value of strmark, so do not allow these or, better, any commands to intervene among other commands which depend on the value of strmark.

  • Functions having the same names as commands that move a value to strmark, do not affect the value of strmark.


Suppress Print Format Option

Obsolete

This format option is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To suppress output of leading or trailing spaces in image windows.

Syntax

print variable [to window] [{suppress [..., option]}]

What It Does

When an image is output to the output device, spaces are output where positions in windows are not occupied by printable characters. This preserves the layout of the image by maintaining the full defined width of every window. When suppress is on a format or print command line, it suppresses output of these spaces from the window(s) to which it is applied, shifting the remainder of image output including static image data leftward on lines containing such window(s). It strips trailing spaces from output through string type windows, and leading spaces from output through Numeric-type windows. It is the only format option that can alter the output of static image data.

format history.2 to history.5 {suppress}

In this example, trailing spaces will be stripped from output through the second through fifth windows in Image history, assuming the windows are of Type String.

print vendor.balance to form.3 {suppress, float$}

In this example, output through the third window in Image form will be stripped of leading spaces (assuming it is of Type Number), and the currency character will be placed at the beginning of the output.

Notes

  • An alternate way of applying suppress to a window is to replace one of the underscores in its definition with an at (@) character.

  • When suppress is applied to numeric windows, output from such windows will not be aligned vertically on the decimal point, as is commonly desired with columnar numeric output.

  • If a suppress option is used on an entry_item command line, it will have no effect, as it is intended only for use with the print and format commands.


Sysdate4

Obsolete

This command is replaced by the Sysdate command.

See Also

Purpose

To return the current system date, hour, minute, and second.

Syntax

sysdate4 {date} [{hour} [{minute} [{second}]]]

{minute} is allowed only if {hour} is used.

{second} is allowed only if {minute} is used.

What It Does

Sysdate4 retrieves the date and time from the operating system and moves the date to date. If an additional variable is provided, the hour is moved to that variable (hour). If two additional variables are provided, the minute is moved to the second additional variable (minute). If three additional variables are provided, the second is moved to the third additional variable (second).

Sysdate4 moves the date (with the year in four digits) to date as a Julian number, which can be interpreted correctly by date-type variables. The hour is moved to hours in 24-hour format. Date can be accommodated in variables of length ten, while hours, minutes and seconds can be accommodated in variables of length two each.

Example

date dToday

integer iHr iMin iSec

sysdate4 dToday iHr iMin iSec

In this example, if it is 1:36:18 PM on January 1, 2002, Visual DataFlex moves 01/01/2002 to dToday 13 to iHr, 36 to iMin, and 18 to iSec.

Notes

  • The sysdate command returns the date with the year in two digits.

  • The predefined variable Strlen is set to the value of hour and the predefined variable strmark is set to the value of minute.


System Command

Obsolete

This command is replaced by the Abort command.

See Also

Purpose

To terminate execution of the running DataFlex program, of DataFlex itself, and return execution to the operating system.

Syntax

system

What It Does

System closes any open database files and returns execution to the operating system.

system

To return to DataFlex after execution of a system command, it is necessary to execute FLEX or DFRUN from the operating system.

If the DataFlex program running was called from another DataFlex program by a chain wait command, system returns execution to the calling program, rather than to the operating system.

Notes

  • System is similar to abort, except that abort exits to the menu (if any) from which the program was executed, while system always exits directly to the operating system.

  • If you are running DataFlex under a batch file, system causes the next command in the batch file to execute, as any exit to and return from the operating system does.

  • Runprogram will pass execution from DataFlex to any other program named in the runprogram command present on the disk.

  • If the DataFlex program was called from another DataFlex program by a chain wait command, system returns execution to the calling program, rather than to the operating system.


Thousands Entry Option

Obsolete

Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To display the thousands separator in numeric data-entry items.

Syntax

set field_options field file.field to dd_thousands

or

entry_item file.field {thousands}

What It Does

Thousands causes numbers displayed in the item to show the thousands delimiter defined in the Configuration after every third digit of numbers greater than 999 (this defaults to the comma character in USA versions). When the cursor enters the item, this formatting disappears, but reappears when the cursor leaves the item.

Entry_Item account.balance {thousands}

In this example, values of Field balance in File account will be displayed with the thousands delimiter, as will entries to the item.

Notes

  • The delimiters occupy space in the item. Be aware that the size of an item may need to be increased to accommodate the additional characters.

  • If there is not enough room in the item to display the data and the delimiters, the delimiters will be omitted (data is favored).

  • Getting the value of an entry item will return the non-formatted version of the data. This is to ensure that any calculations that are performed on the data will proceed without error.

  • This entry option is not connected in any way with the embedded-comma print command option, although it performs a similar function. The two options may be used separately or together.


Total_Resources Global Variable

Obsolete

This variable is obsolete. This command is a legacy command intended for use in character-mode DataFlex.

This variable does not work on embedded resources like bitmaps, icons, and version information that is compiled into a Visual DataFlex application. See Resources for embedding these types of resources into your application.

See Also

Purpose

The number of resources in the current resource library.

Type

Integer

What It Does

Resources are binary or ASCII data embedded in DataFlex compiled files for use by programs. Each such resource is created either by a pseudo-image in the source code of the compiled program or by an include_resource command. The resource library of every DataFlex program is, by default, itself, although it can be changed to any other named compiled file.

(if(total_resources)) showln "We have resources."

Values should never be moved to total_resources.

Notes

  • In a resource library, resources are numbered sequentially from 1. Therefore, the value of total_resources is always equal to the ID of the highest-numbered resource.


Trim Command

Obsolete

This command is replaced by the Trim function.

See Also

Purpose

To remove leading and trailing spaces from a value and move the result to a variable.

Syntax

trim value to variable

What It Does

Trim removes leading and trailing blanks from the contents of value, and places it in variable. Blanks include spaces and any other characters (formfeed, linefeed, tab) designated in the Configuration as "white space." Trim does not remove spaces in value which are surrounded by non-space characters.

string long short

move " 4 leading, 3 trailing " to long

trim long to short

In this example, the value of string Variable long has four leading spaces and three trailing spaces. The value of short after the trim command would be 4 leading, 3 trailing, with no leading or trailing spaces.

When you move a value from a window to another variable, trailing spaces are automatically stripped. Thus, the statement:

trim account.3 to string_var

would make sense only where you had reason to believe account.3 contained leading spaces, and you wished them removed.

The same reasoning applies to moveing a value from another value to a window.

When you move a value from a field to another variable, trailing spaces are always included to the full specified length of the field. So where trailing spaces were not desired, the following command would be effective:

trim blessings.type to string_var

When you move a value to a field from another variable, use of trim would make sense only where you desired to strip leading spaces.

Notes

  • You may trim value back to itself, unless it is a constant. Doing so permanently changes value, while trimming to variable preserves value in its original form.

  • The suppress print format option removes trailing spaces from window output, while trim removes them from in memory variables.

  • The pad command adds trailing spaces to or removes them from the contents of variables to make them a specified total length.


Type

Obsolete

This command is obsolete. See the struct command for using structured types in Visual DataFlex.

See Also

Purpose

To declare a structure for use with DLL calls from Visual DataFlex programs.

Syntax

type TypeName

field FieldName as DataType

:

end_type

Argument Explanation

TypeName The name of the complex data type.

FieldName The name of a field. There can be as many fields in the Type declaration as you wish.

DataType Any Visual DataFlex representation of a 'C' data type.

What It Does

Type enables you to create a complex data structure in memory for use in passing parameters for DLL calls from Visual DataFlex programs.

type tv_item

field tv_item.mask as DWORD

field tv_item.hItem as HANDLE

field tv_item.state as DWORD

field tv_item.stateMask as DWORD

field tv_item.pszText as POINTER

end_type

In this example, Complex Data Structure tv_item is declared. In it, Fields tv_item.mask, tv_item.state, and tv_item.pszText are declared as DWORDs, tv_item.hItem is a HANDLE, and tv_item.pszText is a POINTER.

Note

  • If you declare a structure, the size of the structure is automatically stored in a symbol called <structname>_Size.


Uppercase Command

Obsolete

This command is replaced by the Uppercase function.

See Also

Purpose

To convert all lowercase letters in a value to uppercase and move them to a variable.

Syntax

uppercase value [to variable]

If to variable is not used and value is not a constant, value will be modified.

What It Does

Uppercase converts all lowercase letters in a string to uppercase.

string description

move "Southern California" to description

uppercase description

In this example, the value of String Variable description is changed to SOUTHERN CALIFORNIA.

uppercase last_name to form.3

In this example, any lowercase letters in the value of Variable last_name are converted to uppercase and moved to the third window of Image form. The value of last_name is not affected.

Notes

  • Uppercase produces all capital letters by converting lowercase letters to uppercase. Non alphabetic characters are not affected.

  • The capslock field property produces the same effect as uppercase in window contents.

  • Capitalization (what character is the uppercase of which other character, and vice versa) is set in the Character-Translation function of the Configuration.


Windowindex Predefined Variable

Obsolete

This command is obsolete. This command is valid only in character-mode DataFlex or BasicReport objects.

See Also

Purpose

To provide indexed addressing of a series of windows in an image.

Syntax

pagename.#&

The ampersand indicates that the window to be addressed is the window whose position in pagename is below that of pagename.# by the number of windows equal to the value of Predefined Variable windowindex.

What It Does

A series of windows in an image may be addressed by a single command in a loop in which the value of windowindex is controlled. The window which is addressed in each execution of the loop is determined by the value of windowindex as an offset from the window identified as pagename.#&. The ampersand (&) is literal and required.

Until it is used, the value of windowindex is 0. Thus, until some other value is moved to windowindex, pagename.#& is the same as pagename.# with no ampersand after it. If windowindex is 1, then pagename.#& refers to the next window after pagename.#. References to pagename.# (with no ampersand) are never affected by windowindex, regardless of its value.

There are two primary ways of using windowindex:

a. To select randomly from a range of windows. For example, windows in Image merchandise might relate through print commands to four fields in Database File merch in this way:

Window Field

merchandise.1 merch.recnum

merchandise.2 merch.retail_price

merchandise.3 merch.dealer_price

merchandise.4 merch.distrib_price

Records in the customer file, then, might have a terms field containing 1, 2, or 3, which determines which price (retail, dealer, or distributor) applies to each customer. The following would move the correct price to Variable cost:

move customer.terms to windowindex

move merchandise.1& to cost

b. To access a range of windows sequentially.

for windowindex from 0 to 11

calc (merchandise.8& *1.05) to merchandise.8&

loop

In this example, the contents of the eighth through 19th windows of Image merchandise are multiplied by 1.05.

Notes

  • Windowindex may be positive, for a downward offset from pagename.#&, or negative, for an upward offset.

  • If windowindex drives the window being addressed into the next, or the previous image, it will address windows in such images without triggering an error. This is a valid way of addressing windows in multiple images, so long as it is intended. If a value of windowindex is generated which addresses a nonexistent window (before the first window in the program, or after the last one), DataFlex Error 12, Window number out of range, will be generated.

  • If you have renamed a window with the name command, you may base windowindex ranges on such a window by its pagename.# or by its name, so long as you append the ampersand (&) to whatever you use.

  • The ampersand character cannot be a window number by itself; it must be appended to the actual number of a window in the image.

  • A similar variable which works on fields instead of windows is fieldindex.

  • You cannot address subtotal accumulators (see subtotal command) through windowindex.


Winput

Obsolete

This command is replaced by the Visual DataFlex Debugger.

Purpose

To accept a line of input from the keyboard and move it to a variable. For use only during program development; not to be included in finished applications.

Syntax

winput [prompt] variable [max_length]

If used, prompt must be enclosed in double (") or single (') quotation marks.

Max_length is the maximum allowed length of the input string.

What It Does

Winput stops execution of the program and activates a special-purpose dialog box at the top left of the screen. This box displays prompt if prompt was included in the command. When users press the OK button, winput moves the keyed in data to variable, deactivates the dialog box, and resumes execution of the program. If no data is input before the accelerator key is pressed, the value of variable, if a String, becomes null, and if a Number or Date, becomes zero. This command is suitable for use only during program development; it should not be used in finished applications.

Showln "Current object is" (name(self))

winput sTemp

Notes

  • If users enter data that doesn't match the data type of variable, DataFlex will declare an error after the dialog is closed. This would occur, for example, if you tried to input alphabetic letters into a Number type variable.


Zero_suppress Field Property/Print Option

Obsolete

This format option is obsolete. This format option is valid only in character-mode DataFlex. Refer to the Field_Options property in the DataDictionary class.

See Also

Purpose

To blank the display of numeric items and output windows having a value of zero instead of the default display of zero(es).

Syntax

set field_options field file.field to dd_zero_suppress

or

entry_item file.field {zero_suppress}

or

print window [zero_suppress]

What It Does

Zero_suppress causes the display of Number, Integer, and Real output windows to display the value of zero as spaces instead of the default of spaces followed by the last zero to the left of the decimal point and, for windows specified to display decimal values, the decimal point followed by a zero in each position to the right.

print image.3 {zero_suppress}

In this example, all values of zero printed through the third window of Image image would appear as blank space on the screen. The space specified by the definition of the window would be occupied by spaces.

An effect similar to that of zero_suppress can be attained by embedding the letter Z among the underscores of a Number type window.

Displays of zeroes can be suppressed at the field level by application of this field property in a DataDictionary object with the field_options property.

set field_options field transact.amount to dd_zero_suppress

This line would cause all entry items addressing Field amount in File transact in DEOs using the DataDictionary to display spaces instead of zeros whenever the field value was zero.

Notes

  • Zero_suppress will appear not to work where a small absolute value is put to a window. For example, if a window specifies integer-only display (say, _____.) and a value less than 1 is put to it (say, 0.5), a zero will display in the window. Only a value that is truly zero (such as 5 -5) will be displayed as blanks.


ZeroType

Obsolete

This command is obsolete. See the struct command for using structured types in Visual DataFlex.

See Also

Purpose

To create a string to represent an instance of a structure type and initialize each byte of the string to character zero.

Syntax

ZeroType (type-identifier} to {string-identifier)

Where {type-identifier} represents an instance of a structure type and {string-identifier} represents a string variable.

What It Does

Creates a string to represent an instance of a structure type. Each byte of the string is then initialized to character zero. The type represented by the {type-identifier} argument must be an existing Type created with the Type...End_Type commands.

Example

String sRect

ZeroType tRect To sRect

This example creates a string, sRect, which is the size of the tRect type and initializes each byte sRect to character zero.


Language Reference

The Visual DataFlex Language Reference is a comprehensive alphabetic reference to the commands, functions, and keywords of Visual DataFlex. Each subject is treated in depth, with illustrative examples of how they are used.

The Language Reference is not, however, a standalone guide to Visual DataFlex. Before you use the Language Reference you should already be familiar with the concepts presented in the Visual DataFlex Language Guide and have a foundation of knowledge of Visual DataFlex programs, how to use the Studio, and the basics of database file design and management. This information is presented in other documentation supplied with Visual DataFlex.

Although the Language Reference is not designed to be a learning vehicle, it can rapidly and efficiently extend your knowledge of the Visual DataFlex language once you have mastered the basics. Each article, for example, has a section entitled "See Also" in which other articles on related subjects are identified. Similarly, the heading of each article on a command or function identifies the group of similar commands or functions of which it is a member.

Conventions

Special typefaces and symbols are used when describing the syntax of the Visual DataFlex programming language in this guide. These symbols are described in the following table.

Typeface or symbol | Meaning
Monospace type | Monospaced text is used to represent programming code and code elements as it must be typed. It is also used for all the following symbols.
[] | Square brackets are used to enclose optional syntax. You should not type square brackets verbatim.
{identifier} | Text within {} braces represents Visual DataFlex identifiers such as variable names, object names, or method names.
| | Where an element is one of several mutually exclusive choices, the choices are separated from each other by a vertical bar (|).

All other punctuation, is literal, and must be typed, if used, in statements.


SeeAlso.4

Related Commands

Define


SeeAlso.12

See Also

Append Function

Character Command

Left Command

Mid Command

Pad Command

Right Command

String Command

Trim Command


SeeAlso.15

See Also

Ascii Function

Character Command


SeeAlso.20

See Also

Autoreturn Field Property


SeeAlso.21

See Also

Autofind_ge Field Property

Entry_item Command

Eq Comparison/Find Mode

Find Command


SeeAlso.22

See Also

Autofind Field Property

Find Command

Ge Comparison/Find Mode


SeeAlso.23

See Also

Name Command

Print Command


SeeAlso.24

See Also

Autoback Field Property

Entry_item Command


SeeAlso.26

See Also

Constrain Command

End_constraints Command


SeeAlso.31

See Also

Move Command

MoveNum Command


SeeAlso.34

See Also

Entry_item Command

Format Command

Uppercase Command


SeeAlso.38

Related Commands

Cmdline

Runprogram


SeeAlso.40

See Also

Ascii Command

Ascii Function

Character Function


SeeAlso.47

Related Commands

Chain


SeeAlso.73

See Also

End_item_group Command

Item_group Command

Name_item Command


SeeAlso.74

See Also

Direct_Output


SeeAlso.154

See Also

Direct_input Command

Seqeof Predefined Indicator


SeeAlso.155

See Also

Entry_item Command

Noenter Field Property

Noput Field Property


SeeAlso.159

See Also

Begin_constraints Command

Constrain Command


SeeAlso.162

See Also

Dependent_item Command

Item_group Command


SeeAlso.163

See Also

Item_list Command

On_item Command


SeeAlso.168

See Also

Entry_item Command


SeeAlso.170

See Also

Find Command

If Command

Indicate Command


SeeAlso.176

See Also

Err Predefined Indicator

Error Command

Error_object_id Predefined Variable

Error_type Predefined Variable

Lasterr Predefined Variable

On Error Command


SeeAlso.182

See Also

External_Function Command


SeeAlso.183

Related Commands

End_Type

External_Function

GetBuff

Put

Type

Related Topics

Structured Types


SeeAlso.184

See Also

Filenumber Predefined Variable

Movestr Command

Windowindex Predefined Variable

get_Field_Value Command

get_Attribute command


SeeAlso.185

Related Commands

Get_Directory

Make_Directory

Make_Temp_File

Remove_Directory

Valid_Drive


SeeAlso.186

See Also

Fieldindex Predefined Variable


SeeAlso.187

See Also

Format Command

Print Command


SeeAlso.189

See Also

Constrained_find Command

Constraint_validate Command

Find Command

Found Predefined Indicator

Open Command

Pos Command

Replace Command


SeeAlso.190

See Also

Autofind Field Property

Entry_item Command


SeeAlso.191

See Also

Format Command

Print Command


SeeAlso.193

See Also

Entry_item Command


SeeAlso.194

See Also

Direct_output Command

Linecount Predefined Variable


SeeAlso.196

See Also

Class Command

Forward_end_construct Command

Object Command


SeeAlso.197

See Also

Class Command

End_object Command

Forward_begin_construct Command

Object Command


SeeAlso.201

See Also

Find Command

If Command

Indicate Command

Until Command

While Command


SeeAlso.211

See Also

Set_cursor_visible Command


SeeAlso.213

See Also

Set_default_map_mode Command


SeeAlso.215

Related Commands

Direct_Input

Get_Current_Directory

Runprogram


SeeAlso.220

See Also

Set_filelist Command


SeeAlso.221

Related Commands

Get_Profile_String

Set_Foreign_Profile_String

Set_Profile_String

Set_Registry_Root


SeeAlso.222

Related Commands

Get_Foreign_Profile_String

Set_Foreign_Profile_String

Set_Profile_String

Set_Registry_Root


SeeAlso.223

Related Commands

Get_Profile_String


SeeAlso.224

Related Commands

Get_Foreign_Profile_String

Get_Profile_String

Set_Foreign_Profile_String

Set_Profile_String

Set_Registry_Root


SeeAlso.227

Related Commands

Getbuff

Field

Put_String

Type

End_Type


SeeAlso.228

See Also

Goto Command

On Error Command

On ... Gosub Command

Gosub_Return Command


SeeAlso.230

See Also

Indicate Command

Indicator Command


SeeAlso.231

See Also

Find Command

If Command

Indicate Command

Until Command

While Command


SeeAlso.236

See Also

Save Command

Saverecord Command

Status Command Component


SeeAlso.240

See Also

Direct_Input

Get_Resource_Name

Register_Resource


SeeAlso.242

See Also

Indicate Command

Indicator Command


SeeAlso.244

See Also

Group Command Component

If Command

Indicator Command

Integer Command

Integer Function


SeeAlso.245

See Also

If Command

Ind Command

Indicate Command


SeeAlso.246

See Also

Append Command

Left Command

Mid Command

String Command

Strmark Predefined Variable


SeeAlso.251

See Also

Dependent_item Command

End_item_group Command


SeeAlso.252

See Also

End_item_list Command

Entry_item Command

Name_item Command

On_item Command


SeeAlso.253

See Also

Err Predefined Indicator

Error Command

If Command

Error_object_id Predefined Variable

Error_type Predefined Variable


SeeAlso.254

See Also

Find Command

If Command

Indicate Command

Until Command

While Command


SeeAlso.255

See Also

Insert Command

Mid Command

Pos Command

Right Command

String Command

Strmark Predefined Variable


SeeAlso.257

See Also

Length Function

Strlen Predefined Variable

Trim Command


SeeAlso.262

See Also

Date Command

Function Command

Get Command

Integer Command

Number Command

Procedure Command

Real Command

String Command

Use Command


SeeAlso.270

See Also

Find Command

If Command

Indicate Command

Until Command

While Command


SeeAlso.278

See Also

Insert Command

Pos Command

Replace Command

String Command

Strlen Predefined Variable

Strmark Predefined Variable


SeeAlso.283

See Also

Date Function

Move Command

Moveint Command

Movenum Command

Movereal Command

Movestr Command


SeeAlso.284

See Also

Integer Function

Move Command

Movedate Command

Movenum Command

Movereal Command

Movestr Command


SeeAlso.285

See Also

Calc, Calculate Command

Move Command

Movedate Command

Moveint Command

Movereal Command

Movestr Command

Number Function


SeeAlso.286

See Also

Move Command

Movedate Command

Moveint Command

Movenum Command

Real Function


SeeAlso.287

See Also

Move Command

Movedate Command

Moveint Command

Movenum Command

Movereal Command

String Function


SeeAlso.288

See Also

Autopage Command

Windowindex Predefined Variable


SeeAlso.289

See Also

Name_object Command


SeeAlso.290

See Also

Entry_name_item Command

On_name_item Command


SeeAlso.291

See Also

Name_item Command

Register_function Command

Register_object Command


SeeAlso.292

See Also

If Command

Indicate Command

Until Command

While Command


SeeAlso.293

See Also

Displayonly Field Property

Entry_item Command

Noenter Field Property

Noput Field Property

Skipfound Field Property


SeeAlso.294

See Also

Entry_item Command

Noenter Field Property


SeeAlso.302

See Also

Gosub Command

On ... Goto Command

Return Command


SeeAlso.303

See Also

Goto Command

On ... Gosub Command


SeeAlso.304

See Also

Begin Command

Err Predefined Indicator

Errline Predefined Variable

Error Command

Error_object_id Predefined Variable

Error_report Command

Error_type Predefined Variable

Gosub Command

Indicate Command

Lasterr Predefined Variable

Return Command


SeeAlso.307

See Also

Entry_name_item Command

On_item Command


SeeAlso.314

See Also

Append Command

Left Command

Pos Command

Right Command

Strmark Predefined Variable

Trim Command


SeeAlso.316

See Also

Entry_item Command

Format Command

Number Command

Print Command


SeeAlso.317

See Also

Found Predefined Indicator

Mid Command

Right Command

Strmark Predefined Variable


SeeAlso.324

Related Commands

Field

Getbuff

Put_String

Type


SeeAlso.325

Related Commands

Field

Getbuff_String

Put

Type


SeeAlso.329

See Also

On_key Command


SeeAlso.346

See Also

Item_list Command

On_item Command


SeeAlso.347

See Also

Found Predefined Indicator

Insert Command

Pos Command

Replace Function

String Function

Strmark Predefined Variable


SeeAlso.350

See Also

Entry_item Command

Findreq Field Property


SeeAlso.352

See Also

Direct_input Command

Get_resource_name Command


SeeAlso.353

See Also

Entry_item Command

Retainall Field Property


SeeAlso.354

See Also

Entry_item Command

Get_resource_name Command

Retain Field Property


SeeAlso.356

See Also

Left Command

Pos Command

Right Function

Strlen Predefined Variable


SeeAlso.371

See Also

Get_cursor_visible Command


SeeAlso.373

See Also

Get_default_map_mode Command


SeeAlso.374

See Also

DF_OPEN_PATH Attribute

Get_attribute Command

Get_environment Command

Open Command

Runprogram Command


SeeAlso.377

See Also

Close Command

Get_filelist Command

Open Command


SeeAlso.378

Related Commands

Get_Foreign_Profile_String

Get_Profile_String

Set_Profile_String

Set_Registry_Root


SeeAlso.379

Related Commands

Get_Foreign_Profile_String

Get_Profile_String

Set_Foreign_Profile_String

Set_Registry_Root


SeeAlso.380

Related Commands

Get_Foreign_Profile_String

Get_Profile_String

Get_Program_Key

Set_Foreign_Profile_String

Set_Profile_String


SeeAlso.382

See Also

Direct_Input

Get_Resource_Name

Include_Resource

Total_Resources


SeeAlso.386

See Also

Format Command

Print Command

Subtotal Command


SeeAlso.389

See Also

Entry_item Command

Found Predefined Indicator

Noenter Field Property


SeeAlso.392

See Also

Clear Command

Find Command

Found Predefined Indicator

If Command

Indicate Command

Relate Command


SeeAlso.395

See Also

Mid Command

Pos Command

Right Command

Strmark Predefined Variable

Sysdate Command


SeeAlso.396

See Also

Insert Command

Left Command

Mid Command

Pad Command

Pos Command

Replace Command

Strlen Predefined Variable

Sysdate Command


SeeAlso.403

See Also

Format Command

Output Command

Print Command


SeeAlso.405

See Also

Set_date_attribute Command

Sleep Command

Strlen Predefined Variable

Strmark Predefined Variable

Sysdate Command


SeeAlso.406

See Also

Abort Command

Chain Command

Runprogram Command


SeeAlso.408

See Also

Entry_item Command

Print Command


SeeAlso.409

See also

Get_Resource_Name

Include_Resource

Set_Resource_Library


SeeAlso.410

See Also

Pad Command

Suppress Print Format Option

Trim Command


SeeAlso.412

Related Commands

Field Command

Put Command

End_Type

Related Topics

Structured Types


SeeAlso.416

See Also

Capslock Format/Field Property

Uppercase Function


SeeAlso.424

See Also

Fieldindex Predefined Variable

Subtotal Command


SeeAlso.429

See Also

Fill= Print Format Option


SeeAlso.447

Related Commands

Contains Operator

If Command

Indicate Command

Until Command

While Command


SeeAlso.450

Related Commands

AddressOf

Type

End_Type

External_Function

Field

GetBuff

Put


SeeAlso.451

Related Commands

Getbuff_String

Field

Put_String

Type

End_Type


SeeAlso.463

Related Topics

Type command

Put command

Field command

End_Type command


SeeAlso.468

Related Topics

Define Command

#IFDEF


SeeAlso.475

Related Commands

if command

if function

not function

until

while