ОО проектирование в С++
От: 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;


Я в проектировании полный ламер, так что просьба не смеяться, а внимательно почитать код. И желательно ответить.
Re: ОО проектирование в С++
От: KBH  
Дата: 06.01.05 06:48
Оценка:
Здравствуйте, SISerge, Вы писали:

SIS>Здравствуйте!...


гы... C++ изучай.
Re[2]: ОО проектирование в С++
От: SISerge  
Дата: 06.01.05 07:02
Оценка:
Здравствуйте, KBH, Вы писали:

KBH>Здравствуйте, SISerge, Вы писали:


SIS>>Здравствуйте!...


KBH>гы... C++ изучай.


Дык... Изучил уже. Можно тему закрыть.
Re: ОО проектирование в С++
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 10.01.05 11:42
Оценка:
Здравствуйте, 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;
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re[2]: ОО проектирование в С++
От: SISerge  
Дата: 10.01.05 11:56
Оценка:
Здравствуйте, 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 где можно почитать?
Re[3]: ОО проектирование в С++
От: Максим Зелински Россия  
Дата: 10.01.05 13:58
Оценка:
Здравствуйте, SISerge, Вы писали:

SIS>А про KISS Principle где можно почитать?

Keep It Simple Stupid.
Просьба не обижаться
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.