ОО проектирование в С++
От: SISerge  
Дата: 06.01.05 03:53
Оценка:
Здравствуйте!

Есть такой класс.


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, "&Iuml;&eth;&icirc;&aacute;&euml;&aring;&igrave;&ucirc; &ntilde; Excel &acirc; &Acirc;&agrave;&oslash;&aring;&eacute; &ntilde;&egrave;&ntilde;&ograve;&aring;&igrave;&aring;!", "Error", 0x10010);
      return -2;
   }
   return hr;
}

BOOL ExcelApp::Create()
{
    if(FAILED(Init()))
    {
        ::MessageBox(NULL, "&Yacute;&ecirc;&ccedil;&aring;&igrave;&iuml;&euml;&agrave;&eth; &ecirc;&euml;&agrave;&ntilde;&ntilde;&agrave; &iacute;&aring; &ntilde;&icirc;&ccedil;&auml;&agrave;&iacute;!", "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, "&Yacute;&ecirc;&ccedil;&aring;&igrave;&iuml;&euml;&agrave;&eth; &ecirc;&euml;&agrave;&ntilde;&ntilde;&agrave; &iacute;&aring; &ntilde;&icirc;&ccedil;&auml;&agrave;&iacute;!", "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;


Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.