Developing DDE Applications in DynaComm(R)

Julianne Sharer

Julianne Sharer is the Director of Application Development for WexTech Systems, Inc., a consulting and training firm specializing in applications for the MicrosoftÒ WindowsÔ and AppleÒ MacintoshÒ environments.

Microsoft Corporation does not make any representation or warranty, express or implied, with respect to any information herein. Microsoft makes no warranty, implied or otherwise, regarding the performance or reliability of products manufactured by vendors independent of Microsoft.

Created: March 30, 1992

ABSTRACT

DynaCommÒ is a communications package that allows you to build dynamic data exchange (DDE) applications. An application developed in DynaComm can be a DDE client or a DDE server, or can act as both client and server simultaneously. This article describes the DynaComm programming environment and explains how to create DDE client and server scripts. It also discusses the limitations of DynaComm’s DDE implementation, explains workarounds for problems, and includes a summary of DynaComm’s DDE commands and functions.

INTRODUCTION

DynaComm is a feature-rich communications package from Future Soft Engineering, Inc., which includes an extensive implementation of dynamic data exchange (DDE). A DynaComm program (called a script) can act as a DDE client, a server, or both. An unlimited number of DDE conversations can take place at one time. DynaComm’s capabilities as a server are particularly robust; you can trap DDE messages from the client and write custom routines to respond to particular events. Among DynaComm’s enhancements to the standard arsenal of DDE commands and functions is its use of tables to send and receive data. A table is a two-dimensional array variable whose structure can be defined by the programmer.

DynaComm’s DDE implementation exists on a somewhat lower level than the DDE implementation in applications like MicrosoftÒ Excel and Word for WindowsÔ. For example:

DynaComm won’t present the user with different options upon failing to initiate a DDE conversation unless you write a routine to offer options.

The SYSTEM topic is not implemented in the standard fashion; it acknowledges the DDE INITIATE and TERMINATE messages, but its functionality ends there.

If you want DynaComm to act as a server, you’ll have to write a server script to handle requests from the client application.

You’re more likely to run into compatibility glitches and other quirks with DynaComm than with other packages.

So the trade-off for DynaComm’s flexibility and power is a longer and possibly more troublesome path to completion.

THE PROGRAMMING ENVIRONMENT

A DynaComm script must be compiled into a task file using the built-in compiler before it can be executed. DynaComm also includes a simple text editor to speed the cycle of compiling, testing, and debugging. A text file with the default extension DCP (DynaComm Program) contains the source code for a script and resides in a DCP subdirectory under the DynaComm directory.

You can open an existing script by choosing Open from the File menu and then clicking the Script option button (Figure 1). DynaComm automatically switches to the DCP directory and displays files with the DCP extension. Several script files can be open simultaneously, but you don’t have to open a script file to compile it.

Figure 1. Opening a Script File

To compile a script, choose the Compile command from the Script menu. A dialog box appears to let you select the name and the location of the script you want to compile (Figure 2).

Figure 2. Selecting a Script to Compile

If you have an open script file, its name automatically appears as the default in the Filename box. Compiling a lengthy script can take a long time, but it can take place in the background while you work on another file or even in another application. The compiler creates a binary task file with the same file name and location as the source file, but with a DCT extension (Figure 3). DynaComm lets you execute the task file immediately after a successful compilation.

Figure 3. Compiling a Script

THE SCRIPT LANGUAGE

The DDE implementation is only one part of DynaComm’s powerful script language, which affords complete control over communications and data transfer. The features of this language include:

Customization of menus and function keys and incorporation of dynamic dialog boxes with bitmapped graphics and buttons.

Support for string, integer, real, and Boolean data types.

Structured data tables with programmer-defined dimensions and data types. Tables can be used to transmit and receive data through DDE.

Procedural program structure with parameter passing, calls to external scripts or to procedures within external scripts, and calls to Windows libraries and to other dynamic link libraries (DLLs).

Extensive event handling. You can trap for errors on three levels. You can also trap for incoming DDE messages and for events such as connect, disconnect, modification of a screen area, transmission or receipt of a particular character string through the communications port, and receipt of Windows messages by the DynaComm parent window or by any child window.

DYNACOMM AS A CLIENT

The following script illustrates the use of DynaComm’s DDE commands. In this case, DynaComm is the client, and Microsoft Excel is the server. As the client, the DynaComm script must initiate the DDE conversation, send the appropriate DDE messages, and process the replies from the server. The commands used to perform these actions are similar to DDE scripts in other applications. We will discuss the minor differences in syntax and functionality as we examine the code.

DynaComm’s implementation of the standard DDE command set is complete except for the omission of the ADVISE command. Although DynaComm can be programmed to service an ADVISE from another application, it doesn’t support ADVISE in the client mode.

For descriptions of DynaComm’s DDE commands, see “DDE Commands and Functions,” later in this article.

What the Script Does

This script initiates and conducts a conversation with a Microsoft Excel worksheet called DDETEST.XLS. It sends data to a cell in the worksheet, formats a range of cells, and displays a formatted total in the terminal window. The terminal window displays the output of a communications session. Several script files can be open simultaneously, but only one terminal window can be open at one time.

There are three DDE messages at the core of this script: POKE, EXECUTE, and REQUEST. POKE sends the character string to a named range in the worksheet. Two EXECUTE commands then instruct Microsoft Excel to go to a specified range and format the numbers in that range with a monetary number format. Finally, the script REQUESTs the contents of a cell and displays the result in the terminal window.

Figure 4. Executing the Script

The successful execution of the script depends on the following conditions:

Microsoft Excel must either be running or must reside in a directory on the MS DOSÒ path.

The DDETEST.XLS worksheet must either be loaded or must reside in the directory to which Microsoft Excel is currently logged. DDETEST.XLS contains the names Salaries, Materials, Depreciation, and Total_Expenses.

The DDETEST.DCS settings file must be available in the DynaComm DCS directory.

Note:

Settings files are special DynaComm files containing settings for communications, terminal emulation, and other options. By default, they are stored in the DCS subdirectory under the DynaComm directory.

The full script is shown in the following code. The characters following a semicolon on a line are comments.

$depreciation = "1498.87" ;string variable to be poked into Excel

%channel = 0 ;integer variable to hold DDE channel

$expenses = "" ;string variable to hold a value from Excel

;Initiate DDE conversation with Excel to be sure it's loaded.

Access "excel" "system" %channel

;If DDE conversation didn't initiate, %channel = 0.

If %channel < 1 Perform LaunchExcel

Access Cancel %channel

Access "excel" "ddetest.xls" %channel

If %channel < 1 Perform LoadSheet

;Set the cell named Depreciation equal to the $Depreciation

;variable.

;Excel interprets the character string as if the user typed it in.

Poke $Depreciation To %channel "depreciation"

;Select the Figures cell range...

Instruct %channel '[formula.goto("figures")]'

;And format it.

Instruct %channel '[format.number("$#,##0.00_);($#,##0.00)")]'

;Assign the value of Excel's Total_Expenses cell to $Expenses.

Request $Expenses From %channel "Total_Expenses"

Access Cancel %channel

;Clear the terminal window and display the total expenses.

;Open a blank terminal window.

Window Open Settings "ddetest.dcs"

Clear

Display "Total expenses are: " | $expenses

Return

*LaunchExcel

When Error 3 Perform GiveUp

Launch "excel.exe"

Access "excel" "System" %channel

If %channel < 1 Perform GiveUp

;Disable errortrap, because Access Cancel can generate erroneous

;errors.

When Cancel Error 3

Return

*LoadSheet

When Error 3 Perform GiveUp

Access "excel" "system" %channel

Instruct %channel '[open("ddetest.xls")]'

;Disable errortrap, because Access Cancel can generate erroneous

;errors.

When Cancel Error 3

Access Cancel %channel

Access "excel" "ddetest.xls" %channel

If %channel < 1 Perform GiveUp

Return

*GiveUp

Dialog

Message "An execution error occurred."

Message "Please be sure Excel is running"

Message "and the DDETEST.XLS worksheet is loaded."

;The button performs 2 commands:

;Dialog Cancel clears the dialog box, and

;Cancel stops program execution completely.

Button Default "OK" Dialog Cancel,

Cancel

Dialog End

Wait Resume

Excel? Are You With Me?

The first three lines:

$Depreciation = "1498.87"

%channel = 0

$Expenses = ""

initialize the $Depreciation, %channel, and $Expenses memory variables. Memory variables are always preceded by a character indicating the data type:

The dollar sign ($) precedes a string variable.

The percent sign (%) precedes an integer variable.

The exclamation point (!) precedes a real variable (also called a floating-point variable).

The pound sign (#) precedes a Boolean variable.

The command:

Access "excel" "ddetest.xls" %channel

initiates a DDE conversation with Microsoft Excel, using SYSTEM as the topic, and assigns the DDE channel to the %channel variable. If DynaComm doesn’t receive a response to the DDE INITIATE message, %channel is set to 0. If it receives a response but is unable to initialize the conversation for any reason, %channel is set to –1. We can check the value of %channel with the following command:

If %channel < 1 Perform LaunchExcel

The command Perform LaunchExcel at the end of the line is the command argument to the If command. Conditional branching and event-trapping commands such as If, While, and When Error require a command argument to determine how the script will respond to the specified condition.

If the %channel variable is less than 1, Microsoft Excel is assumed not to be running, and execution branches to the target labeled LaunchExcel. A target is a location in a script marked by an asterisk (*) followed by the target name. Although DynaComm has no command to explicitly declare a subroutine, targets can be used as subroutines. DynaComm keeps track of its previous location when it executes the Perform command and comes back to that location if it encounters a Return command in the subroutine. The LaunchExcel subroutine contains the statements:

*LaunchExcel

When Error 3 Perform GiveUp

Launch "excel.exe"

Access "excel" "System" %channel

If %channel < 1 Perform GiveUp

When Cancel Error 3

Return

The When Error command tells DynaComm to perform the GiveUp subroutine if it encounters an error. Internal run-time errors are assigned error levels of 1, 2, or 3. An error level of 1 is fatal, and 3 is the least severe.1 The argument 3 after the When Error command means that an error level of 3 is sufficient to trigger the error trap. Level-1 errors and level-2 errors would also trigger the error trap because they are more severe than level-3 errors.

The Launch command attempts to start Microsoft Excel, and the Access command on the next line attempts for the second time to initiate a DDE conversation with Microsoft Excel. If either of these commands fails, execution branches to the GiveUp subroutine.

*GiveUp

Dialog

Message "An execution error occurred."

Message "Please be sure Excel is running"

Message "and the DDETEST.XLS worksheet is loaded."

Button Default "OK" Dialog Cancel,

Cancel

Dialog End

Wait Resume

GiveUp displays an error message in a dialog box and waits for the user to click OK. Dialog boxes in DynaComm scripts, unlike those in most programming environments, do not automatically suspend program execution. To pause the script, we need the Wait Resume command after the dialog box.

Note also that the ubiquitous OK button doesn’t have any default action assigned to it. Any actions the button performs must be explicitly stated on the Button command line. You can use a command block in place of a single command if the command takes an argument. Command blocks consist of a series of command lines. To define a command block, you may either separate its component command lines with commas or delimit the entire command block with a Begin command and an End command. In this example, a comma is used to separate the Dialog Cancel and Cancel commands. The Dialog Cancel command clears the dialog box from the screen and resumes program execution, and the Cancel command stops program execution on all levels.

The DEFAULT keyword causes the button to be activated by pressing ENTER.

A Topic of General Interest

Having successfully initiated the DDE conversation with Microsoft Excel, we can sleep peacefully knowing that Microsoft Excel is loaded. But the topic of interest to this script is not SYSTEM but the DDETEST.XLS worksheet. Going back to the top of the script, the command:

Access Cancel %channel

terminates the conversation taking place on the specified channel, and the command:

Access "excel" "ddetest.xls" %channel

begins a new conversation, this time with DDETEST.XLS as the topic. Again, we have to test for a failure using the line:

If %channel < 1 Perform LoadSheet

which, in this case, performs the LoadSheet subroutine if the DDE INITIATE message fails. The assumption is that Microsoft Excel is running, but the worksheet is not loaded.

Note:

A bug in the current version of DynaComm produces a run-time error when Access Cancel is executed. Therefore, we disabled the error trap after successfully initiating a conversation with Microsoft Excel in the LaunchExcel and LoadSheet subroutines.

The LoadSheet subroutine initiates a conversation with Microsoft Excel again and attempts to open the worksheet using the Instruct command.

*LoadSheet

When Error 3 Perform GiveUp

Access "excel" "system" %channel

Instruct %channel '[open("ddetest.xls")]'

When Cancel Error 3

Access Cancel %channel

Access "excel" "ddetest.xls" %channel

If %channel < 1 Perform GiveUp

Return

The Instruct command issues a DDE EXECUTE message. The command string to be executed is delimited by square brackets, as required by Microsoft Excel.

Let the Games Begin

The first thing our script does after initiating the DDE conversation is to poke the value of the $Depreciation variable into the corresponding cell in the Microsoft Excel worksheet.

Poke $Depreciation To %channel "depreciation"

We’re sending the data to Microsoft Excel in the form of a text string, but because Microsoft Excel interprets it as though it were typed in by the user, it becomes a numeric value in the worksheet.

Next, we use a pair of Instruct commands:

Instruct %channel '[formula.goto("figures")]'

Instruct %channel '[format.number("$#,##0.00_);($#,##0.00)")]'

to go to the Figures range in the worksheet and format the numbers in that range using dollar signs, commas, and two decimal places.2

The Request command:

Request $Expenses From %channel "Total_Expenses"

takes the calculated value from the worksheet’s Total_Expenses range, which is the item in this DDE transaction, and assigns it to the $Expenses string variable. The conversation is terminated with an Access Cancel command.

The last lines of code open the DDETEST.DCS settings file, clear the terminal window, and display a message showing the data requested from Microsoft Excel:

Window Open Settings "ddetest.dcs"

Clear

Display "Total expenses are: " | $expenses

Return

The DynaComm Script Reference included in the DynaComm Asynchronous Edition 3.00.18 documentation describes a function called WindowHnd, which can be used to determine the handle of the terminal window, followed by a Window Activate command to bring the window into focus. However, the WindowHnd function is implemented only in the DynaComm/EliteÔ Edition, so you must open the DDETEST.DCS settings file to bring the terminal window into focus.

The vertical bar (|) in the Display command is the concatenation operator used to join two text strings. Because the procedure currently being executed is at the highest level—that is, it was not called by a Perform command—the Return command stops program execution.

DYNACOMM AS A SERVER

To use DynaComm as a DDE server, you must write a script to handle incoming requests. Unlike most DDE-aware applications, DynaComm doesn’t have predefined topics, items, or supported EXECUTE strings; the programmer must define these. In addition, the server script must be structured to process DDE messages as they come in. Fortunately, DynaComm’s script language allows you to build a capable and remarkably flexible DDE server application.

Topics, Items, and EXECUTE Strings

In server mode, DynaComm supports two kinds of topics: the name of a script and SYSTEM. The SYSTEM topic tests whether DynaComm is loaded; it doesn’t do anything else. If you initiate a DDE conversation with DynaComm as the server and a script name as the topic, DynaComm loads and executes the script. DynaComm refuses to initiate a DDE conversation with a script topic if another script is currently running and is not paused at a Wait Resume command.

You must explicitly declare the items that a client application can access with the DDE POKE, REQUEST, and ADVISE messages. DynaComm provides three event-trapping commands for this purpose: When Poke, When Request, and When Advise. You can declare up to 16 items at a time for each service. The item names need not be the same. For example, you can set up a server script to accept DDE POKE messages to the items “North”, “South”, and “East”, and to reply to DDE REQUEST messages for the items “Red”, “Green”, and “Blue”. In this case, a DDE REQUEST from a client for the item “South” would be refused.

EXECUTE strings must be supported explicitly by the script code. Any number of EXECUTE strings can be supported simultaneously. A single When Execute command traps and acknowledges an incoming DDE EXECUTE message, stores the EXECUTE string in a memory variable, and, at the programmer’s option, branches execution to a subroutine to handle multiple EXECUTE strings.

Serving the Public

The following script operates as a DDE server. The actions it performs are not client-specific; we’ll be using Microsoft Excel and Word for Windows macros to demonstrate the script’s capabilities. This script, like the previous client script, deals with the DDE POKE, REQUEST, and EXECUTE services.

The structure of a dedicated server script usually resembles this example. The main procedure sets up traps and supporting memory variables for the DDE services it will provide and then waits in an infinite loop until an event trap is triggered. At that point, program execution branches to the appropriate routine and then returns to the main loop for the next event trap trigger. The program exits when it receives a DDE TERMINATE message from the client. The syntax for DDE event-handling commands is not obvious; we will discuss each command in detail. The sample script provides three services:

1.It responds to a DDE REQUEST for the “BaudRate” item by checking the current baud setting, placing its value in Table 0, and sending Table 0 to the client as a DDE DATA message.

2.It accepts a DDE POKE to the “WordString” item and places its value in Table 1.

3.It displays the contents of Table 1 in the terminal window when it receives a DDE EXECUTE message with the “DisplayPoke” command string.

Table Define 0 Fields Char 5 ;holds the baud rate for DDE REQUEST

Table Define 1 Fields Char 50 ;holds a poked string from WinWord

;Execute the Reply procedure on DDE REQUEST.

When Request 0 "BaudRate" Perform Reply("BaudRate")

;On DDE POKE to item "WordString", place the value in Table 1.

When Poke 0 Table 1 "WordString" Perform AcceptPoke

;On DDE EXECUTE, store the command string to $DDE_Exec

;and pass control to the ServiceDDE procedure.

When Execute $DDE_Exec Perform ServiceDDE

;Stop script execution on DDE TERMINATE.

When Terminate Cancel

;The following line forms an infinite loop.

While True Wait Signal

*Reply($ItemName)

If $ItemName = "BaudRate",

Begin

;Store the current baud rate setting to record buffer

;for Table 0.

@R0 = Settings(BaudRate)

;Write contents of record buffer to Table 0.

Record Write 0

;Send Table 0 in response to request for item "BaudRate".

Table Reply 0 To "BaudRate"

End

return

;Dummy procedure for DDE POKE.

*AcceptPoke

Return

*ServiceDDE

if $DDE_Exec = "DisplayPoke",

Begin

Clear

Record Read 1

Window Restore

Display @R1 | Chr(13)

End

Return

Introducing Tables

DynaComm’s DDE commands that transmit and receive data in the server mode use structured tables as the “in” and “out” boxes for these transactions.3 DynaComm also supports text tables, which store unstructured data as lines of text, but DDE operations require the use of structured tables. In this article, we will use the term table to refer to structured tables.

Structured tables are two-dimensional array variables. This means that they contain multiple values arranged logically in rows and columns. When you perform DDE transactions with tables, you can transmit an entire block of data, consisting of several rows and columns, in a single transaction. For this reason, tables are ideal for DDE transactions with spreadsheets.

In this example, however, we’ll keep things simple. The first two lines:

Table Define 0 Fields Char 5

Table Define 1 Fields Char 50

define the dimensions and the data types for two structured tables. In the first line, the argument 0 after the Table Define command means that we are defining the structure of Table 0. DynaComm allows 16 tables, numbered 0 through 15. Tables are always referenced by number.

The fields clause specifies the data type and length of each field. Table 0 has only one field whose data type is character (indicated by the keyword Char) and whose length is five. There are three data types:

Character (keyword Char)

Integer (keyword Int)

Real (keyword Real)

You can create multifield tables by adding field definitions separated by commas, as follows:

Table Define 0 Fields Char 5, Int 7, Char 35, Real 9

Setting the Traps

The four commands following the table definitions are event-handling (or event-trapping) commands. These commands always begin with When followed by the event type. Other arguments vary from one event-handling command to another. The When commands do not suspend execution; they simply prepare DynaComm to respond to a particular event at whatever time the event may occur. The first of these commands:

When Request 0 "BaudRate" Perform Reply("BaudRate")

directs the program flow to the Reply subroutine when a DDE REQUEST comes in for the “BaudRate” item. As many as 16 When Request commands, numbered 0 through 15, can be active at one time. The argument 0 after the When Request command is an index that assigns this command to the first slot. Event-handling commands that use an index argument can be individually reassigned or disabled using the When Cancel command. The Perform Reply("BaudRate") argument at the end of the command line branches to the Reply subroutine and passes it the "BaudRate" parameter.

The next event trap:

When Poke 0 Table 1 "WordString" Perform AcceptPoke

receives an incoming DDE POKE with the “WordString” item. The item value is placed in Table 1, and execution branches to the AcceptPoke subroutine. In this particular case, we don’t need to perform any action on the POKE item except to store its value in Table 1. Therefore, AcceptPoke is a “dummy” procedure consisting of a target label and a Return command.

The following command line:

When Execute $DDE_Exec Perform ServiceDDE

builds support for DDE EXECUTE requests into our server. DynaComm stores the EXECUTE string in the $DDE_Exec string variable and passes control to the ServiceDDE subroutine.

Note:

The only way to make your application accept certain EXECUTE strings and refuse others is to write a low-level message-trapping routine.

Finally:

When Terminate Cancel

stops program execution on all levels when it receives a DDE TERMINATE message.

These four commands set the traps for the DDE messages this script supports. At this point, we want our server to wait with infinite patience until it receives a request from a client application. The following line suits the task nicely:

While True Wait Signal

The While command performs a conditional loop. By supplying the Boolean constant TRUE as the condition, we form an infinite loop. The Wait Signal command argument suspends program execution until a DDE message comes in.

Filling the Orders

The first subroutine, Reply, responds to a DDE REQUEST, as established earlier by the When Request command. The target label for the Reply subroutine specifies that a character argument can be passed to the subroutine. Its value is assigned to the $ItemName string variable:

*Reply($ItemName)

If $ItemName = "BaudRate",

Begin

@R0 = Settings(BaudRate)

Record Write 0

Table Reply 0 To "BaudRate"

End

return

The If command tests the value of $ItemName. In this particular case, only one item name can trigger this routine. In general, however, the routine should be able to handle a REQUEST for any item we plan to support. The subroutine also includes an example of a command block delimited by the Begin and End commands. For command blocks longer than a few lines, the Begin and End commands are more practical and readable than the comma separator discussed earlier.

The line:

@R0 = Settings(BaudRate)

uses the Settings function to test the baud rate in DynaComm’s current configuration and assigns that value to the record buffer for Table 0. You cannot read from or write to tables directly. All read and write operations must take place through the record buffer, which is a special variable that holds one table record at a time. Record buffers are identified by the “at” sign (@) followed by an ‘R’ and the number of the defined table. A particular field in the record buffer can be referenced by appending a period (.) followed by the number of the field. For example:

!Interest = @R3.5

assigns the value of the fifth field in the record buffer for Table 3 to the !Interest real variable.

The following commands:

Record Write 0

Table Reply 0 To "BaudRate"

copy the contents of record buffer 0 into Table 0 and send a DDE DATA message to the client with “BaudRate” as the item and the contents of Table 0 as the value.

The ServiceDDE subroutine handles DDE EXECUTE messages. It begins by testing the value of the $DDE_Exec variable, which holds the EXECUTE string passed by the client.

*ServiceDDE

if $DDE_Exec = "DisplayPoke",

Begin

Clear

Record Read 1

Window Restore

Display @R1 | Chr(13)

End

Return

If the EXECUTE string passed was “DisplayPoke”, we’re in business. The subroutine begins by clearing the terminal window and reading the first record of Table 1, which contains the value poked to “WordString”, into the corresponding record buffer. It then restores the DynaComm application window to be sure it’s not minimized or maximized and displays the contents of the record buffer in the terminal window, followed by a Return character (ASCII code 013).

On the Client Side

The Word for Windows document template (CLIENT.DOT) and the Microsoft Excel macro sheet (CLIENT.XLS) each contain two macros, GetBaudRate and PokeToDisplay. These macros comprise the client counterpart of our DynaComm server application.4

The GetBaudRate macro

1.Initiates a DDE conversation with DynaComm with SYSTEM as the topic. If this fails, it attempts to start DynaComm and tries to initiate the conversation again.

2.Terminates the current conversation and begins a new conversation with SERVER as the topic.

3.Sends a DDE REQUEST message for the “BaudRate” item and assigns the server’s reply to a variable.

4.Displays DynaComm’s baud rate in a message dialog box.

5.Terminates the DDE conversation.

The complete GetBaudRate macro code for Word for Windows is shown below.

Dim Shared channel

Sub MAIN

On Error Goto StartDynaComm

' Check to see if DynaComm is running.

Channel = DDEInitiate("DynaComm", "system")

DDETerminate channel

ConnectToServer:

On Error Goto GiveUp

ErrorText$ = "DynaComm was unable to execute the Server script."

' Initiate a DDE conversation with the Server script as the topic

Channel = DDEInitiate("DynaComm", "Server")

ErrorText$ = "DynaComm can't supply the requested data."

BaudRate$ = DDERequest$(channel, "BaudRate")

MsgBox "DynaComm's baud rate is set to " + baudrate$

Goto finish

StartDynaComm:

On Error Goto GiveUp

ErrorText$ = "Unable to start DynaComm."

' Start DynaComm.

Shell "DynaComm.exe", 1

ErrorText$ = "Unable to initiate a DDE conversation with DynaComm."

channel = DDEInitiate("DynaComm", "System")

Goto ConnectToServer

GiveUp:

MsgBox ErrorText$, "Request from DynaComm", 48

Goto Finish

finish:

On Error Resume Next

DDETerminate Channel

End Sub

The GetBaudRate macro code for Microsoft Excel is as follows:

The PokeToDisplay macro

1.Initiates a DDE conversation with DynaComm with SYSTEM as the topic. If this fails, it attempts to start DynaComm and tries to initiate the conversation again.

2.Terminates the current conversation and begins a new conversation with SERVER as the topic.

3.Activates the DynaComm application window.

4.Presents the user with an input dialog box (Figure 5) and pokes the user’s input to the “WordString” item in DynaComm.

Figure 5. Dialog Box Produced by PokeToDisplay

5.Sends a DDE EXECUTE message to DynaComm with “DisplayPoke” as the EXECUTE string.

6.Terminates the DDE conversation.

The complete PokeToDisplay macro code for Word for Windows is shown below.

Dim Shared channel

Sub MAIN

On Error Goto StartDynaComm

' Check to see if DynaComm is running.

Channel = DDEInitiate("DynaComm", "System")

DDETerminate channel

ConnectToServer:

On Error Goto GiveUp

ErrorText$ = "DynaComm was unable to execute the Server script."

' Initiate a DDE conversation with the Server script as the topic.

Channel = DDEInitiate("DynaComm", "Server")

' Prompt for text to be sent to DynaComm.

PokeText$ = InputBox$("Enter the text to be Poked into DynaComm:",

"Poke to DynaComm")

ErrorText$ = "Unable to send the requested data to DynaComm."

' Bring DynaComm into the foreground.

AppActivate "DynaComm"

' Send the text to DynaComm.

DDEPoke channel, "WordString", PokeText$

ErrorText$ = "DynaComm would not execute the requested command."

' Execute DynaComm's routine to display the poked data.

DDEExecute channel, "DisplayPoke"

Goto finish

StartDynaComm:

On Error Goto GiveUp

ErrorText$ = "Unable to start DynaComm."

' Start DynaComm.

Shell "DynaComm.exe", 1

ErrorText$ = "Unable to initiate a DDE conversation with DynaComm."

channel = DDEInitiate("DynaComm", "System")

Goto ConnectToServer

GiveUp:

MsgBox ErrorText$, "Poke To DynaComm", 48

Goto Finish

finish:

On Error Resume Next

DDETerminate Channel

End Sub

The PokeToDisplay macro code for Microsoft Excel is as follows:

PITFALLS, PROBLEMS, AND WORKAROUNDS

DDE EXECUTE Limitation in Server Mode

You can’t make your application refuse certain DDE EXECUTE strings and accept others without writing your own low-level routine.

Workaround

If your DynaComm server application needs to communicate with a client unfamiliar with the EXECUTE strings your server supports, or if you need feedback from DynaComm for debugging purposes, you can set up a flag to indicate whether the EXECUTE was successful and make it available to the client using a When Request or a When Advise command.

The server application must update the flag every time it receives an EXECUTE message, and the client application must check the flag after issuing the DDE EXECUTE to determine whether the EXECUTE was processed. The following code shows a DynaComm server script created for this purpose.

Table Define 0 fields char 5

@R0=“False”

Record Write 0

When Execute $DDE_Exec Perform Slave

When Request 0 “Valid_Exec” Table Reply 0 to “Valid_Exec”

*Slave

If $DDE_Exec = “Command1” perform Command1,

Goto SlaveEnd

If $DDE_Exec = “Command2” perform Command2,

Goto SlaveEnd

@R0=“False”

*SlaveEnd

Table clear 0

Record write 0

Return

*Command1

@R0=“True”

Perform DoThis

*Command2

@R0=“True”

Perform DoThat

Poor Error Handling

Run-time error handling is poorly documented and lacking in useful information. The programmer (not the user, we pray) is presented with an error dialog box indicating that a run-time error occurred and the command number—not the line number—that produced the error.

Workaround

To track down a questionable run-time error:

1.Insert the following lines immediately before the section of the script you believe is causing the problem:

Debug "?"

Show

This will cause DynaComm to enter step mode and display script commands before execution. You can place the Noshow command after the problem area in the script to resume uninterrupted execution of the script commands.

2.Recompile the script and run it with the terminal window displayed. When the script gets to the Show command, DynaComm will suspend execution and display each command following Show in the status bar at the bottom of the terminal window.

3.Execute the script one line at a time using Resume from the Script menu.

Duplicate Rows in Tables

When you use Table Request in client mode or When Poke in server mode to receive data into tables, the last row of data is entered twice in the table.

Workaround

Write a loop that reads data from the table but ignores the last record. You can also use this loop to transfer the data to a new table. The code below demonstrates how to use the Record Read command in conjunction with the EOF function. The Record Read command reads data from the table into the record buffer and moves to the next row in the table with each iteration. The EOF function returns TRUE if the table is positioned at the last record.

Table Define 0 fields char 5, int 6, char 7

Table Define 1 fields char 5, int 6, char 7

When Poke 0 "Data_Table" Perform FixTable

*FixTable

Record Read 0

While Not EOF(),

Begin

@R1=@R0

Record write 1

Record Read 0

End

Return

Microsoft Excel Misinterprets Data

Data sent to Microsoft Excel in SYLK format using the Table Send command can’t be interpreted as dates, formulas, or Booleans.

Workaround

DynaComm’s Table Send command lets you send data in TEXT, DIF, or SYLK format. When you send data to Microsoft Excel in SYLK format, Microsoft Excel interprets the data exactly as it’s stored in the DynaComm table, so you’re limited to text, integer, and real data types. Thus the “=B$3+Total_Sales” text string comes into Microsoft Excel as a text string. However, if you send data as TEXT or DIF, Microsoft Excel interprets the data as though the user typed it in. So “10/25/91” becomes a date value, “TRUE” becomes a Boolean, and “=SUM(B5:C10)” becomes a formula.

Table Request Doesn't Work with Microsoft Excel

The Table Request command yields an empty table or produces unpredictable results when used to request data from Microsoft Excel.

Workaround

To use the Table Request command with Microsoft Excel, you must request data in SYLK format. Follow these guidelines to get the data you need:

You must define the table before you issue the Table Request command. The lengths and data types of each column must be appropriate for the data you expect to receive. If you try to read text into an integer column, that column will be left blank.

You can read dates and times into a real numeric column. See the Microsoft Excel documentation for details on these numeric values.

You can read Booleans into integer or real columns but not into text columns. Oddly enough, the numeric column will not contain a numeric value but will contain the “TRUE” or “FALSE” text string, provided that you’ve allotted enough room in the receiving columns.

The Table Request and When Poke commands destroy existing data in the table before they write new data. Both commands also duplicate the last row transmitted from Microsoft Excel.

Problems with Word for Windows

DynaComm intermittently refuses DDE POKE and DDE REQUEST messages from Word for Windows. It can’t receive data from Word for Windows through the Table Request command.

Workaround

No workaround exists at present.

Can't Enter Numeric Values into the Record Buffer

DynaComm won’t accept a numeric value into the record buffer, even if you define columns as integer or real.

Workaround

The record buffer is a string variable, so you must enter all data, including real and integer values, as strings. The following code shows an example:

Table Define 0 Fields char 40 int 4 real 8

@R0.1 = "Acme Propeller Beanie"

@R0.2 = "35"

@R0.3 = "9.50"

record write 0

Can't Poke or Request a Numeric Value

The Poke and Request commands are restricted to text data.

Workaround

All requested items are transferred in text format. Therefore, to request a numeric item, you must place it in a string variable. If the server application supports SYLK format, you can use the Table Send and Table Request commands in place of Poke and Request to exchange numeric values.

DDE COMMANDS AND FUNCTIONS

Command Summary

Access

Sends a DDE INITIATE message and optionally stores the channel number in a variable. If more than one server responds, channel numbers can be stored in multiple variables.

Access Cancel

Cancels the active DDE conversation.

Instruct

Sends a DDE EXECUTE message to the DDE server.

Launch

Executes a specified application for MS-DOS or Windows.

Poke

Performs a DDE POKE. You can send only character strings to the server using the Poke command.

Request

Sends a DDE REQUEST for an item and places the reply in a string variable. The request is restricted to text data.

Table Reply

Sends the contents of a specified DynaComm table to a client in response to a DDE ADVISE or a DDE REQUEST message.

Table Request

Requests data from a server in TEXT, SYLK, or DIF format and places the reply in a DynaComm table.

Table Send

Sends the contents of a DynaComm table to the client with a DDE POKE message, using TEXT, SYLK, or DIF format.

Wait Signal

Pauses script execution until the client’s next DDE message is received.

When Advise

Specifies the commands or procedures to be executed when DynaComm receives a DDE ADVISE or a DDE UNADVISE message from the client. If multiple DDE conversations are taking place, you can specify the desired channel number on the command line.

When Execute

Specifies the commands or procedures to be executed when DynaComm receives a DDE EXECUTE message from the client. If multiple DDE conversations are taking place, you can specify the desired channel number on the command line.

When Initiate

Specifies the commands or procedures to be executed when DynaComm receives a DDE INITIATE message from the client. You can optionally store the channel number in a variable.

When Poke

Specifies the commands or procedures to be executed when DynaComm receives a DDE POKE message from the client. If multiple DDE conversations are taking place, you can specify the desired channel number on the command line.

When Request

Specifies the commands or procedures to be executed when DynaComm receives a DDE REQUEST message from the client. If multiple DDE conversations are taking place, you can specify the desired channel number on the command line.

When Terminate

Specifies the commands or procedures to be executed when DynaComm receives a DDE TERMINATE message from the client. If multiple DDE conversations are taking place, you can specify the desired channel number on the command line.

Function Summary

Advise

Indicates whether the When Advise command was triggered by a DDE ADVISE or a DDE UNADVISE message.

The SYSTEM Command

The System command is a very powerful DynaComm command that is not documented in the DynaComm Script Reference . This command allows you to execute any menu command from within a script. Its syntax is:

System menucode commandcode

where menucode is a hexadecimal number identifying a menu, and commandcode is a hexadecimal number identifying a command from the menu. The following table lists menus, commands, and their associated codes.

Menu/Command Code

File Menu 0x000
New 0x0101
Open 0x0102
Close 0x0103
Save 0x0111
Save As 0x0112
Delete 0x0113
Print 0x0121
Printer Setup 0x0122
Exit 0x01FF
Edit Menu 0x100
Undo 0x0201
Select All 0x0211
Cut 0x0221
Copy 0x0222
Paste 0x0223
Clear 0x0224
Copy Table 0x0225
Copy Bitmap 0x0226
Copy Special 0x022F
Set Margin 0x0231
Set Tab Width 0x0232
Reformat 0x0233
Align 0x0234
Center 0x0235
Merge 0x0236
Send 0x0241
Save Select 0x0242
Print Select 0x0243
Save Screen 0x0251
Search Menu 0x200
Find 0x0301
Find Same 0x0302
Replace Same 0x0303
Goto Line 0x0311
Display Select 0x0312
Settings Menu 0x300
Phone Number 0x0401
Emulate 0x0402
Terminal 0x0403
Function Keys 0x0404
Text Transfers 0x0405
Binary Transfers 0x0406
Communications 0x0407
Modem 0x0408
Mouse 0x0410
Monitor 0x0133
Printer 0x0131
Timer 0x0132
Phone Menu 0x400
Dial 0x0501
Hangup 0x0502
Wait for Call 0x0503
Remote Kermit 0x0511
Transfer Menu 0x500
Send Text File 0x0601
Receive Text File 0x0602
View Text File 0x0603
View GIF Image 0x0604
View RLE Image 0x0605
Send Binary File 0x0611
Receive Binary File 0x0612
Pause 0x0621
Resume 0x0622
Stop 0x0623
Script Menu 0x600
Compile 0x0701
Execute 0x0711
Pause 0x0712
Resume 0x0713
Stop 0x0714
Window Menu 0x700
Arrange All 0x0801
Stack All 0x0802
Hide/Show Terminal 0x0811
Hide/Show Function Keys 0x0812

GLOSSARY

argument An expression that modifies the way a command, function, or subroutine works. The argument (also called a parameter) is usually entered after the command, function, or subroutine name and passed to it at run time. Arguments are sometimes delimited by commas.

Boolean A value of TRUE or FALSE. A Boolean expression is a logical condition or set of conditions that evaluates to TRUE or FALSE.

character string A sequence of text characters, which may include alphanumeric and control or symbol characters.

child window A window that is considered part of a parent window. Child windows behave differently from parent windows—they are closed automatically when the parent window closes and usually can’t be moved outside the boundaries of the parent window.

client The application that initiates a DDE conversation and directs the flow of data by issuing DDE POKE, REQUEST, ADVISE, and EXECUTE messages.

command argument An argument to a branching or an event-handling command that specifies the command or commands to be performed under the described condition. The command argument can be a command block that contains multiple commands to be executed.

command block A series of commands that take the place of a single command when used as a command argument. A command block is defined either by ending every line but the last with a comma or by delimiting the command block with Begin and End commands.

compiler A software program or module that translates a program written in a high-level language into a binary file containing machine code.

concatenation Appending one text string to another to form a single text string.

conditional branching Directing the flow of program execution by testing whether a certain condition or set of conditions is true at a certain point. If and While are branching commands.

DDE See dynamic data exchange.

DLL See dynamic link library.

dynamic data exchange Special Windows messages that allow applications running under Windows to communicate and exchange data with one another.

dynamic link library A modular file containing routines written in machine code. DLLs obviate the need for linking or consolidating application and library code into a single executable file.

error level A value of 1, 2, 3, or 4 indicating the severity and source of a run-time error. Error level 1 is fatal and error level 3 is the least severe of the internal run-time errors. Error level 4 is a programmer-defined error condition triggered by the Taskerror command.

event handling Directing the flow of program execution in response to an event such as user input from the keyboard, a DDE message, or an error condition.

EXECUTE string An argument to a DDE EXECUTE message that indicates, in the server’s terms, the action to be performed.

integer A whole number that may be positive, negative, or zero.

item A particular object, such as a memory variable or a spreadsheet range, that is the source or destination of a DDE transaction. The items available for a DDE transaction are defined by the topic of the conversation.

parameter See argument.

parent window A top-level application window that may contain child windows.

real number A number that may include a decimal point.

record buffer A special variable that serves as a temporary holding place for data read from and written to a table. There are 16 record buffers, numbered 0 through 15, each corresponding to the table with the same number. Record buffers are denoted by the “at” sign (@) followed by an ‘R’ and the number of the defined table.

script A program written in DynaComm. The source code for the script resides in an ASCII file with a DCP extension and is compiled into a binary task file with a DCT extension.

server The application that carries out instructions from the client application by responding to DDE REQUEST, POKE, ADVISE, and EXECUTE messages.

settings file A special DynaComm file containing settings for communications, terminal emulation, modem commands, and so on.

source code Program code written in a high-level language.

string See character string.

structured table A memory variable containing rows and columns, in which each column’s length and data type can be determined by the programmer.

SYSTEM topic A DDE topic supported by most DDE implementations. The SYSTEM topic usually responds to DDE REQUESTS for the “formats”, “sysitems”, and “topics” items.

target A location in a script file marked by a target label, which consists of an asterisk (*) followed by the target name. The target label defines a subroutine when combined with the Return command.

task file A special binary program file that DynaComm can execute. The task file is created by compiling a DynaComm script and normally has a DCT extension.

terminal window A DynaComm child window that displays text received through the communications port and input by the user during a communications session. The terminal window shares the name of the current settings file, if one is open.

topic The subject of a DDE conversation, in the server’s terms. Document file names and SYSTEM are the most common topics.

1DynaComm also provides a programmer-definable error level of 4.

2Because Microsoft Excel allows multiple commands in a single EXECUTE string, these two Excel commands could be concatenated and sent from DynaComm with a single Instruct command.

3You can also use the Table Request and Table Send commands to perform DDE transactions with tables in the client mode.

4A timing discrepancy causes these macros to fail intermittently.