Implementacja Foreach (for in do) dla Delphi 7

papudrun

1 Słowem wstępu
2 Kod modułu
3 Przykład wykorzystania #1
4 Przykład wykorzystania #2

Słowem wstępu

Podczas pisania jednego z programów spotkałem się z problemem braku możliwości wykorzystania foreach w Delphi 7. Począwszy od Delphi 2005 możliwe jest wykorzystanie następującej składni: ```delphi for enumerator in collection do begin //do something here end; ``` Aby ten sam efekt uzyskać w starszych wersjach Delphi musimy pokombinować. Wykorzystamy do tego następujący moduł:

Kod modułu

```delphi unit foreach; interface type IForEach = interface function Next(var item: OleVariant): boolean; procedure Reset(); end; function makeForEach(collection: IDispatch): IForEach; // ================================================================== implementation uses Windows, SysUtils, ActiveX; type TForEach = class(TInterfacedObject, IForEach) fEnum : IEnumVARIANT; constructor Create(collection: IDispatch); function Next(var item: OleVariant): boolean; procedure Reset(); end; // ================================================================== function makeForEach(collection: IDispatch): IForEach; begin Result := TForEach.Create(collection); end; // ================================================================== { TForEach } constructor TForEach.Create(collection: IDispatch); var invokeResult : OleVariant; disppar : DISPPARAMS; hr : HRESULT; begin VariantInit(invokeResult); zeromemory(@disppar, sizeof(DISPPARAMS)); hr := collection.Invoke(DISPID_NEWENUM, GUID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, disppar, @invokeResult, nil, nil); if SUCCEEDED(hr) then begin fEnum := IUnknown(invokeResult) as IEnumVARIANT; VariantClear(invokeResult); if fEnum = nil then raise Exception.Create('Collection does not support IEnumVARIANT'); Reset(); end else begin raise Exception.Create('Collection does not return an enumerator'); end; end; // ------------------------------------------------------------------ function TForEach.Next(var item: OleVariant): boolean; var nFetched : cardinal; newItem : OleVariant; begin Result := False; if fEnum < nil then begin VariantInit(newItem); if SUCCEEDED(fEnum.Next(1, newItem, nFetched)) then begin if nFetched > 0 then begin item := newItem; VariantClear(newItem); Result := True; end; end; end; end; // ------------------------------------------------------------------ procedure TForEach.Reset; begin Assert(fEnum < nil); fEnum.Reset(); end; // ------------------------------------------------------------------ end. ```

Przykład wykorzystania #1

```delphi var foreach : IForEach; en : IEnumSomething; item : ISomething; varitem : OleVariant; begin // DoSomething() returns a collection en := DoSomething() as IEnumSomething; foreach := makeForEach(en); while foreach.Next(varitem) do begin item := IUnknown(varitem) as ISomething; item.GreatFunction(); end; ```

Przykład wykorzystania #2

```delphi var ExcelApp: Variant; foreach : IForEach; collection : Variant; collection_item: Variant; varitem : OleVariant; {...} collection := ExcelApp.WorkSheets[1].Range['D5:D300']; foreach := makeForEach(collection); while foreach.Next(varitem) do begin collection_item := varitem; if Trim(collection_item.Text)<'' then begin Memo1.lines.add(collection_item.Text); end; end; ``` ____ Źródła #Delphi 6 Items #Foreach - Wikipedia

0 komentarzy