I'm new with Embarcadero C++Builder, VCL and OLE. What I'm trying to do is open an RTF file using OLE, but I'm getting an exception:
Bad variable type
when executing this line:
wordDoc = wordDoc.OleFunction( "open", file );
I'm not sure how to fix this. Here is my code:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
#include <System.hpp>
#include <oleauto.h>
#include <sysvari.h>
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
try
{
Application->Initialize();
UnicodeString file( "C:\\TempFiles\\Test.rtf" );
Variant wordApp = Variant::CreateObject( "word.application" );
wordApp.OlePropertySet( "Visible", Variant( false ) );
Variant wordDoc = wordApp.OlePropertyGet( "documents" );
wordDoc = wordDoc.OleFunction( "open", file );
//Application->MainFormOnTaskBar = true;
//Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (...)
{
try
{
throw Exception("");
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
//---------------------------------------------------------------------------
The problem is that you are passing a UnicodeString
in the 2nd parameter of Variant::OleFunction()
when calling Word's Open()
function.
Internally, OleFunction()
converts the input parameters to Variant
values (rather than OleVariant
), and then passes them as-is to IDispatch::Invoke()
.
Variant
is compatible with OLE only when it holds OLE-compatible data. UnicodeString
is specific to Delphi/C++Builder and unknown to OLE, so it is not OLE-compatible.
When a Variant
is assigned a UnicodeString
value, its VType
field is set to varUString
(0x0102), and its payload is a pointer to the UnicodeString
's internal data with its refCnt
field incremented (the Variant
will decrement the refCnt
when destroyed).
OLE is complaining about that unsupported VType
value when your UnicodeString
-turned-Variant
is passed to IDispatch::Invoke()
.
To fix the error, you need to instead pass a WideString
to OleFunction()
. WideString
is a wrapper for an OLE BSTR
string. When a Variant
is assigned a WideString
value, its VType
field is set to varOleStr
(0x0008, aka VT_BSTR
in OLE), and its payload is a proper BSTR
pointer that is a copy of the WideString
data (the Variant
will free the BSTR
when destroyed).
So, you need to either:
change your file
variable to WideString
:
WideString file( L"C:\\TempFiles\\Test.rtf" );
keep your file
variable as UnicodeString
, but convert it to WideString
when passing it to OleFunction()
:
wordDoc = wordDoc.OleFunction( L"open", WideString(file) );