views:

224

answers:

3

Hello,

I'm trying to write a Delphi program that will loop through each worksheet in an Excel file and format some cells. I'm receiving an error while trying to use the for-in loop over the Workbook.Worksheets collection, though. The error is specifically:

[DCC Error] Office.pas(36): E2431 for-in statement cannot operate on collection type 'Sheets' because 'Sheets' does not contain a member for 'GetEnumerator', or it is inaccessible

The line of code this occurs for is:

for Worksheet in Workbook.Worksheets do

The definition of Worksheet and Workbook is as follows:

var ExcelApp: ExcelApplication;
var Workbook: ExcelWorkbook;
var Worksheet: ExcelWorksheet;

I'm porting this code to Delphi from C#, in which it works. Does anyone know why I'd be getting this GetEnumerator error? I'm using the Office 2007 Excel Interop file and Embarcadero® Delphi® 2010 Version 14.0.3593.25826.

Thanks in advance.

A: 

EDIT: Based on comments, the GetEnumerator method exists for the object, so this solution is likely incorrect.

It's been a while since I've used Delphi, but my guess based on the error is that the ExcelWorksheet collection is not enumerated, which would mean doing a for/each style loop would not work and you'd need to use a C-like for loop:

 For  i := 1 to Length(Workbook.Worksheets) do
  Worksheet = Workbook.Worksheets[i];
end;
saalon
According to MSDN, it does have a GetEnumerator method, though.http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.sheets.getenumerator(office.11).aspxPerhaps I'm not properly instanciating the objects? I'm new to Delphi. Here's what I've got in my implementation portion.http://pastebin.com/QaxUXuZ2
Ryan
I think Mason's comment above might be the right direction to go. I remember that when importing COM assemblies in Delphi it creates a big interface definition. GetEnumerator might not be declared there.(By the way, I totally pity you having to move anything from C# to Delphi).
saalon
+1  A: 

I'm not sure how C# handles enumerable collections, but for Delphi, it looks for a method on the collection called GetEnumerator, which returns an enumerator. The enumerator must be a data structure that contains at least the following two members:

public
  function MoveNext: boolean;
  property Current: <some type> read <some read method>;
end;

If Delphi says 'Sheets' does not contain a member for 'GetEnumerator', or it is inaccessible, then that means exactly what it says. Either there's no GetEnumerator on Sheets, or it's not a public method. What does the definition of Sheets look like?

Mason Wheeler
The definition of Sheets can be found here, on MSDN: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.sheets_methods(office.11).aspx That is a link to the methods available within Sheets. So, the GetEnumerator method does exist and is public.
Ryan
OK, looks like it exists, but the compiler can't find it. If this is coming from another language, you're accessing it through a translated header or interface definition somewhere. Check and make sure that it's got GetEnumerator declared.
Mason Wheeler
Ok. Yea, I'm importing a unit using the Excel Type Library. It doesn't look like there's any trace of GetEnumerator in the unit that it's creating. Looks like I might have to use the For loop as saalon stated below.
Ryan
@Ryan: Can you just edit the definition from the Excel Type Library and add the GetEnumerator declaration?
Mason Wheeler
+1  A: 

C# handles enumerators similar to Delphi. There is an IEnumerable interface that has two methods: MoveNext, and Reset; and also one property called Current.

For ExcelWorkBook.Sheets property, you should take note that although MSDN documentation says it has a GetEnumerator method, this class's definition in ExcelXP unit provided by Delphi does not provide such a method. So maybe you have to import a newer version of its type library into Delphi.

vcldeveloper