Bạn cài VS6 trong đĩa MSDN có các ví dụ về cách làm việc với đối tượng COM trong C++, trong đó có Excel. Bạn tham khảo ví dụ dưới đây. Mã:
#include
#include
#include
using namespace std;
int main[int argc, char* argv[]]
{
// global variables
ifstream in_fp;
const char* szFileName = argv[1];
const char* szDictFile = argv[2];
wchar_t wszFileName[MAX_PATH+1];
DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
VARIANT vResult; // used to hold variant results
OLECHAR FAR* szFunction;
IDispatch* pDispApp;
IDispatch* pDispXlBooks;
DISPID dispid_Books; //Documents property of application object
DISPID dispid_Quit;
BSTR bstrFileName = ::SysAllocString[OLESTR["filename"]];
BSTR bstrPassWord = ::SysAllocString[OLESTR["pass"]];
//get arguements and check files
if [ argc != 3 ]{
printf["usage %s \n", argv[0]];
exit[1];
}
in_fp.open[szFileName, ios::in];
if [!in_fp || strlen[szFileName] > MAX_PATH]{
printf["error loading %s\n", szFileName];
exit[1];
}
in_fp.close[];
in_fp.open[szDictFile, ios::in];
if [!in_fp]{
printf["error loading %s\n", szDictFile];
exit[1];
}
//convert file name to bstr for use with COM
MultiByteToWideChar[CP_ACP, 0, szFileName, strlen[szFileName]+1,
wszFileName, sizeof[wszFileName]/sizeof[wszFileName[0]]];
bstrFileName = ::SysAllocString[wszFileName];
// COM work starts here
//Initialize COM
::CoInitialize[NULL];
printf["initializing COM...\n"];
//get the CLSID for the Excel Application Object
CLSID clsid;
CLSIDFromProgID[L"Excel.Application", &clsid];
//get a pointer to the Objects IUnknown interface and Create
//an instance of the Excel Application.
IUnknown* pUnk;
HRESULT hr = ::CoCreateInstance[ clsid, NULL,
CLSCTX_SERVER, IID_IUnknown, [void**] &pUnk];
printf["instance of Excel Created...\n"];
/*
All COM interfaces inherit from the IUnknown interface, this interface
has a total of three functions: QueryInterface[], AddRef[] and Release[]
QueryInterface[] is used to retrieve a pointer to the IDispatch Interface
and the AddRef[] and Release[] functions are used to maintain the
reference count [a count of all the number of interface pointers that are
being used by clients].
*/
hr = pUnk->QueryInterface[IID_IDispatch, [void**]&pDispApp];
/*
use ::GetIDsOfNames on pDisApp to get the DISPID
The DISPID [dispatch identifier] uniquely identifies each method within
a function. You then use ::Invoke to call that method or property.
when IDispatch::Invoke is called it also passes on parameters for the
method and recieves it's returned value. This does most of the work.
*/
szFunction = OLESTR["Workbooks"];
hr = pDispApp->GetIDsOfNames [IID_NULL, &szFunction, 1,
LOCALE_USER_DEFAULT, &dispid_Books];
hr = pDispApp->Invoke [dispid_Books, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dpNoArgs, &vResult, NULL, NULL];
pDispXlBooks = vResult.pdispVal;
//DISPPARAMS for Open method
DISPID dispid_Open;
VARIANT vArgsOpen[5];
DISPPARAMS dpOpen;
dpOpen.cArgs = 5;
dpOpen.cNamedArgs = 0;
dpOpen.rgvarg = vArgsOpen;
char entry[25];
wchar_t wszPassWord[25];
printf["attempting dictionary attack...\n"];
while[in_fp.getline[entry, sizeof[entry]]]{
//again convert to bstr
MultiByteToWideChar[CP_ACP, 0, entry, -1,
wszPassWord, sizeof[wszPassWord]/sizeof[wszPassWord[0]]];
bstrPassWord = ::SysAllocString[wszPassWord];
vArgsOpen[4].vt = VT_BSTR;
vArgsOpen[4].bstrVal = bstrFileName; //Filename
vArgsOpen[3].vt = VT_ERROR;
vArgsOpen[3].scode = DISP_E_PARAMNOTFOUND; //Updatelinks - ommitted
vArgsOpen[2].vt = VT_BOOL;
vArgsOpen[2].scode = TRUE; //Open ReadOnly
vArgsOpen[1].vt = VT_ERROR;
vArgsOpen[1].scode = DISP_E_PARAMNOTFOUND; //file format - ommitted
vArgsOpen[0].vt = VT_BSTR;
vArgsOpen[0].bstrVal = bstrPassWord; //the file password;
//Invoke the Open method
szFunction = OLESTR["Open"];
hr = pDispXlBooks->GetIDsOfNames[IID_NULL, &szFunction, 1,
LOCALE_USER_DEFAULT, &dispid_Open];
hr = pDispXlBooks->Invoke[dispid_Open, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&dpOpen, NULL, NULL, NULL];
printf["."];
if [!FAILED[hr]]
break;
}
if [!FAILED[hr]] // the password was in the dictionary file
printf["\npassword is %s\n", entry];
else
printf["\nthe password was not found\n"];
//Invoke the Quit method
szFunction = OLESTR["Quit"];
hr = pDispApp->GetIDsOfNames[IID_NULL, &szFunction, 1,
LOCALE_USER_DEFAULT, &dispid_Quit];
hr = pDispApp->Invoke [dispid_Quit, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&dpNoArgs, NULL, NULL, NULL];
//Clean-up
::SysFreeString[bstrFileName];
::SysFreeString[bstrPassWord];
pDispXlBooks->Release[];
pDispApp->Release[];
pUnk->Release[];
::CoUninitialize[];
return 0;
}
Điều quan trọng bạn phải biết cách sử dụng các METHOD của các lớp giao diện IUnknown, IDispatch như: QueryInterface, GetIDsOfNames, Invoke Các thủ tục trong 2 lớp giao diện này cho phép làm việc với các đối tượng COM.
Bạn cần biết các thành phần của các đối tượng trong Excel như Application, Workbook, Worksheet, Range,... Nếu mới tiếp cận Excel, nên dùng chức năng "Record Macro" để biết các method/property của các đối tượng làm việc như thế nào [thông qua ngôn ngữ VB].