Как получить значение ячейки Excel в C ++ - PullRequest
2 голосов
/ 23 декабря 2011

Если кто-то знает, как перейти от Excel :: Window к реальному значению в открытой ячейке Excel, пожалуйста, дайте мне знать. Вот условия задачи: - Excel в настоящее время работает в одном окне с одной книгой на одном листе - у некоторых ячеек есть данные (для упрощения, скажем, только у одной ячейки [1,1] есть данные, то есть «а») Вопрос в том, как узнать, что данные есть только в одной ячейке, а ячейка - [1,1], а данные - «а». Для начала вот фрагмент кода:

int main( int argc, CHAR* argv[])
{
   CoInitialize( NULL );
   HWND excelWindow = FindWindow(L"XLMAIN", NULL);
   EnumChildWindows(excelWindow, (WNDENUMPROC) EnumChildProc, (LPARAM)1);
   return 0;
}
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM)
{
   WCHAR szClassName[64];
   if(GetClassNameW(hwnd, szClassName, 64))
   {
      if(_wcsicmp(szClassName, L"EXCEL7") == 0)
      {
         Excel::Window* pWindow = NULL;
         HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, __uuidof(Excel::Window), (void**)&pWindow);
         if(hr == S_OK)
         {
            // Here we need to answer the question using pWindow                
            pWindow->Release();
         }
         return false;     
      }     
   }
   return true;
}  

Ответы [ 2 ]

4 голосов
/ 04 января 2012

Вот наконец используемый код:

#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();
}

Функция AutoWrap () была взята из http://support.microsoft.com/kb/216686/en-us?fr=1,, а начальная выборка из http://www.northatlantawebdesign.com/index.php/2009/07/15/access-microsoft-excel-2007-com-api-through-microsoft-active-accessibility/ Спасибо всем, кто помог.

0 голосов
/ 24 декабря 2011

Daniil,

Я полагаю, что вы используете Excel COM для доступа к нему. Я никогда не делал этого с помощью C ++, но я думаю, что он не должен сильно отличаться от C #. Ваша самая сложная задача - импортировать необходимые библиотеки для этого. Но я верю, что вы уже сделали это.

Вы должны использовать что-то вроде этого:

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;
        }
     }
}

Обратите внимание, я не проверял этот код. Я просто показываю вам, как это должно выглядеть. Вы должны прочитать документацию здесь: http://msdn.microsoft.com/en-us/library/ms262200.aspx и использовать ее соответствующим образом.

Надеюсь, это поможет.

...