Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

How to use Dynamic Data Exchange (DDE) with Word and Excel from Visual C++


View products that this article applies to.

Summary

This article describes how to use Dynamic Data Exchange (DDE) in Visual C++ to communicate with Excel and Word.

NOTE: When possible, it is recommended that you use Automation, not DDE, to communicate with Excel or Word. Excel and Word have rich object models that provide functionality through Automation that is not available with DDE. Excel versions 5.0 and later, and Word versions 7.0 and later, support Automation.

↑ Back to the top


More information

Sample DDE Client

The following sample uses an Excel workbook or a Word document for the DDE topic.

For Excel, create a new workbook (C:\Test.xls) that contains data in cells A1 and A2. For Word, create a new document (C:\Test.doc) that contains text. Select some, but not all, of the text in the document and create a bookmark named "MyBookmark" at that location.
  1. In Visual C++, create a new Win32 Console Application named "DDEClient".
  2. In the AppWizard, select A Simple Application and then click Finish.
  3. Replace the code in DDEClient.cpp with the following:
    #include "stdafx.h"
    #include "windows.h"
    #include "ddeml.h"
    #include "stdio.h"
    
    HDDEDATA CALLBACK DdeCallback(
        UINT uType,     // Transaction type.
        UINT uFmt,      // Clipboard data format.
        HCONV hconv,    // Handle to the conversation.
        HSZ hsz1,       // Handle to a string.
        HSZ hsz2,       // Handle to a string.
        HDDEDATA hdata, // Handle to a global memory object.
        DWORD dwData1,  // Transaction-specific data.
        DWORD dwData2)  // Transaction-specific data.
    {
        return 0;
    }
    
    void DDEExecute(DWORD idInst, HCONV hConv, char* szCommand)
    {
        HDDEDATA hData = DdeCreateDataHandle(idInst, (LPBYTE)szCommand,
                                   lstrlen(szCommand)+1, 0, NULL, CF_TEXT, 0);
        if (hData==NULL)   {
            printf("Command failed: %s\n", szCommand);
        }
        else    {
            DdeClientTransaction((LPBYTE)hData, 0xFFFFFFFF, hConv, 0L, 0,
                                 XTYP_EXECUTE, TIMEOUT_ASYNC, NULL);
        }
    }
    
    void DDERequest(DWORD idInst, HCONV hConv, char* szItem, char* sDesc)
    {
        HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0);
        HDDEDATA hData = DdeClientTransaction(NULL,0,hConv,hszItem,CF_TEXT, 
                                     XTYP_REQUEST,5000 , NULL);
        if (hData==NULL)
        {
            printf("Request failed: %s\n", szItem);
        }
        else
        {
            char szResult[255];
            DdeGetData(hData, (unsigned char *)szResult, 255, 0);
            printf("%s%s\n", sDesc, szResult);
        }
    }
    
    void DDEPoke(DWORD idInst, HCONV hConv, char* szItem, char* szData)
    {
        HSZ hszItem = DdeCreateStringHandle(idInst, szItem, 0);
    	DdeClientTransaction((LPBYTE)szData, (DWORD)(lstrlen(szData)+1),
                              hConv, hszItem, CF_TEXT,
                              XTYP_POKE, 3000, NULL);
        DdeFreeStringHandle(idInst, hszItem);
    }
    
    int main(int argc, char* argv[])
    {
        char szApp[] = "EXCEL";
        char szTopic[] = "C:\\Test.xls";
        char szCmd1[] = "[APP.MINIMIZE()]";
        char szItem1[] = "R1C1";  char szDesc1[] = "A1 Contains: ";
        char szItem2[] = "R2C1";  char szDesc2[] = "A2 Contains: ";
        char szItem3[] = "R3C1";  char szData3[] = "Data from DDE Client";
        char szCmd2[] = "[SELECT(\"R3C1\")][FONT.PROPERTIES(,\"Bold\")][SAVE()][QUIT()]";
    
        //DDE Initialization
        DWORD idInst=0;
        UINT iReturn;
        iReturn = DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback, 
                                APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0 );
        if (iReturn!=DMLERR_NO_ERROR)
        {
            printf("DDE Initialization Failed: 0x%04x\n", iReturn);
            Sleep(1500);
            return 0;
        }
    
        //Start DDE Server and wait for it to become idle.
        HINSTANCE hRet = ShellExecute(0, "open", szTopic, 0, 0, SW_SHOWNORMAL);
        if ((int)hRet < 33)
        {
            printf("Unable to Start DDE Server: 0x%04x\n", hRet);
            Sleep(1500); DdeUninitialize(idInst);
            return 0;
        }
        Sleep(1000);
    
        //DDE Connect to Server using given AppName and topic.
        HSZ hszApp, hszTopic;
        HCONV hConv;
        hszApp = DdeCreateStringHandle(idInst, szApp, 0);
        hszTopic = DdeCreateStringHandle(idInst, szTopic, 0);
        hConv = DdeConnect(idInst, hszApp, hszTopic, NULL);
        DdeFreeStringHandle(idInst, hszApp);
        DdeFreeStringHandle(idInst, hszTopic);
        if (hConv == NULL)
        {
            printf("DDE Connection Failed.\n");
            Sleep(1500); DdeUninitialize(idInst);
            return 0;
        }
    
        //Execute commands/requests specific to the DDE Server.
        DDEExecute(idInst, hConv, szCmd1);
        DDERequest(idInst, hConv, szItem1, szDesc1); 
        DDERequest(idInst, hConv, szItem2, szDesc2);
        DDEPoke(idInst, hConv, szItem3, szData3);
        DDEExecute(idInst, hConv, szCmd2);
    
        //DDE Disconnect and Uninitialize.
        DdeDisconnect(hConv);
        DdeUninitialize(idInst);
    
        Sleep(3000);
        return 1;
    }
    					
  4. For Word, replace the first 7 lines in the main function with the following:
        char szApp[] = "WINWORD";
        char szTopic[] = "C:\\test.doc";
        char szCmd1[] = "[AppMinimize][EditGoTo Destination:=\"\\EndofDoc\"][InsertPara]";
        char szItem1[] = "\\Doc";      char szDesc1[] = "Document contains: \n";
        char szItem2[] = "MyBookmark"; char szDesc2[] = "MyBookmark contains: \n";
        char szItem3[] = "\\EndofDoc"; char szData3[] = "Data from DDE Client";
        char szCmd2[] = "[FileSave][FileExit(2)]";
    					
  5. Build and then run the application.
With Excel, the DDE client initiates a DDE conversation using the topic for the workbook file (C:\Test.xls) and performs the following actions:
  • Executes the APP.MINIMIZE command.
  • Requests the data in the items R1C1 and R2C1. Note that Excel requires that request items be in R1C1 notation.
  • Pokes data to R3C1.
  • Formats R3C1 in bold, saves the workbook, and then quits Excel.
With Word, the DDE client initiates a DDE conversation using the topic for the document file (C:\Test.doc) and performs the following actions:

  • Executes commands to minimize the application, go to the end of the document and insert a new paragraph.
  • Requests the item "\Doc" to retrieve the contents of the entire document. Note that \Doc is a predefined bookmark.
  • Requests the item "MyBookmark" to retrieve the text in the bookmark.
  • Executes commands to save the document and quit Word.

↑ Back to the top


References

For additional information on DDE, click the article numbers below to view the articles in the Microsoft Knowledge Base:
108933 Top 10 DDEML Support Issues
238133 How To Write a DDEML Server for Excel and Use it with NetDDE

↑ Back to the top


Keywords: KB279721, kbhowto, kbdde

↑ Back to the top

Article Info
Article ID : 279721
Revision : 5
Created on : 1/29/2007
Published on : 1/29/2007
Exists online : False
Views : 678