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