Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как реализовать функциональность "ForEach" в VBA для COM-объекта, написанного на Delphi

Delphi , Компоненты и Классы , Коллекции

Вы хотите использовать цикл "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":

TAMDBObjIDEnumeratorAdapter = class(TSGGenericOLEVariantEnumeratorAdapter<Integer>);

Затем создадим перечислимое для этого свойства:

TAMDBObjIDEnumerableAdapter = class(TSGGenericOLEVariantEnumerableAdapter<Integer>, IAMObjectIDs, ISGEnumerable<Integer>)
  public
    constructor Create(const aSourceEnumerable: ISGEnumerable<Integer>);
end;

Наконец, создадим экземпляр перечислимого и используем его в цикле "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




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Коллекции ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-09-04 11:29:43/0.0079231262207031/1