How to check if OleVariant contains an interface
One of the frustrating things when working with Excel through the automation interface is weak typing.
The return value can contain anything for different types.
How can I check if a variant returned by an caller
interface is ExcelRange
?
function TAddInModule.InBank: boolean;
var
ExcelAppAsVariant: OleVariant;
test: string;
Caller: OleVariant;
begin //Exception handling omitted for brevity.
Result:= false;
ExcelAppAsVariant:= ExcelApp.Application;
Caller:= ExcelApp.Application.Caller[EmptyParam, 0];
if IDispatch(Caller) is ExcelRange then begin //E2015 Operator not applicable
Result:= lowercase(Caller.Parent.Name) = 'bank'
end;
end;
(Oddly enough, the operator as
works and (IDispatch(Caller) as ExcelRange).Parent;
compiles just fine).
The following code works, but looks too verbose:
if VarIsType(Caller, varDispatch) then begin
IUnknown(Caller).QueryInterface(ExcelRange, ICaller)
if Assigned(ICaller) then ICaller......
There is also no built-in function VarIsInterface(Variant, Interface)
.
How can I check that the OleVariant contains a given interface?
See also: How to distinguish OleVariant from IDispatch?
EDIT
Thanks everyone, I used the following to do the testing because Excel mixes Interfaces and OleStrings as possible return values.
if VarIsType(Caller, varDispatch) and Supports(Caller, ExcelRange) then begin
source to share
The module System.Variants
has functions VarSupports()
to test / extract the interface from (Ole)Variant
:
function VarSupports(const V: Variant; const IID: TGUID; out Intf): Boolean; overload;
function VarSupports(const V: Variant; const IID: TGUID): Boolean; overload;
For example:
Caller := ExcelApp.Application.Caller[EmptyParam, 0];
if VarSupports(Caller, ExcelRange) then
Result := LowerCase(Caller.Parent.Name) = 'bank';
if VarSupports(Caller, ExcelRange, ICaller) then
ICaller.DoSomething;
source to share