Follow these steps to create a Visual C++ 6.0 that automates simple Excel:
1. Start Visual C++ 6.0 and create a new Win32 console application called XlCpp. Choose an application "Hello, World!" And click Finish.
2. Open the file generated XlCpp.cpp and add the following code before the main function ():
Code:
# Include <ole2.h> / / OLE2 Definitions
/ / AutoWrap () - Automation helper function ...
HRESULT AutoWrap (int Autotype, VARIANT * pvResult, IDispatch * pDisp, LPOLESTR ptName, int carga ...) {
/ / Begin variable-argument list ...
va_marklist;
va_begin (marker, carga);
if (! pDisp) {
MessageBox (NULL, "NULL IDispatch Passed to AutoWrap ()", "Error", 0x10010);
_exit (0);
}
/ / Variables used ...
DISPPARAMS disparam = {NULL, NULL, 0, 0};
DISPID = dispidNamed DISPID_PROPERTYPUT;
DISPID dpID;
HRESULT hresult;
char buffer [200];
char Namesize [200];
/ / Convert down to ANSI
WideCharToMultiByte (CP_ACP, 0, ptName, -1, Namesize, 256, NULL, NULL);
/ / Get DISPID for name Passed ...
hresult = pDisp-> GetIDsOfNames (IID_NULL, & ptName, 1, LOCALE_USER_DEFAULT, & dpID);
if (FAILED (hresult)) {
sprintf (buffer, "IDispatch:: GetIDsOfNames (\"% s \ ") failed w / err 0x% 08lx", Namesize, hresult);
MessageBox (NULL, buffer, "AutoWrap ()", 0x10010);
_exit (0);
return hresult;
}
/ / Allocate memory for arguments ...
VARIANT * parga = new VARIANT [carga +1];
/ / Extract arguments ...
for (int i = 0; i <carga; i + +) {
parga [i] = va_arg (marker, VARIANT);
}
/ / Build DISPPARAMS
disparam.cArgs = carga;
disparam.rgvarg = parga;
/ / Handle special-case for property-puts!
if (autotype & DISPATCH_PROPERTYPUT) {
disparam.cNamedArgs = 1;
disparam.rgdpIDNamedArgs dpIDNamed = &;
}
/ / Make the call!
hresult = pDisp-> Invoke (dpID, IID_NULL, LOCALE_SYSTEM_DEFAULT, Autotype, & disparam, pvResult, NULL, NULL);
if (FAILED (hresult)) {
sprintf (buffer, "IDispatch:: Invoke (\"% s \ "=% 08lx) failed w / err 0x% 08lx", Namesize, dpID, hresult);
MessageBox (NULL, buffer, "AutoWrap ()", 0x10010);
_exit (0);
return hresult;
}
/ / End variable-argument section ...
va_end (marker);
delete [] parga;
return hresult;
}
3. In the function main (), replace the line printf () with the following code:
Code:
/ / Initialize COM for this thread ...
CoInitialize (NULL);
/ / Get CLSID for Our server ...
CLSID clsid;
HRESULT hresult = CLSIDFromProgID (L "Excel.Application", & clsid);
if (FAILED (hresult)) {
:: MessageBox (NULL, "CLSIDFromProgID () failed", "Error", 0x10010);
return -1;
}
/ / Start server and get IDispatch ...
IDispatch * pXlApp;
hresult = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **) & pXlApp);
if (FAILED (hresult)) {
:: MessageBox (NULL, "Excel not registered Properly", "Error", 0x10010);
return -2;
}
/ / Make it visible (ie 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 SAFEARRAY of variants 15x15 ...
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 gains ...
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 object ActiveSheet
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 paramet;
paramet.vt = VT_BSTR;
paramet.bstrVal =:: SysAllocString (L "A1: O15");
VARIANT result;
VariantInit (& result);
AutoWrap (DISPATCH_PROPERTYGET, & result, pXlSheet, L "Range", 1, paramet);
VariantClear (& paramet);
pXlRange = result.pdispVal;
}
/ / Set range safearray With Our ...
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 arent 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 (ie 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 ();
4. Compile and run.
AutoWrap function () simplifies most of the low-level details involved in the direct use of IDispatch. Feel free to use in your own implementations. However, if you pass multiple parameters, you must do so in reverse order.
Code:
For example:
VARIANT paramet [3];
paramet [0]. vt = VT_I4; paramet [0]. lVal = 1;
paramet [1]. vt = VT_I4; paramet [1]. lVal = 2;
paramet [2]. vt = VT_I4; paramet [2]. lVal = 3;
AutoWrap (DISPATCH_METHOD, NULL, pDisp, The "call", 3, paramet [2], paramet [1], paramet [0]);
Bookmarks