Здравствуйте!
Есть такой класс.
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;
Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.
Здравствуйте, SISerge, Вы писали:
SIS>SIS>ExcelApp app;
SIS>app.Create();
SIS>app.Workbook[i].Worksheet[i].Rows.Count;
SIS>
SIS>Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.
Если пишешь фреймворк с которым будут мн6ого работать то пиши так. В остальных случаях придерживайся KISS Principle. Не фиг классы плодить только для того чтобы написать строку кода покрасивей. Кроме того если использовать type library то компилятор тебе сам классы нагенерит чтобы ты мог писать app.Workbook[i].Worksheet[i].Rows.Count;
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Здравствуйте, Anatolix, Вы писали:
A>Здравствуйте, SISerge, Вы писали:
SIS>>SIS>>ExcelApp app;
SIS>>app.Create();
SIS>>app.Workbook[i].Worksheet[i].Rows.Count;
SIS>>
SIS>>Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.
A>Если пишешь фреймворк с которым будут мн6ого работать то пиши так. В остальных случаях придерживайся KISS Principle. Не фиг классы плодить только для того чтобы написать строку кода покрасивей. Кроме того если использовать type library то компилятор тебе сам классы нагенерит чтобы ты мог писать app.Workbook[i].Worksheet[i].Rows.Count;
А про KISS Principle где можно почитать?