Как получить информацию IDispatch из свойства варианта в объекте Delphi com в VBA? - PullRequest
1 голос
/ 21 декабря 2009

У меня есть COM-объект, написанный на Delphi, который имеет свойство, которое возвращает вариант. В основном это свойство возвращает значение в зависимости от параметра, который я передаю. Когда я получаю доступ к объекту из VBA (например, в Excel), я могу написать что-то вроде:

MyObject.MyProperty("IntProperty") = 22

Теперь свойство также может возвращать объект IDispatch, который хранится в варианте. Если я получаю доступ к объекту com из Delphi, я пишу следующий код для извлечения этой информации IDispatch

var
  Info : IMyInterface;

Info := IDispatch(TVarData(MyObject.MyProperty['InfoProperty']).VDispatch) as IMyInterface;

Info.foo := 10;
info.y   := 'test';
info.saveit;

Можно ли извлечь эту информацию IDispatch в VBA? Я еще не нашел способ сделать это.

Чтобы очистить на 100%, свойство имеет тип OLEVariant, а не IDispatch. У меня есть свойства типа IDispatch, и они работают нормально.

Это объявление get_MethodProperty

function get_MethodProperty(const aPropertyName: WideString):OLEVariant;

Это сработало бы, если бы я объявил это как

function get_MethodProperty(const aPropertyName: WideString):IDispatch;

Но это не то, чего я хочу.

<Ч />

Это код VBA, и он не выполняется во второй строке

Dim Info as Object
Set Info = MyObject.MethodProperty("InfoProperty")
Info.foo = 10
Info.y = "test"
call info.saveit

Ответы [ 4 ]

0 голосов
/ 24 декабря 2009

Я попробовал это на одном из моих серверов автоматизации, и он отлично работал в VBA (Excel) Моя реализация в Delphi выглядит так:

Метод Get в главном объекте:

function TApplication.Get_MethodProperty(const aPropertyName: WideString): OleVariant;
begin
  if aPropertyName = 'IntProperty' then begin
    result := 42;
  end else if aPropertyName = 'InfoProperty' then begin
    result := TInfoObject.Create as IDispatch;
  end;
end;

Объявление TInfoObject:

  TInfoObject = class(TAutoObject, IInfoObject)
  protected
    function Get_foo: Integer; safecall;
    procedure Set_foo(Value: Integer); safecall;
    function Get_y: WideString; safecall;
    procedure Set_y(const Value: WideString); safecall;
    procedure saveit; safecall;
  end;

Внедрение TInfoObject:

{ TInfoObject }

function TInfoObject.Get_foo: Integer;
begin
  result := 123;
end;

function TInfoObject.Get_y: WideString;
begin
  result := 'info';
end;

procedure TInfoObject.Set_foo(Value: Integer);
begin
  // NYI
end;

procedure TInfoObject.Set_y(const Value: WideString);
begin
  // NYI
end;

procedure TInfoObject.saveit;
begin
  ShowMessage('saveit');
end;

Тестовый код VBA:

Dim Info As Object

Set Info = MyObject.MethodProperty("InfoProperty")

Info.foo = 10
Info.y = "test"

Call Info.saveit

Если это не работает в вашем приложении, пожалуйста, предоставьте мне сообщение об ошибке VBA.

0 голосов
/ 22 декабря 2009

Вы можете "извлечь" IDispatch в VBA, как это

Dim info As Object
Set info = MyObject.MyProperty("IntProperty")
info.foo = 10
info.y = "test"
info.saveit
0 голосов
/ 22 декабря 2009

Насколько я знаю, если IDispatch задействован, вы используете позднюю привязку, и поэтому я думаю что-то вроде

Set info = CreateObject('WhatEverYourLibraryIs')

отсутствует (может быть, эта ссылка Microsoft о Использование раннего и позднего связывания в Automation тоже поможет)

0 голосов
/ 21 декабря 2009

Я не совсем уверен, что вы подразумеваете под «извлечением информации IDispatch». VBA должен быть в состоянии использовать вариант, содержащий IDispatch просто отлично. Простые тесты включают в себя:

  1. Если вы вызываете info.xxx из vba, появляется ли xxx в ваших GetIDsOfNames?
  2. Если вы вызываете VarType (info) из vba, будет ли результат vbObject? (== varDispatch)
...