Вы хотите использовать цикл "For Each" в VBA для перебора элементов свойства "IDList" COM-объекта, написанного на Delphi. В этом материале мы рассмотрим, как реализовать это с помощью интерфейсов и адаптеров.
Базовые интерфейсы для перечисления
В целях избежания проблем с интерфейсами "IEnum" и "IEnum" в Delphi мы создадим собственные наборы интерфейсов для перечисления, которые будут использоваться в циклах "for..in" на Object Pascal.
ISGEnumeratorBase = interface(IInterface)
['{DA91A203-3B39-4287-9A6F-6E9E4B184BAD}']
function MoveNext: Boolean;
end;
ISGEnumeratorReset = interface(ISGEnumeratorBase)
['{FBD2EFBD-D391-4BE2-A3AB-9C9D09197F78}']
procedure Reset;
end;
ISGEnumeratorClone = interface(ISGEnumeratorBase)
['{E3A128FD-7495-464D-BD5E-3EBA3AEFE94F}']
function Clone: ISGEnumeratorBase;
end;
ISGEnumerator<T> = interface(ISGEnumeratorBase)
function GetCurrent: T;
property Current: T read GetCurrent;
end;
ISGEnumerable<T> = interface(IInterface)
function GetEnumerator: ISGEnumerator<T>;
end;
Адаптер для интерфейса IEnumVariant
Для реализации цикла "For Each" в VBA нам нужен адаптер, который позволяет создавать интерфейс "IEnumVariant" на основе наших интерфейсов "ISGEnumerator" и "ISGEnumerable".
Сначала создадим базовый класс адаптера:
TSGOLEVariantEnumeratorAdapterBase = class(TAutoIntfObject, IEnumVariant)
private class var
vOLETypeLib: ITypeLib;
private
class function GetOLETypeLib: ITypeLib; static;
class destructor ClassDestroy;
// для IOLEEnumVariant
function Next(celt: LongWord; var rgvar: OleVariant; out pceltFetched: Longword): HResult; stdcall;
function Skip(celt: LongWord): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out Enum: IEnumVariant): HResult; stdcall;
protected
class property OLETypeLib: ITypeLib read GetOLETypeLib;
function DoNext(aFetchRequestCount: LongWord; var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean; virtual; abstract;
function DoSkip(aSkipCOunt: LongWord): boolean; virtual; abstract;
function DoReset: boolean; virtual;
function DoClone(out Enum: IEnumVariant): boolean; virtual;
public
constructor Create;
end;
Затем создадим обобщенный адаптер, который будет использовать наши интерфейсы и методы базового класса:
TSGGenericOLEVariantEnumeratorAdapter<TEnumeratedType> = class(TSGOLEVariantEnumeratorAdapterBase, ISGEnumerator<TEnumeratedType>)
private
FSourceEnumerator: ISGEnumerator<TEnumeratedType>;
protected
function MapCurrentToVariant(aCurrent: TEnumeratedType): OleVariant; virtual;
function DoReset: boolean; override;
function DoClone(out Enum: IEnumVariant): boolean; override;
function DoNext(aFetchRequestCount: LongWord; var rgvar: OleVariant; out aActuallyFetchedCount: Longword): boolean; override;
function DoSkip(aSkipCOunt: LongWord): boolean; override;
property SourceEnumerator: ISGEnumerator<TEnumeratedType> read FSourceEnumerator implements ISGEnumerator<TEnumeratedType>;
public
constructor Create(const aSourceEnumerator: ISGEnumerator<TEnumeratedType>);
end;
Реализация методов и свойств адаптера позволит нам создавать интерфейс "IEnumVariant" на основе наших интерфейсов "ISGEnumerator" и "ISGEnumerable".
Пример использования
Теперь мы можем использовать наш адаптер для создания перечисления объектов в VBA. Сначала создадим перечислитель для свойства "IDList":
Наконец, создадим экземпляр перечислимого и используем его в цикле "For Each" в VBA:
Dim MyObject as Object
Set MyObject = CreateObject("MyObjectClass")
Dim IDList as Object
Set IDList = MyObject.IDList
Dim Item as Integer
For Each Item in IDList
Debug.Write CStr(Item) & ";"
Next
Надеемся, что эта статья помогла вам разобраться, как реализовать функциональность "ForEach" в VBA для COM-объекта, написанного на Delphi.
В материале описывается, как использовать цикл 'For Each' в VBA для перебора элементов свойства 'IDList' COM-объекта, написанного на Delphi, с помощью интерфейсов и адаптеров.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.