Microsoft KB Archive/238133

= How To Write a DDEML Server for Excel and Use it with NetDDE =

Article ID: 238133

Article Last Modified on 1/24/2007

-

APPLIES TO


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

-



This article was previously published under Q238133



SUMMARY
This article walks you through building a DDE Management Library (DDEML) server application for Microsoft Excel using Visual C++, and illustrates how you can use the server remotely.



MORE INFORMATION
A common use of DDE (Dynamic Data Exchange) is to create an application that serves data to DDE clients such as Microsoft Excel. For instance, you might have an application that continuously gets real-time stock market quotes. Using DDE, you could expose this data from your application, and Excel users with access to it could reference it right in their calculations using DDE links.

The first part of this article walks you through building a very basic DDE server application using the DDEML. It updates a counter variable continuously, and advises any DDE clients listening as it changes:  Create a new Visual C++ 6.0 project. Select "Win32 Application" as the project type, and name it "DdemlSvr." When it asks you what kind of project you want, select "An empty project." Add a new .cpp file to your project called "main.cpp."  Paste the following code into main.cpp:
 * 1) include 
 * 2) include 
 * 3) include 

// Globals... HSZ g_hszAppName; HSZ g_hszTopicName; HSZ g_hszItemName; int g_count = 0; DWORD g_idInst = 0;

// Declarations: HDDEDATA EXPENTRY DdeCallback(UINT type, UINT fmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2);

// WinMain.. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // Initialize DDEML... if(DdeInitialize(&g_idInst, DdeCallback, APPCLASS_STANDARD, 0)) { MessageBox(NULL, "DdeInitialize failed", "Error", MB_SETFOREGROUND); return -1; }  // Create string handles... g_hszAppName = DdeCreateStringHandle(g_idInst, "DdemlSvr", NULL); g_hszTopicName = DdeCreateStringHandle(g_idInst, "MyTopic", NULL); g_hszItemName = DdeCreateStringHandle(g_idInst, "MyItem", NULL); if( (g_hszAppName == 0) || (g_hszTopicName == 0) || (g_hszItemName == 0) ) { MessageBox(NULL, "DdeCreateStringHandle failed", "Error", MB_SETFOREGROUND); return -2; }  // Register DDE server if(!DdeNameService(g_idInst, g_hszAppName, NULL, DNS_REGISTER)) { MessageBox(NULL, "DdeNameService failed!", "Error", MB_SETFOREGROUND); return -3; }  // Create a timer to simulate changing data... SetTimer(0,0,1,0); // Message loop: MSG msg;

while (GetMessage(&msg, NULL, 0, 0)) { // On WM_TIMER, change our counter, and update clients... if(msg.message == WM_TIMER) { g_count++; DdePostAdvise(g_idInst, g_hszTopicName, g_hszItemName); }     TranslateMessage(&msg); DispatchMessage(&msg); }  return msg.wParam; }

// Our DDE Callback function... HDDEDATA EXPENTRY DdeCallback(UINT wType, UINT fmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2) {

switch (wType) { //   case XTYP_CONNECT: // Client is trying to connect. Respond TRUE if we have what they want... if ((!DdeCmpStringHandles(hsz1, g_hszTopicName)) &&        (!DdeCmpStringHandles(hsz2, g_hszAppName))) return (HDDEDATA)TRUE;  // SERVER supports Topic|Service else return FALSE; // SERVER does not support Topic|Service //   case XTYP_ADVSTART: // Client starting advisory loop. // Say "ok" if we have what they are asking for...

if((!DdeCmpStringHandles(hsz1, g_hszTopicName)) &&        (!DdeCmpStringHandles(hsz2, g_hszItemName))) return (HDDEDATA)TRUE;  // SERVER supports Topic|Service else return FALSE; // SERVER does not support Topic|Service //

case XTYP_ADVREQ: // Client wants our data. Since this is specific to Excel, we'll     // go ahead and assume they want XlTable-formatted data. For a     // generic DDE server, you might want to handle various formats // specified by the passed in fmt parameter.

if(!DdeCmpStringHandles(hsz1, g_hszTopicName) &&        !DdeCmpStringHandles(hsz2, g_hszItemName)) {

short xltableData[100]; // tdtTable record... xltableData[0] = 0x0010; // tdtTable xltableData[1] = 4; // 2 short ints following xltableData[2] = 1; // # rows xltableData[3] = 1; // # cols // tdtInt record... xltableData[4] = 0x0006; xltableData[5] = 2; xltableData[6] = (short)g_count;

return DdeCreateDataHandle(g_idInst, (UCHAR*)xltableData, 2*7, 0, g_hszItemName, fmt, 0); }         //    default: return (HDDEDATA)NULL; } }                    Compile and run the project.

The application first calls DdeInitialize to initialize the DDEML library, passing the address of your DdeCallback function that acts in a manner similar to a window procedure. Then, it registers your application, topic, and item strings to get string handles. And finally, it registers your DDE server so clients can see it.

Once a client references you in a DDE link, your DdeCallback function will get called a few times with various parameters starting a DDE conversation. For this simple example, you just check to make sure they are asking for the right topic and name, and under the assumption the client is going to be Excel, just return your data in Excel's XlTable format.

Walk through the following steps to test your DDE server locally before continuing:
 * 1) Make sure your DdemlSvr.exe application is running. You can do this by examining the process list of the Windows Task Manager.
 * 2) Start Excel, and type the following in a cell: =DdemlSvr|MyTopic!MyItem

The cell should obtain the value of g_count from the DDE server application, and increment rapidly as it receives updates.

Now, you are ready to experiment using the server remotely using NetDDE. Follow these steps to set up the server:  Start the DdemlSvr.exe application in a networked Windows NT 4.0 machine that will be your DDE Server: (Install it if it is not already running.)</li> On that same machine, run "DdeShare" from the command-line.</li> Choose Shares from the menu, and select DDE Shares.</li> Click on Add a Share. Fill in the values under Application Name as follows:

Share Name: MyShare$

Old Style: DdemlSvr.DDE

New Style: DdemlSvr.OLE

Static: DdemlSvr

</li> Fill in MyTopic in the three boxes below Topic Name.</li> Click OK, then select MyShare$, and click Trust Share.</li> Check Initiate to Application Enable.</li> Click OK on all the dialog boxes, and exit the DdeShare utility.</li></ol>

Follow these steps to set up the client and test the server:
 * 1) Start Excel on another Windows NT 4.0 machine on the same network; this will be your Client.
 * 2) Type the following in a cell, and substitute the name of your server machine on the network for SERVERNAME: ='\\SERVERNAME\NDDE$'|'MyShare$'!MyItem

You should see results similar to those you saw when you tested on the client, a number incrementing continuously.

<div class="references_section">