Здравствуйте!
Есть такой класс.
excel.h
class ExcelApp
{
private:
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...);
HRESULT Init();
CLSID clsid;
HRESULT hr;
IDispatch *pXlApp;
IDispatch *pXlBooks;
IDispatch *pXlBook;
IDispatch *pXlSheet;
VARIANT result;
IDispatch* GetWorkBooks();
IDispatch* AddWorkBook();
IDispatch* GetActiveSheet();
IDispatch* GetActiveBook();
IDispatch* GetActiveCell(int r,int c);
VARIANT x,x1,x2;
DISPPARAMS dp;
DISPID dispidNamed;
DISPID dispID;
char buf[200];
char szName[200];
public:
BOOL Open(CString filename);
BOOL Create();
BOOL Create(CString filename);
void Release();
void Visible(BOOL Scr=true);
void SetCellValue(int r,int c,CString); //r-ïî âåðòèêàëè c-ïî ãîðèçîíòàëè,
CString GetCellValue(int r,int c);
void CloseApp();
int RowCount();
};
excel.cpp
#include "excel.h"
HRESULT ExcelApp::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, "IDispatch=NULL ïåðåäàí â AutoWrap()", "Error", 0x10010);
_exit(0);
}
dp.cArgs = NULL;
dp.cNamedArgs=NULL;
dp.rgdispidNamedArgs=0;
dp.rgvarg=0;
dispidNamed = DISPID_PROPERTYPUT;
// 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);
};
dp.cNamedArgs=0;
dp.rgdispidNamedArgs=NULL;
dispidNamed = DISPID_PROPERTYPUT;
// 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;
}
HRESULT ExcelApp::Init()
{
CoInitialize(NULL);
// Get CLSID for our server...
hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if(FAILED(hr)) {
::MessageBox(NULL, "CLSID<>ProgID(). Init() failed", "Error", 0x10010);
return -1;
}
// Start server and get IDispatch...
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pXlApp);
if(FAILED(hr)) {
::MessageBox(NULL, "Ïðîáëåìû ñ Excel â Âàøåé ñèñòåìå!", "Error", 0x10010);
return -2;
}
return hr;
}
BOOL ExcelApp::Create()
{
if(FAILED(Init()))
{
::MessageBox(NULL, "Ýêçåìïëàð êëàññà íå ñîçäàí!", "Error", 0x10010);
return false;
}
pXlBooks = GetWorkBooks();
pXlBook = AddWorkBook();
pXlSheet = GetActiveSheet();
return true;
}
IDispatch* ExcelApp::GetWorkBooks()
{
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"Workbooks", 0);
return result.pdispVal;
}
IDispatch* ExcelApp::AddWorkBook()
{
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, L"Add", 0);
return result.pdispVal;
}
IDispatch* ExcelApp::GetActiveSheet()
{
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveSheet", 0);
return result.pdispVal;
}
IDispatch* ExcelApp::GetActiveBook()
{
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveWorkbook", 0);
return result.pdispVal;
}
void ExcelApp::Visible(BOOL Scr)
{
x.vt = VT_I4;
x.lVal = Scr;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x);
}
BOOL ExcelApp::Open(CString filename)
{
if(FAILED(Init()))
{
::MessageBox(NULL, "Ýêçåìïëàð êëàññà íå ñîçäàí!", "Error", 0x10010);
return false;
}
x.vt = VT_BSTR;
x.bstrVal = filename.AllocSysString();
pXlBooks = GetWorkBooks();
AutoWrap(DISPATCH_METHOD, NULL, pXlBooks,L"Open", 1,x);
::SysFreeString(x.bstrVal);
pXlBook=GetActiveBook();
pXlSheet=GetActiveSheet();
return true;
}
BOOL ExcelApp::Create(CString filename)
{
if(!Create())return false;
x.vt = VT_BSTR;
x.bstrVal = filename.AllocSysString();
//pXlBooks = GetWorkBooks();
//pXlBook=GetActiveBook();
//pXlSheet=GetActiveSheet();
AutoWrap(DISPATCH_METHOD, NULL, pXlBook,L"SaveAs", 1,x);
::SysFreeString(x.bstrVal);
return true;
}
void ExcelApp::Release()
{
if(pXlSheet!=NULL)pXlSheet->Release();
if(pXlBook!=NULL)pXlBook->Release();
if(pXlBooks!=NULL)pXlBooks->Release();
if(pXlApp!=NULL)pXlApp->Release();
CoUninitialize();
}
void ExcelApp::SetCellValue(int r,int c,CString value)
{
x2.vt=VT_BSTR;
x2.bstrVal=value.AllocSysString();
IDispatch* pXlCells=GetActiveCell(r,c);
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlCells, L"Cells", 1, x2);
::SysFreeString(x2.bstrVal);
pXlCells->Release();
}
IDispatch* ExcelApp::GetActiveCell(int r,int c)
{
VariantInit(&result);
x.vt=VT_I4;
x.lVal=r;
x1.vt=VT_I4;
x1.lVal=c;
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, L"Cells", 2, x1,x);
return result.pdispVal;
}
CString ExcelApp::GetCellValue(int r,int c)
{
IDispatch* pXlCells=GetActiveCell(r,c);
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET,&result, pXlCells, L"Value", 0);
pXlCells->Release();
return result.bstrVal;
}
void ExcelApp::CloseApp()
{
AutoWrap(DISPATCH_METHOD, NULL, pXlBooks,L"Close", 0);
}
int ExcelApp::RowCount()
{
IDispatch *Rows;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET,&result, pXlSheet, L"Rows", 0);
Rows=result.pdispVal;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET,&result, Rows, L"Count", 0);
return result.intVal;
}
В нем обращение к методам идет так:
ExcelApp app;
app.Create();
app.RowCount();
и т.д.
Как можно создать иерархию классов, чтобы обращение к методам шло типа вот так:
ExcelApp app;
app.Create();
app.Workbook[i].Worksheet[i].Rows.Count;
Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.