Форум программистов, компьютерный форум, киберфорум
C++: COM, OLE, ActiveX
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.74/58: Рейтинг темы: голосов - 58, средняя оценка - 4.74
19 / 18 / 1
Регистрация: 10.01.2017
Сообщений: 944
1

Чтение/запись в Excel с COM OLE C++

24.01.2019, 21:21. Просмотров 11394. Ответов 70
Метки нет (Все метки)

Здравствуйте,

Подскажите пожалуйста, есть ли у кого пример кода чтения и записи данных из/в откртый ексель файл с помощью COM/OLE на чистом С++.

Есть микрософтовский пример:
https://support.microsoft.com/... -or-import

Он создает ексель файл и записывает в него данные, но как записать данные в уже открытый ексель, как этот ексель файл отловить, такого примера нет, а доработать/изменить микрософтовский примера под свою задачу, для меня на данный момент, к сожалению совершенно не возможно, настолько там все сложно.

Может кто нибудь делал нечто подобное.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.01.2019, 21:21
Ответы с готовыми решениями:

Cpp builder-Ole-Excel. WideString пишет в ячейку Excel минус перед нулем
Здравствуйте! Посмотрите пожалуйста: Когда аргумент val == 0, в ячейку Excel пишется "-0". Без...

Общение с Excel через OLE
Недавно начал изучать с++. Использую ms vc++ 2010 express. Код такой // 2.cpp: определяет точку...

OLE. Как переименовать созданный файл в Excel.Application?
Доброго дня всем! Подскажите, как переименовать созданный файл в Excel? По умолчанию создается...

Задание диапазона ячеек при объединении (OLE-сервер Excel)
Добрый день. Столкнулась с такой проблемой: при работе с OLE-сервером Excel, при задании диапазона...

70
5842 / 3976 / 1630
Регистрация: 07.05.2019
Сообщений: 12,345
Записей в блоге: 1
30.01.2020, 20:54 61
Цитата Сообщение от Optimus11 Посмотреть сообщение
Что Msdn имеет ввиду под zero-length string ? Стока нулевой длинны. Это как ?
Просто пустая строка - ""; strlen("') == 0
1
19 / 18 / 1
Регистрация: 10.01.2017
Сообщений: 944
05.02.2020, 16:09  [ТС] 62
Подскажите пожалуйста, я правильно понимаю, что COM не дает возможность работать с файлом екселя, который не открыт ?
0
5842 / 3976 / 1630
Регистрация: 07.05.2019
Сообщений: 12,345
Записей в блоге: 1
05.02.2020, 16:50 63
Цитата Сообщение от Optimus11 Посмотреть сообщение
Подскажите пожалуйста, я правильно понимаю, что COM не дает возможность работать с файлом екселя, который не открыт ?
Да, правильно. Напрямую с файлом там ты работать не можешь. Ты создаёшь приложение Excel, которое будет работать с файлом.
0
652 / 211 / 21
Регистрация: 20.05.2016
Сообщений: 879
Записей в блоге: 15
24.11.2020, 18:04 64
Возможно ли забирать и передавать массив Variant-ов по ссылке или указателю (а не по значению)? Ибо операции получения данных и выгрузка на лист Excel дольше чем сам расчет.
Сейчас делаю так:

Automation helper function...
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// AutoWrap() - Automation helper function...
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
    va_list marker;// Begin variable-argument list...
    va_start(marker, cArgs);
    HRESULT hr = S_FALSE;
    if (!pDisp) {
        va_end(marker);
        return hr;
    }
    DISPPARAMS dp = { NULL, NULL, 0, 0 };// Variables used...
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    DISPID dispID;
    char szName[255];
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);// Convert down to ANSI
    hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);// Get DISPID for name passed...
    if (FAILED(hr)) {
        va_end(marker);
        return hr;
    }
    VARIANT *pArgs = new VARIANT[cArgs + 1];// Allocate memory for arguments...
    for (int i = 0; i < cArgs; i++) {// Extract arguments...
        pArgs[i] = va_arg(marker, VARIANT);
    }
    dp.cArgs = cArgs;// Build DISPPARAMS
    dp.rgvarg = pArgs;
    if (autoType & DISPATCH_PROPERTYPUT) {// Handle special-case for property-puts!
        dp.cNamedArgs = 1;
        dp.rgdispidNamedArgs = &dispidNamed;
    }
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);// Make the call!
    if (FAILED(hr)) {
        va_end(marker);
        delete[] pArgs;
        return hr;
    }
    va_end(marker);
    delete[] pArgs;
    return hr;
}

C++
1
2
3
4
5
6
7
8
9
10
11
CComPtr <IDispatch> Selection; {
        CComVariant result;
        if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Selection", 0) != S_OK) { MessageBox(hwndExcel, L"Selection: ", L"XLL", MB_OK | MB_ICONERROR); return; }
        Selection = result.pdispVal;    }
 
    CComVariant array_in_out;
    if (AutoWrap(DISPATCH_PROPERTYGET, &array_in_out, Selection, L"Value", 0) != S_OK) { MessageBox(hwndExcel, L"ValueGET: ", L"XLL", MB_OK | MB_ICONERROR); return; }
 
//что-то делаю с array_in_out и далее выкладываю
 
if (AutoWrap(DISPATCH_PROPERTYPUT, NULL, Selection, L"Value", 1, array_in_out) != S_OK) { MessageBox(hwndExcel, L"ValuePUT: ", L"XLL", MB_OK | MB_ICONERROR); return; }
0
2 / 2 / 0
Регистрация: 27.04.2015
Сообщений: 57
21.01.2021, 14:22 65
Приветствую всех читающих

Пытаюсь работать с Экселем через OLE, а в частности использую функцию AutoWrap со страницы примера автоматизации от MS.

При попытках выбрать нужный лист, оно не работает, выдает ошибку гласящую, как я понял, о том что объект не подключен к COM (0x800401FD).
Ниже описал последовательность действий ("лишнее" убрал, потому это не полный код).
И вот при выборе диапазона ячеек (Range) вылетает ошибка.

Если же использовать "ActiveSheet" то работает нормально...

Я полагаю ошибка именно в последовательности, но в руководстве к этим командам не нашел никаких оговорок.
Пробовал применять к книге и листу "Activate" - без толку (зачем вообще это нужно?).


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, _T("Workbooks"), 0);
    pXlBooks = result;
    AutoWrap(DISPATCH_METHOD, &result, pXlBooks, _T("Open"), 1, filePath);
    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, _T("Item"), 1, index);
    pXlBook = result;
    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBook, _T("Sheets"), 0);
    pXlSheets = result;
    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheets, _T("Item"), 1, index);
    pXlSheet = result;
    AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, _T("Range"), 1, parm);
    pXlRange = result;
0
19 / 18 / 1
Регистрация: 10.01.2017
Сообщений: 944
21.01.2021, 15:13  [ТС] 66
Цитата Сообщение от Foton6 Посмотреть сообщение
Приветствую всех читающих

Пытаюсь работать с Экселем через OLE, а в частности использую функцию AutoWrap со страницы примера автоматизации от MS.

При попытках выбрать нужный лист, оно не работает, выдает ошибку гласящую, как я понял, о том что объект не подключен к COM (0x800401FD).
Ниже описал последовательность действий ("лишнее" убрал, потому это не полный код).
И вот при выборе диапазона ячеек (Range) вылетает ошибка.

Если же использовать "ActiveSheet" то работает нормально...

Я полагаю ошибка именно в последовательности, но в руководстве к этим командам не нашел никаких оговорок.
Пробовал применять к книге и листу "Activate" - без толку (зачем вообще это нужно?).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
string Sheet_work_or_active = "ActiveSheet"; //  Или любое другое значение, если нужен лист по названию.
Sheet_name = "Name_List";                         //Название листа, если нужен лист по названию.
 
 
USES_CONVERSION; // Без этой штуки не работает A2OLE преобразование в LPOLESTR.
LPOLESTR Sheet_work_or_active_lpolestr = A2OLE(Sheet_work_or_active.c_str()); 
 
 
    int cArgs_parametr = 1;
        if (Sheet_work_or_active == "ActiveSheet")
        {
            cArgs_parametr = 0;
        }
        else
        {
            cArgs_parametr = 1;
        }
 
 
               //-------------------------------------------------------
        string textos_string_for_Sheet_Name;
        textos_string_for_Sheet_Name = Sheet_name;
        VARIANT Sheet_Name_bstr;
        Sheet_Name_bstr.vt = VT_BSTR;
        BSTR bstrTextos_for_Sheet_Name = _com_util::ConvertStringToBSTR(textos_string_for_Sheet_Name.c_str()); 
        Sheet_Name_bstr.bstrVal = ::SysAllocString(bstrTextos_for_Sheet_Name);
        VARIANT result;
        VariantInit(&result);
               //-------------------------------------------------------
 
 
 
        AutoWrap_write(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)Sheet_work_or_active_lpolestr, cArgs_parametr, Sheet_Name_bstr);
 
        pXlSheet = result.pdispVal;   //Этот AutoWrap возвращает имя Листа - активного или указанного по имени.
0
2 / 2 / 0
Регистрация: 27.04.2015
Сообщений: 57
21.01.2021, 15:36 67
Optimus11
Спасибо!
Но это как то не соответствует документации Оо
ActiveSheet - не должен принимать параметров: https://docs.microsoft.com/en-... ctivesheet

Да и выбирать лист по имени не очень удобно, по крайней мере мне хотелось бы по индексу.
Должен же быть более "правильный" способ работать с любым листом или я что-то не так понял?
А если несколько одноименных листов и в разных книга, то что выберется?
0
652 / 211 / 21
Регистрация: 20.05.2016
Сообщений: 879
Записей в блоге: 15
21.01.2021, 16:22 68
Foton6, вы что-то намудрили.
Вот, все работает нормально, массив забираю с листа нужного индекса
C++
1
2
3
4
5
6
7
    CComVariant array_in_out;
    {CComVariant result, p1(1), p2(L"A1:A2");
    if (AutoWrap(DISPATCH_PROPERTYGET, &result, pExcelDisp, L"Sheets", 0) != S_OK) { MessageBox(hwndExcel, L"Sheets: ", bedvitXLL, MB_OK | MB_ICONERROR); return -1; }
    if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"Item", 1, p1) != S_OK) { MessageBox(hwndExcel, L"Item: ", bedvitXLL, MB_OK | MB_ICONERROR); return -1; }
    if (AutoWrap(DISPATCH_PROPERTYGET, &result, result.pdispVal, L"Range", 1, p2) != S_OK) { MessageBox(hwndExcel, L"Range: ", bedvitXLL, MB_OK | MB_ICONERROR); return -1; }
    if (AutoWrap(DISPATCH_PROPERTYGET, &array_in_out, result.pdispVal, L"Value", 0) != S_OK) { MessageBox(hwndExcel, L"ValueGET: ", bedvitXLL, MB_OK | MB_ICONERROR); return -1; }
    }
0
2 / 2 / 0
Регистрация: 27.04.2015
Сообщений: 57
21.01.2021, 16:54 69
bedvit
Мдаааа, опять видимо моя невнимательность сыграла, сейчас все работает хотя ничего не трогал можно сказать Оо
Ну и ладненько, а то я уж было подумал надо каждый объект активировать перед тем как с ним работать О.О
0
2 / 2 / 0
Регистрация: 27.04.2015
Сообщений: 57
22.01.2021, 00:39 70
Опять возник затык...
Пытаюсь очистить выбранный "Range" при помощи "Clear" или "ClearContents", но вылетает ошибка: 0x800a03ec

Методом тыка выяснил что это происходит при попытке чистить объединенные ячейки.
Попробовал вместо них использовать "Delete", но тогда прилетает диалог предупреждающий о потере данных и необходимости принять волевое решение и нажать да или нет.

Как с этим быть подскажите?
>_<

А пока гуглил приведенный номер ошибки выяснил что она может вылетать если новым экселем (2010+) открыть xls
и пытаться манипулировать ячейками в которых первым символом идет " = ". И единственный совет: убедитесь что у вас ни одна ячейка не начинается с "="...
0
2 / 2 / 0
Регистрация: 27.04.2015
Сообщений: 57
22.01.2021, 22:14 71
Хм, если записываемое значение это строка и она начинается с символа "=" то прилетает ошибка 0x80020009.

-6 часов, прелесть.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.01.2021, 22:14

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Чтение из Excel в StringGrid
Здравствуйте! Как считать информацию из открытого файла Excel в StringGrid? Пробовала вот так: ...

Работа с БД SQLite 3: чтение, запись
есть бд SQLite 3, раньше с SQLite не работал, подскажите как от туда считать данные и записать их...

Чтение данных из Excel с Visual C++
Здраствуйте. Нужно запрограммировать считывание данных из Excel-файла на Visual C++ (MVS 2005)....

Запись и чтение Excel
Здраствуйте. Подскажите как реализировать возможность записывать информацию с полей в лист Excel....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
71
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.