Applies To:
  • CitectSCADA 1.00, 1.01, 1.10, 1.11, 1.20, 2.00, 2.01

Summary:
This article has been superseded by Q1839.

The following is a description on how to setup DDE with Microsoft Access. 

Solution:
As with all DDE communications, the most important step is to ascertain the correct APPLICATION name, TOPIC names and ITEM names. The Application name is incorrectly stated in the Access manuals as "ACCESS". The Topic is usually the name of document but in the case of ACCESS it is a combination of the Database and Table names. The most commonly used Topics and Items are as follows:-

Application MSAccess (NOT Access as stated in the Access Manual).
Topic DatabaseName;TABLE TableName (eg MyDatabase;TABLE MyTable)
   Item FirstRow
       LastRow
       NextRow
       PrevRow
Topic Database (eg MyDatabase)
    Item TableList
       QueryList
       FormList
       ReportList
       MacroList
       ModuleList
Topic System
    Item SysItems
       Formats
       Status
       Topics

Full details can be found in ACCESS HELP under "DDE/Using Microsoft Access as a DDE Server". Chapter 9 of "Introduction to Programming" also has some useful information and examples. A CICODE example is:

DataBuffer = DDERead("MSAcces","MyDatabase;TABLE MyTable","FirstRow",0);

The 4th parameter is new (Citect V2.01) and tells the Application whether or not to set up an ADVISE LOOP. DataBuffer will contain all the fields in the first row separated by TAB (Char(9)). If the Table row is likely to total 254 characters or more (remember to add a tab for each field), it is necessary to design Queries in Access that return rows that are less than 254 characters and call multiple Queries instead of the Table.

To send data to Access, first use DDEPost to post each field. Forms can be designed in Access with an unbound control for each field containing a DDE entry (eg =DDE("Citect","Data", PostName)). After posting the data, wait (say 1 second) then call a macro to force Access to REFRESH the form, than wait 1 second and call another macro to transfer the fields from the unbound form to a form bound to the desired table.

DDEPost("Recipe", RecipeNo);
DDEPost("Sugar", Sugar);
DDEPost("Cocoa", Cocoa);
Sleep(1);
DDEExec("MSAccess","[RefreshData]");
Sleep(1);
DDEExec("MSAccess","[AddRecipe]");

Another approach is to write Access Basic and use DDERequest to obtain the posted data and place it directly into the table. This would require only one time delay and one macro call from Cicode. However, this method seems to be more troublesome in relation to timimg issues.

There is a problem when data is changed on the Access side, resulting deleted records being sent as null data and appended records not being seen. It is thought that if the DDE Channel could be closed and re-opened from Cicode (not possible at present) that the data would then be correct. Citect personnel are considering the issue. There are two choices, the first a new function DEClose(sApp) which would close the DDE channel that Citect had opened for the Application. The alternative is to have DDEInitiate() function (which returns a DDE Channel number) with a full set of DDE functions that can address the channel (including DDEClose(Channel). The second option would allow full DDE functionality. The present Cicode functions hide the DDE Channnel from the user but as we can see, this can lead to problems (see also NETDDE).

Microsoft has been asked whether there is any way to DDEWrite directly to an Access Table. This is mainly a question of obtaining a valid ITEM name - if one exists, (such as "NEWROW") to write the data to.

There is the possibility of using either DDEWrite or DDEExec to send an Action Query in the form of an SQL string, however it does seem to be possible with our current DDE Functions. Some examples of they way SQLs could be sent via channel oriented DDE are as follows (note that neither is currently possible):-

Channel = DDEInitiate("MSAccess", "WIL_DEMO;SQL");
DDEExec(Channel, "INSERT INTO LOCALTBL ( RECIPENO, SUGAR, COCOA ) SELECT '1' AS A,'11.1' AS B,'111' AS C WITH OWNERACCESS OPTION;";

If SQLString is more than 254 charcaters it would normally be possible to open a DDEChannel using the App and Topic parameters, then use successive DDEWrites to that Channel to send the SQLText in chunks (the end being marked with a ";").

Channel = DDEInitiate("MSAccess", "WIL_DEMO;SQL");
DDEWrite(Channel, "SQLText", "INSERT INTO LOCALTBL ( RECIPENO, SUGAR, COCOA ) SELECT '1' AS A,'11.1' AS B,'111' AS C WITH OWNERACCESS OPTION;");

";SQL" is a special Topic modifier for Access and "SQLText" is a special Item. The SQLString used in the example would add a new row to LOCALTBL with RECIPENO = '1', SUGAR = '11.1' and COCOA ='111'. 


 

Keywords:
 

Attachments