2010-07-22 60 views
0

我是從How to use Dynamic Data Exchange (DDE) with Word and Excel from Visual C++的例子,我以某種方式設法能夠從Excel中檢索值。如何通知動態數據交換(DDE)的任何更新?

現在的問題是,在這個例子中,我必須再次運行該應用程序以獲得必要的更新。我如何做到這一點,如果在Excel中有更新,我的應用程序將被通知? DdeAdvise?

在此先感謝! Excel只是一個例子!不,我需要DDE而不是COM,即使它老了。

// DDEExample.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <windows.h> 
#include "ddeml.h" 

#define PAUSE system("pause") 

HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hconv, 
     HSZ hsz1, HSZ hsz2, HDDEDATA hdata, 
     ULONG_PTR dwData1, ULONG_PTR dwData2) 
{ 
printf("uType: %d", uType); 
switch(uType) 
{ 
    case XTYP_REQUEST: 
    printf("XTYP_REQUEST\n"); 
    break; 

} 
return 0; 
} 

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); 
    } 
} 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
char szApp[] = "EXCEL"; 
char szTopic[] = "C:\\Test.xlsx"; 
char szCmd1[] = "[APP.MINIMIZE()]"; 
char szItem1[] = "R1C1"; char szDesc1[] = "A1 Contains: "; 


UINT uiResult; 
DWORD m_dwDDEInstance = 0; 
uiResult = DdeInitialize(&m_dwDDEInstance, (PFNCALLBACK) &DdeCallback, APPCLASS_STANDARD|APPCMD_CLIENTONLY, 0); 
if(uiResult != DMLERR_NO_ERROR) 
{ 
    printf("DDE Initialization Failed: 0x%04x\n", uiResult); 
    return FALSE; 
} 
printf("m_dwDDEInstance: %u\n", m_dwDDEInstance); 
//PAUSE; 
HSZ hszApp, hszTopic; 
HCONV hConv; 
hszApp = DdeCreateStringHandle(m_dwDDEInstance, szApp, 0); 
hszTopic = DdeCreateStringHandle(m_dwDDEInstance, szTopic, 0); 
hConv = DdeConnect(m_dwDDEInstance, hszApp, hszTopic, NULL); 
DdeFreeStringHandle(m_dwDDEInstance, hszApp); 
DdeFreeStringHandle(m_dwDDEInstance, hszTopic); 
if(hConv == NULL) 
{ 
    printf("DDE Connection Failed.\n"); 
} 

DDERequest(m_dwDDEInstance, hConv, szItem1, szDesc1); 
DdeDisconnect(hConv); 
DdeUninitialize(m_dwDDEInstance); 

PAUSE; 
} 
+0

有一些令人信服的理由使用DDE而不是自動化? – 2010-07-22 06:19:42

+0

@Marcelo Cantos 你好,謝謝你的回覆。 DDE是通信應用程序提供的唯一選項,我認爲DDE對於應用程序通信而言是相當「開放」的。 – user303907 2010-07-22 06:30:32

+0

@ user303907:DDE是一個錯誤的混亂。不要使用它。研究其他可能的解決方案,例如OLE。否則,我不認爲Office有用戶輸入通知。 – Dummy00001 2010-07-22 09:18:30

回答

0

這不是一個很大的答案,所以我很抱歉。無論如何,你有沒有可能使用C#甚至C++/CLI?因爲如果你可以,那麼你可以使用NDde。所有的低級管道都有建議循環的地方,下載中包含了一些示例。

1

來自MS平臺SDK: 「客戶端可以通過在調用DdeClientTransaction中指定XTYP_ADVSTART事務類型來向服務器請求熱建議循環」。

//#include "stdafx.h" 
#include "windows.h" 
#include "ddeml.h" 
#include "stdio.h" 

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"; 

HSZ hszApp, hszTopic; 
DWORD idInst=0; 

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. 
{ 
    if(uType==XTYP_ADVDATA && uFmt==CF_TEXT) 
    { 
     HSZ hszItem1 = DdeCreateStringHandle(idInst, szItem1, 0); 
     HSZ hszItem2 = DdeCreateStringHandle(idInst, szItem2, 0); 
     char szResult[255]; 
     if((!DdeCmpStringHandles(hsz1, hszTopic)) && (!DdeCmpStringHandles(hsz2, hszItem1))) 
     { 
      DdeGetData(hdata, (unsigned char *)szResult, 255, 0); 
      printf("%s - %s\n", szItem1,szResult); 
     } 
     else if((!DdeCmpStringHandles(hsz1, hszTopic)) && (!DdeCmpStringHandles(hsz2, hszItem2))) 
     { 
      DdeGetData(hdata, (unsigned char *)szResult, 255, 0); 
      printf("%s - %s\n", szItem2,szResult); 
     } 
    } 
    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 szCmd2[] = "[SELECT(\"R3C1\")][FONT.PROPERTIES(,\"Bold\")]";//[SAVE()][QUIT()]"; 

    //DDE Initialization 
    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", (UINT)hRet); 
     Sleep(1500); DdeUninitialize(idInst); 
     return 0; 
    } 
    Sleep(1000); 

    //DDE Connect to Server using given AppName and topic. 
    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); 

    HSZ hszItem = DdeCreateStringHandle(idInst, szItem1, 0); 
    DdeClientTransaction(NULL,0,hConv,hszItem,CF_TEXT, 
           XTYP_ADVSTART,5000 , NULL); 


BOOL bRet; 
MSG msg; 

while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) 
{ 
    if (bRet == -1) 
    { 
     // handle the error and possibly exit 
    } 
    else 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

    //DDE Disconnect and Uninitialize. 
    DdeDisconnect(hConv); 
    DdeUninitialize(idInst); 

    Sleep(3000); 
    return 1; 
} 

希望這有助於