Подскажите пожалуйста, есть ли у кого пример кода чтения и записи данных из/в открытый ексель файл с помощью COM/OLE на чистом С++.
Есть микрософтовский пример: https://support.microsoft.com/en-us/help/216686/how-to-automate-excel-from-c-without-using-mfc-or-import
Он создает ексель файл и записывает в него данные, но как записать данные в уже в Открытый ексель файл, как этот ексель файл отловить, такого примера нет, а доработать/изменить микрософтовский примера под свою задачу, для меня на данный момент, к сожалению совершенно не возможно, настолько там все сложно.
Может кто нибудь делал нечто подобное.
Для подключения к запущенному экземпляру Excel необходимо использовать вызов GetActiveObject вместо CoCreateInstance. Далее, для получения доступа к открытому документу нужно заменить вызов метода Add на вызов свойства Item с индексом 1. Получаем такой код:
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <ole2.h> // OLE2 Definitions
// AutoWrap() - Automation helper function...
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
// Begin variable-argument list...
va_list marker;
va_start(marker, cArgs);
if (!pDisp) {
MessageBoxA(NULL, "NULL IDispatch passed to AutoWrap()", "Error", 0x10010);
_exit(0);
}
// Variables used...
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
HRESULT hr;
char buf[200];
char szName[200];
// 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)) {
printf("IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr);
getchar();
_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);
}
// 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)) {
printf("IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
getchar();
_exit(0);
return hr;
}
// End variable-argument section...
va_end(marker);
delete[] pArgs;
return hr;
}
int main(int argc, char **argv)
{
// Initialize COM for this thread...
CoInitialize(NULL);
// Get CLSID for our server...
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if (FAILED(hr)) {
::MessageBoxA(NULL, "CLSIDFromProgID() failed", "Error", 0x10010);
return -1;
}
IUnknown* pUnk;
hr = GetActiveObject(clsid, NULL, &pUnk);
if (FAILED(hr)) {
::MessageBoxA(NULL, "GetActiveObject failed!", "Error", 0x10010);
return -2;
}
IDispatch *pXlApp;
hr = pUnk->QueryInterface(IID_IDispatch, (void**)&pXlApp);
if (FAILED(hr)) {
::MessageBoxA(NULL, "QueryInterface failed!", "Error", 0x10010);
return -2;
}
// Make it visible (i.e. app.visible = 1)
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, (LPOLESTR)L"Visible", 1, x);
}
// Get Workbooks collection
IDispatch *pXlBooks;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"Workbooks", 0);
pXlBooks = result.pdispVal;
}
//Open workbook
IDispatch *pXlBook;
{
VARIANT result;
VariantInit(&result);
VARIANT index;
VariantInit(&index);
index.vt = VT_INT;
index.intVal = 1;
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, (LPOLESTR)L"Item",1, index);
pXlBook = result.pdispVal;
VariantClear(&index);
}
// Create a 15x15 safearray of variants...
VARIANT arr;
arr.vt = VT_ARRAY | VT_VARIANT;
{
SAFEARRAYBOUND sab[2];
sab[0].lLbound = 1; sab[0].cElements = 15;
sab[1].lLbound = 1; sab[1].cElements = 15;
arr.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
}
// Fill safearray with some values...
for (int i = 1; i <= 15; i++) {
for (int j = 1; j <= 15; j++) {
// Create entry value for (i,j)
VARIANT tmp;
tmp.vt = VT_I4;
tmp.lVal = i * j;
// Add to safearray...
long indices[] = { i,j };
SafeArrayPutElement(arr.parray, indices, (void *)&tmp);
}
}
// Get ActiveSheet object
IDispatch *pXlSheet;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"ActiveSheet", 0);
pXlSheet = result.pdispVal;
}
// Get Range object for the Range A1:O15...
IDispatch *pXlRange;
{
VARIANT parm;
parm.vt = VT_BSTR;
parm.bstrVal = ::SysAllocString(L"A1:O15");
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, (LPOLESTR)L"Range", 1, parm);
VariantClear(&parm);
pXlRange = result.pdispVal;
}
// Set range with our safearray...
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlRange, (LPOLESTR)L"Value", 1, arr);
// Save workbook
VARIANT var_result;
VariantInit(&var_result);
AutoWrap(DISPATCH_METHOD, &var_result, pXlBook, (LPOLESTR)L"Save", 0);
VariantClear(&var_result);
// Release references...
pUnk->Release();
pXlRange->Release();
pXlSheet->Release();
pXlBook->Release();
pXlBooks->Release();
pXlApp->Release();
VariantClear(&arr);
printf("All done! Press any key to exit\n");
getchar();
// Uninitialize COM for this thread...
CoUninitialize();
return 0;
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Столкнулся с интересным вопросом, причем ничего явно отвечающего на него в интернете не нашелСобственно, есть папка Program Files (x86)\Windows Kits/10/Include...