Microsoft KB Archive/279721

From BetaArchive Wiki
Knowledge Base


Article ID: 279721

Article Last Modified on 1/29/2007



APPLIES TO

  • Microsoft Excel 2000 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Word 97 Standard Edition
  • Microsoft Excel 97 Standard Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Word 2002 Standard Edition
  • Microsoft Excel 2002 Standard Edition



This article was previously published under Q279721

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.

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.


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



Additional query words: DdeCreateStringHandle DdeInitialize DdeCreateDataHandle DdeClientTransaction XTYP_POKE XTYP_REQUEST XTY_EXECUTE Winword

Keywords: kbdde kbhowto KB279721