tags:

views:

247

answers:

5

Hi,

I'm automating Word with Delphi, but some times I got an error message:

The requested member of the collection does not exist

It seems that the Item member of the Styles collection class does not always exist and some times causes the above mentioned error. My workaround is to catch the exception and skip it, but is there anyway to detect it instead of using the try...except block? The problem with the try...except block is that when debugging the raised exception is annoying...

My code example:

var
  aWordDoc: _WordDocument
  i: Integer;
  ovI: OleVariant;
  wordStyle: Style;
begin
  for i := 1 to aWordDoc.Styles.Count do
  begin
    ovI := i;
    try
      wordStyle := aWordDoc.Styles.Item(ovI);
    except
      Continue;//skip if any error occurred.
    end;

    //do something with wordStyle
  end;
end
A: 

try checking if it is null or not with a IF statement

Jonathan D
Hi, the question is How, thanks.
Edwin
A: 

If the compiler accepts it, but it sometimes cannot happen to exist, it is probably IDispatch based latebinding. IDispatch objects can be queried. Maybe carefully working yourself up the tree querying every object for the next would work.

You would then roughly be doing what the compiler does, except that that one throws an exception if somethines doesn't exist. (and if the exception comes in from COM, maybe a slightly different code path can test more).

Sorry to have no readily made code.

Marco van de Voort
He is using early binding, the Styles property and Styles.Item property should exist. These are around since Word97. The error occurs because the requested Item at index ovI does not exist, which is strange, because he does a for loop from 1 to Styles.Count.
The_Fox
Yes, I'm using early binding, that's quite strange... Maybe that comes from the interior of MICROSOFT WORD and there is nothing we can do...
Edwin
A: 

I get that message when a bookmark that I'm trying to fill from Word doesn't exist so i have a process that checks first, but I'm not sure the same method would work for you.

procedure MergeData(strBookMark, strData : string);
begin
  if WinWord.ActiveDocument.Bookmarks.Exists(strBookMark) = True then
    WinWord.ActiveDocument.FormFields.Item(strBookMark).Result := strData;
end;
Leslie
Hi Leslie, Unfortunately, the styles collection doesn't provide such a method...
Edwin
A: 

It has nothing to do with the Item function not being there. The Item function does exists, but the index you give seems to be wrong.

See this msdn article.

An invalid index seems really weird, because you are performing a for loop from 1 to Styles.Count. So if there is no Style, you should not enter the loop.

The only plausible explanation I can think of is that while you are in your loop, the Styles.Count changes and you are getting out of bounds. Are you deleting styles in your loop perhaps? Try a loop going from Styles.Count downto 1 or try a While loop, evaluating Styles.Count at every iteration.

Other things I can think of, but are very unlikely:

  • While assigning I to ovI, it gets converted to an OleString, so Word searches for a style named "I", instead of a Style at I
  • While assigning I to ovI, something in the conversion goes wrong and it gets in the range of $FFFFFFA5 - $FFFFFFFF, which are constants for Builtin styles.
The_Fox
Hi Fox! It seems that that's because the internal mechanism of Word OLE...
Edwin
I'm not deleting a style in the loop, just copying the styles.
Edwin
You can try to print the number of Styles just after the `ovI := I` statement, to check if the number of Styles doesn't change.
The_Fox
+2  A: 

maybe you are out of index.... try correcting your code ..

for i := 0 to aWordDoc.Styles.Count-1 do
  begin

  end;
XBasic3000
Or better:for i := Low(aWordDoc.Styles) to High(aWordDoc.Styles) do
Jørn E. Angeltveit
In the WORD OLE API, the first index of styles connection starts from 1. It's not an ordinary Delphi array.
Edwin