How to get Excel cell value in C++

前端 未结 2 1993
夕颜
夕颜 2021-02-06 18:42

If someone knows how to go from Excel::Window pointer to real value in opened Excel cell, please let me know. Here is the task conditions: - Excel is currently running in one s

2条回答
  •  遇见更好的自我
    2021-02-06 19:16

    Here is code finally used:

    #include 
    #include 
    #import "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE14\MSO.DLL" no_implementation rename("RGB", "ExclRGB") rename("DocumentProperties", "ExclDocumentProperties") rename("SearchPath", "ExclSearchPath")
    #import "C:\Program Files (x86)\Common Files\microsoft shared\VBA\VBA6\VBE6EXT.OLB" no_implementation
    #import "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE" rename("DialogBox", "ExclDialogBox") rename("RGB", "ExclRGB") rename("CopyFile", "ExclCopyFile") rename("ReplaceText", "ExclReplaceText")
    #include 
    using std::string;
    
    BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)
    {
        WCHAR szClassName[64];
        if(GetClassNameW(hwnd, szClassName, 64))
        {
            if(_wcsicmp(szClassName, L"EXCEL7") == 0)
            {
                //Get AccessibleObject
                Excel::Window* pWindow = NULL;
                IDispatch* pXlSheet = NULL;
                HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, __uuidof(Excel::Window), (void**)&pWindow);
                if(hr == S_OK)
                {               
                    try {
                        VARIANT result;
                        VariantInit(&result);
                        AutoWrap(DISPATCH_PROPERTYGET, &result, pWindow, L"ActiveSheet", 0);
                        pXlSheet = result.pdispVal;
                        _variant_t sheetName;
                        VariantInit(&sheetName);
                        if ((pXlSheet != NULL) && (pXlSheet != (IDispatch*)0xCCCCCCCC))
                        AutoWrap(DISPATCH_PROPERTYGET, &sheetName, pXlSheet, L"Name", 0); 
    
                        // get cell which you need
                        string location = "C5"; 
                        location += ":" + location; // cell is a range with the same start/end cells
                        OLECHAR *sOleText=new OLECHAR[location.length()+1];
                        mbstowcs(sOleText,location.c_str(),location.length()+1);
    
                        IDispatch *pXlRange; // Get Range from Sheet
                        VARIANT parm;
                        parm.vt = VT_BSTR;
                        parm.bstrVal = ::SysAllocString(sOleText); 
                        VARIANT result;
                        VariantInit(&result);
                        AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, L"Range", 1, parm);
                        VariantClear(&parm);
                        pXlRange = result.pdispVal;
                        Excel::RangePtr cell = pXlRange;
                        Excel::CharactersPtr ptr = cell->Characters;
                        _bstr_t text = ptr->Text; // here is needed text
                    } catch (...) { }
                }
                return false;     // Stops enumerating through children
            }       
        }
        return true;
    }
    
    void main( int argc, CHAR* argv[])
    {
        CoInitialize(NULL);
        HWND excelWindow = FindWindow(L"XLMAIN", NULL);
        EnumChildWindows(excelWindow, (WNDENUMPROC) EnumChildProc, (LPARAM)1);
        CoUninitialize();
    }
    

    The AutoWrap() function has been taken from http://support.microsoft.com/kb/216686/en-us?fr=1, while the initial sample from http://www.northatlantawebdesign.com/index.php/2009/07/15/access-microsoft-excel-2007-com-api-through-microsoft-active-accessibility/ Thanks to all who helped.

提交回复
热议问题