How to get Excel cell value in C++

前端 未结 2 1987
夕颜
夕颜 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 <windows.h>
    #include <oleacc.h>
    #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 <string>
    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.

    0 讨论(0)
  • 2021-02-06 19:19

    Daniil,

    I believe you are using the Excel COM to access it. I've never done this using C++, but I guess it shouldn't be much different than C#. Your toughest task should be importing the necessary libraries to do so. But I believe you have done that already.

    You should use something like this:

    int full_cells = 0;
    Excel::_Worksheet worksheet = pWindow->ActiveSheet;
    for(int j = 1; j < worksheet.Columns.Count; j++)
    {
        for (int i = 1; i < worksheet.Rows.Count; i++)
        {
            if(worksheet.Cells[i][j].Value != "")
            {
                full_cells++;
                cout << worksheet.Cells[i][j].Value;
            }
         }
    }
    

    Please note I haven't tested this code. I'm just showing you what it is supposed to look like. You should read the documentation here: http://msdn.microsoft.com/en-us/library/ms262200.aspx and use it appropriately.

    Hope it helps.

    0 讨论(0)
提交回复
热议问题