-
May 23rd, 2013, 06:03 PM
#1
COleVariant in WinAPI (afxdisp.h)
Hey ho...
guess i need some help of experts again.. wanna export listview to MS excel. i found a really nice article on this:
http://www.codeproject.com/Articles/...mation-Using-C
however the only one thing that does not seem to work with my OLE is COleVariant class.
It's simply not declared. I tried adding afxdisp.h but it's not a standard lib in my Microsoft Visual Visual Studio Express 2012 and it seems to be very specific to MFC.
I tried to add it manually from internet but it's then referring (calling) to other *.h
is there any way to either replace COleVariant with VARIANT (or something) or add afxdisp.h (and all connected libs) to my program?
i wanna achieve this :
Code:
IDispatch* pRange;
{
COleVariant oleRange(szCell);
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, oleRange.Detach());
pRange = result.pdispVal;
}
will be grateful for any hint!
thanks
.
-
May 24th, 2013, 07:53 AM
#2
Re: COleVariant in WinAPI (afxdisp.h)
COleVariant is a c++ wrapper class around VARIANT
so yes, you can use VARIANT but you'll have to do all the conversions to/from yourself.
-
May 24th, 2013, 05:28 PM
#3
Re: COleVariant in WinAPI (afxdisp.h)
it doesnt really help coz i simply donno how to do this.
i would like to use ATL and MFC libs in my VC Express 2012 version. i tried few links with using SDK but all refer to old version of SDK and VC Express 2008 which is completely different to mine.
There must be some way to put those lib into my program.
-
May 26th, 2013, 03:11 AM
#4
Re: COleVariant in WinAPI (afxdisp.h)
Ok.. I tried to run it with ATL and MFC libs, i installed 30days version of VC Prof 2012, and although COleVariant worked, there is a lot of dependencies when i started adding ATL libs. i cannot even compile my program with windows.h anymore coz ATL does not go along with win32 app, i got hundred of warnings and errors, i permanently gave up with this approach.
I guess my last chance now is to find some way to convert COleVariant to something else.
original code:
Code:
IDispatch* pRange;
{
LPCTSTR szRange = "a1";
COleVariant oleRange(szRange);
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, oleRange.Detach());
pRange = result.pdispVal;
}
i would like to change it to something like this:
Code:
IDispatch* pRange;
{
VARIANT xx;
xx.vt=VT_I1;
xx.pcVal="a1";
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, functionDetach(xx));
pRange = result.pdispVal;
}
does anyone have any idea how that functionDetach(xx) should look like to give me the same result as COleVariantClass.Detach()?
-
May 26th, 2013, 08:33 AM
#5
Re: COleVariant in WinAPI (afxdisp.h)
MSDN does know it for sure!
COleVariant:etach
So just pass in your xx instead of "functionDetach(xx)"!
Victor Nijegorodov
-
May 26th, 2013, 09:45 AM
#6
Re: COleVariant in WinAPI (afxdisp.h)
Hi Victor,
tried that but then the OLEMethod function breaks at Invoking:
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);
The code of OLEMethod:
Code:
HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...)
{
if(!pDisp) return E_FAIL;
va_list marker;
va_start(marker, cArgs);
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
char szName[200];
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
// Get DISPID for name passed...
HRESULT hr= pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
if(FAILED(hr)) {
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(nType & DISPATCH_PROPERTYPUT) {
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call!
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);
if(FAILED(hr)) {
return hr;
}
// End variable-argument section...
va_end(marker);
delete [] pArgs;
return hr;
}
The error says:
Unhandled exception at 0x750E80EE (oleaut32.dll) in Kredens (OLE aut).exe: 0xC0000005: Access violation writing location 0x010B8074
I will only add that the OLEMethod works correctly coz it does NOT break at e.g:
Code:
IDispatch *pSheet;
{
VARIANT result;
VariantInit(&result);
VARIANT itemn;
itemn.vt = VT_I4;
itemn.lVal = 1;
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheets, L"Item", 1, itemn);
pSheet = result.pdispVal;
}
-
May 26th, 2013, 10:24 AM
#7
Re: COleVariant in WinAPI (afxdisp.h)
Originally Posted by berkov
i would like to change it to something like this:
Code:
IDispatch* pRange;
{
VARIANT xx;
xx.vt=VT_I1;
xx.pcVal="a1";
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, functionDetach(xx));
pRange = result.pdispVal;
}
Sorry! I missed this erroneos assignments.
VT_I1 means theat the value is of type char (one and only one char symbol!) while you are trying to pass in the char* (a ponther to char array)
Try to change your code to be:
Code:
VARIANT xx;
xx.vt=VT_BSTR;
xx.pcVal= L"a1";
Victor Nijegorodov
-
May 26th, 2013, 11:07 AM
#8
Re: COleVariant in WinAPI (afxdisp.h)
Ah, you are right, didn't see it.
i tried it and now it seems the BSTR does not take the UNICODE:
IntelliSense: a value of type "const wchar_t *" cannot be assigned to an entity of type "CHAR *"
i had to remove that "L" and put it like this:
xx.pcVal = "a1";
and unfortunately i got the same error on runtime as at the beginning.
any other ideas?
-
May 26th, 2013, 11:21 AM
#9
Re: COleVariant in WinAPI (afxdisp.h)
Is your build an ANSI or UNICODE?
Anyway, you should always use _T() macro for text/symbol constants.
Victor Nijegorodov
-
May 26th, 2013, 11:39 AM
#10
Re: COleVariant in WinAPI (afxdisp.h)
The project is "Use Multi-Byte Character Set".
i tried it with _T("a1") and still the same error.
-
May 26th, 2013, 11:48 AM
#11
Re: COleVariant in WinAPI (afxdisp.h)
Ok, then let's begin from the very begin! What error exactly do you have? Where? Please, show your actual code.
Victor Nijegorodov
-
May 26th, 2013, 12:14 PM
#12
Re: COleVariant in WinAPI (afxdisp.h)
hmm.. the code is very long, it has a lot of pages as i've been writing it for 4 months now.
but i will try to copy the most important parts:
xls.cpp:
Code:
#include <windows.h>
#include "xls.h"
#include "classes.h"
#include "resources.h"
#include "Tchar.h"
HRESULT hr2;
HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...)
{
if(!pDisp) return E_FAIL;
va_list marker;
va_start(marker, cArgs);
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
char szName[200];
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
// Get DISPID for name passed...
HRESULT hr= pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
if(FAILED(hr)) {
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(nType & DISPATCH_PROPERTYPUT) {
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call!
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);
if(FAILED(hr)) {
return hr;
}
// End variable-argument section...
va_end(marker);
delete [] pArgs;
return hr;
}
CMSExcel::CMSExcel(void)
{
m_hr=S_OK;
m_pEApp=NULL;
m_pBooks=NULL;
m_pActiveBook=NULL;
}
HRESULT CMSExcel::Initialize(bool bVisible)
{
CoInitialize(NULL);
CLSID clsid;
m_hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if(SUCCEEDED(m_hr))
{
m_hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&m_pEApp);
if(FAILED(m_hr)) m_pEApp=NULL;
}
{
m_hr=SetVisible(bVisible);
}
return m_hr;
}
HRESULT CMSExcel::SetVisible(bool bVisible)
{
if(!m_pEApp) return E_FAIL;
VARIANT x;
x.vt = VT_I4;
x.lVal = bVisible;
m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, m_pEApp, L"Visible", 1, x);
return m_hr;
}
HRESULT CMSExcel::NewExcelBook(bool bVisible)
{
if(m_pEApp==NULL)
{
if(FAILED(m_hr=Initialize(bVisible)))
return m_hr;
}
{
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, m_pEApp, L"Workbooks", 0);
m_pBooks = result.pdispVal;
}
{
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_METHOD, &result, m_pBooks, L"Add", 0);
m_pActiveBook = result.pdispVal;
}
return m_hr;
}
HRESULT CMSExcel::SetExcelValue(LPCTSTR szRange,LPCTSTR szValue,bool bAutoFit, int nAlignment)
{
if(!m_pEApp) return E_FAIL;
if(!m_pActiveBook) return E_FAIL;
IDispatch *pSheets;
{
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, m_pActiveBook, L"Sheets", 0);
pSheets = result.pdispVal;
}
IDispatch *pSheet;
{
VARIANT result;
VariantInit(&result);
VARIANT itemn;
itemn.vt = VT_I4;
itemn.lVal = 1;
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheets, L"Item", 1, itemn);
pSheet = result.pdispVal;
}
IDispatch* pRange;
{
//COleVariant oleRange(szRange);
VARIANT xx;
xx.vt=VT_BSTR;
xx.pcVal = _T("a1");
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, xx);
pRange = result.pdispVal;
}
{
//COleVariant oleValue(szValue);
m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, pRange, L"Value", 1, "aa");
}
if(bAutoFit)
{
IDispatch* pEntireColumn;
{
VARIANT result;
VariantInit(&result);
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pRange, L"EntireColumn",0);
pEntireColumn= result.pdispVal;
}
{
m_hr=OLEMethod(DISPATCH_METHOD, NULL, pEntireColumn, L"AutoFit", 0);
}
pEntireColumn->Release();
}
{
VARIANT x;
x.vt = VT_I4;
x.lVal = nAlignment;
m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, pRange, L"HorizontalAlignment", 1, x);
}
pRange->Release();
pSheet->Release();
pSheets->Release();
return m_hr;
}
HRESULT CMSExcel::Quit()
{
if(m_pEApp==NULL) return E_FAIL;
DISPID dispID;
LPOLESTR ptName=(LPOLESTR)"Quit";// LPOLESTR ptName=_T("Quit");
m_hr = m_pEApp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
if(SUCCEEDED(m_hr))
{
DISPPARAMS dp = { NULL, NULL, 0, 0 };
m_hr = m_pEApp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
&dp, NULL, NULL, NULL);
}
m_pEApp->Release();
m_pEApp=NULL;
return m_hr;
}
CMSExcel::~CMSExcel(void)
{
Quit();
CoUninitialize();
}
xls.h:
Code:
#include "classes.h"
#ifndef xls_h
#define xls_h
class CMSExcel
{
protected:
HRESULT m_hr;
IDispatch* m_pEApp;
IDispatch* m_pBooks;
IDispatch* m_pActiveBook;
private:
HRESULT Initialize(bool bVisible=true);
public:
CMSExcel(void);
~CMSExcel(void);
HRESULT SetVisible(bool bVisible=true);
HRESULT NewExcelBook(bool bVisible=true);
HRESULT SetExcelValue(LPCTSTR szRange,LPCTSTR szValue,bool bAutoFit, int nAlignment);
HRESULT Quit();
};
HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...);
#endif
and let's say that i call this somewhere from main.cpp:
Code:
CMSExcel xx;
xx.NewExcelBook(true);
xx.SetExcelValue("a2","1",true,1);
The error is:
Unhandled exception at 0x00B996C3 in Kredens (OLE aut).exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.
and it's caused in OLEMEthos function at the line:
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
where this OLEMethod is called by (/from):
m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, xx);
I guess i did some stupid mistake when i was copying the code from some example, not fully understanding it.
I believe you are right saying that it must have somethign to do with that conversion thing which i dont quite understand yet.
-
May 26th, 2013, 12:29 PM
#13
-
May 26th, 2013, 12:38 PM
#14
Re: COleVariant in WinAPI (afxdisp.h)
In xls.cpp
Code:
char szName[200];
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
szName is defined as size 200, but WideCharToMultiByte is told that is is 256!
Also, you are not testing the return value from WideCharToMultiByte to determine if the function succeeded or failed.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
May 26th, 2013, 12:49 PM
#15
Re: COleVariant in WinAPI (afxdisp.h)
Originally Posted by 2kaud
szName is defined as size 200, but WideCharToMultiByte is told that is is 256!
Good catch!
Victor Nijegorodov
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|