文章編號: 216686 - 上次校閱: 2007年5月11日 - 版次: 5.2
如何不使用 MFC 或 # import 自動化 Excel 從 C + +
系統提示 本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。
有幾個優點撰寫您自動化直線的 C + + 中的程式碼。首先,foremost,您可以執行完全決定。 接下來,您的程式碼將會變得更小、 更快,而且容易偵錯。而且最後,您不會依存於任何的程式庫。即使您是專用來使用 MFC 的包裝函式類別或 Visual C++ 的原生 COM 支援 (# import)],您可能仍然需要深入 IDispatch 和 COM 自動化的內容,若要解決常見的錯誤並與這些架構的限制。
使用只是 C + + 的 Microsoft Office Excel 會自動執行的建置簡單的 Visual C++ 6.0 主控台應用程式,請依據以下步驟:
啟動 Visual 的 C + + 6.0 和建立新命名 XlCpp 選擇"一個 Hello、 全球!"應用程式基底的 Win32 主控台應用程式,然後按一下 [完成 ]。 開啟產生的 XlCpp.cpp,然後加入下列程式碼之前 main () 函式。
#include <ole2.h> // OLE2 Definitions
// AutoWrap() - Automation helper function...
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
// Begin variable-argument list...
va_list marker;
va_start(marker, cArgs);
if(!pDisp) {
MessageBox(NULL, "NULL IDispatch passed to AutoWrap()", "Error", 0x10010);
_exit(0);
}
// Variables used...
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
HRESULT hr;
char buf[200];
char szName[200];
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
// Get DISPID for name passed...
hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
if(FAILED(hr)) {
sprintf(buf, "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr);
MessageBox(NULL, buf, "AutoWrap()", 0x10010);
_exit(0);
return hr;
}
// Allocate memory for arguments...
VARIANT *pArgs = new VARIANT[cArgs+1];
// Extract arguments...
for(int i=0; i<cArgs; i++) {
pArgs[i] = va_arg(marker, VARIANT);
}
// Build DISPPARAMS
dp.cArgs = cArgs;
dp.rgvarg = pArgs;
// Handle special-case for property-puts!
if(autoType & DISPATCH_PROPERTYPUT) {
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call!
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
if(FAILED(hr)) {
sprintf(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
MessageBox(NULL, buf, "AutoWrap()", 0x10010);
_exit(0);
return hr;
}
// End variable-argument section...
va_end(marker);
delete [] pArgs;
return hr;
}
在 main () 函式取代下列程式碼 printf() 線條。
// Initialize COM for this thread...
CoInitialize(NULL);
// Get CLSID for our server...
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if(FAILED(hr)) {
::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 0x10010);
return -1;
}
// Start server and get IDispatch...
IDispatch *pXlApp;
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pXlApp);
if(FAILED(hr)) {
::MessageBox(NULL, "Excel not registered properly", "Error", 0x10010);
return -2;
}
// Make it visible (i.e. app.visible = 1)
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x);
}
// Get Workbooks collection
IDispatch *pXlBooks;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"Workbooks", 0);
pXlBooks = result.pdispVal;
}
// Call Workbooks.Add() to get a new workbook...
IDispatch *pXlBook;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, L"Add", 0);
pXlBook = result.pdispVal;
}
// Create a 15x15 safearray of variants...
VARIANT arr;
arr.vt = VT_ARRAY | VT_VARIANT;
{
SAFEARRAYBOUND sab[2];
sab[0].lLbound = 1; sab[0].cElements = 15;
sab[1].lLbound = 1; sab[1].cElements = 15;
arr.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
}
// Fill safearray with some values...
for(int i=1; i<=15; i++) {
for(int j=1; j<=15; j++) {
// Create entry value for (i,j)
VARIANT tmp;
tmp.vt = VT_I4;
tmp.lVal = i*j;
// Add to safearray...
long indices[] = {i,j};
SafeArrayPutElement(arr.parray, indices, (void *)&tmp);
}
}
// Get ActiveSheet object
IDispatch *pXlSheet;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveSheet", 0);
pXlSheet = result.pdispVal;
}
// Get Range object for the Range A1:O15...
IDispatch *pXlRange;
{
VARIANT parm;
parm.vt = VT_BSTR;
parm.bstrVal = ::SysAllocString(L"A1:O15");
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, L"Range", 1, parm);
VariantClear(&parm);
pXlRange = result.pdispVal;
}
// Set range with our safearray...
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlRange, L"Value", 1, arr);
// Wait for user...
::MessageBox(NULL, "All done.", "Notice", 0x10000);
// Set .Saved property of workbook to TRUE so we aren't prompted
// to save when we tell Excel to quit...
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlBook, L"Saved", 1, x);
}
// Tell Excel to quit (i.e. App.Quit)
AutoWrap(DISPATCH_METHOD, NULL, pXlApp, L"Quit", 0);
// Release references...
pXlRange->Release();
pXlSheet->Release();
pXlBook->Release();
pXlBooks->Release();
pXlApp->Release();
VariantClear(&arr);
// Uninitialize COM for this thread...
CoUninitialize();
編譯並執行。 AutoWrap() 函數簡化了大部分的與直接使用 IDispatch 相關的低階詳細資料。請隨意在您自己的實作中使用它。一個警告就是如果您傳遞多個參數,他們必須反向順序傳遞。例如:
VARIANT parm[3];
parm[0].vt = VT_I4; parm[0].lVal = 1;
parm[1].vt = VT_I4; parm[1].lVal = 2;
parm[2].vt = VT_I4; parm[2].lVal = 3;
AutoWrap(DISPATCH_METHOD, NULL, pDisp, L"call", 3, parm[2], parm[1], parm[0]);
如更多有關使用 Visual C++ 來自動化 Office 的資訊,按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中 「 文件:
196776 ?
(http://support.microsoft.com/kb/196776/
)
使用 Visual C++ 的辦公室自動化
216388 ?
(http://support.microsoft.com/kb/216388/
)
B2CSE.exe 將 Visual Basic 自動化程式碼轉換成 Visual C++
(c) Microsoft Corporation 1999,保留所有的權限。 由 Joe Crump,Microsoft Corporation 的貢獻。
這篇文章中的資訊適用於: Microsoft Office Excel 2007 Microsoft Office Excel 2003 Microsoft Excel 2002 Standard Edition Microsoft Excel 2000 Standard Edition Microsoft Excel 97 Standard Edition Microsoft Visual C++ 5.0 Enterprise Edition Microsoft Visual C++ 6.0 Enterprise Edition Microsoft Visual C++ 5.0 Professional Edition Microsoft Visual C++ 6.0 Professional Edition Microsoft Visual C++, 32-bit Learning Edition 6.0 kbmt kbautomation kbhowto KB216686 KbMtzh
機器翻譯 重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:
216686 ?
(http://support.microsoft.com/kb/216686/en-us/
)
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。
請說明您希望我們對本篇文章進行什麼改善及需要改善的原因
謝謝您!您的意見將協助我們改進支援內容。如需更多協助選項,請造訪
說明及支援首頁 。