Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

storing references in array problems

Status
Not open for further replies.

Smedowns

Technical User
Jun 22, 2009
6
US
Hi, i'm trying to create a listbox that holds all "Figure" cross references in it. The problem is that when I run the following code, it will only store a maximum of 8 figures. The strange thing is that if I step through the code line by line, it will store all 44 figures. I can't figure out why this is happening.

Code:
Private Sub UserForm_Initialize()
    Dim varXRefs() As String
    Dim Index As Integer
    Dim c As Integer
    
    Selection.Fields.Update

    ' Clear out any previous contents

    Me.cboFigureNumber.Clear

    ' Load just the figures into varXRefs

    varXRefs = ActiveDocument.GetCrossReferenceItems _
    (ReferenceType:="Figure")
    
c = UBound(varXRefs)

    ' Load the ListBox from varXRefs as an array

    For Index = 1 To UBound(varXRefs)
        Me.cboFigureNumber.AddItem varXRefs(Index)
    Next Index
End Sub
 
You may try this:
Code:
...
varXRefs = ActiveDocument.GetCrossReferenceItems(ReferenceType:="Figure")
DoEvents
c = UBound(varXRefs)
...
BTW, which version of word admits "Figure" as a valid WdReferenceType ?

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
This still causes c to equal 44 when I step through the code and 8 when I run the code.

I'm using word 2003 but this is how the figures are being defined:

Code:
    With CaptionLabels("Figure")
        .NumberStyle = wdCaptionNumberStyleArabic
        .IncludeChapterNumber = True
        .ChapterStyleLevel = 1
        .Separator = wdSeparatorHyphen
    End With


    Selection.InsertCaption Label:="Figure", TitleAutoText:="InsertCaption1", _
        Title:="", Position:=wdCaptionPositionAbove
 
Are you sure that all the figures referenced at the time the UserForm loads ?

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
I'm not sure I understand what you mean. How can I check if they are referenced aside from them not showing up in my listbox?
 
GetCrossReferenceItems can not be relied upon. You need to find another way to get the details you want.

Two ways, neither easy: walk the Fields collection and parse SEQ Fields looking for "Figure", or add a Table of Figures and extract the text from it (and then Undo it).

Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
Or, just to be perverse, you could check for the Caption style. As Tony and PHV will no doubt mention (so don't bother), this is grossly inefficient. I am just tossing it out to be...oh, I don't know...perverse.
Code:
Private Sub UserForm_Initialize()
   Dim oPara As Paragraph
   For Each oPara In ActiveDocument.Paragraphs
      If oPara.Range.Style = "Caption" Then
         If oPara.Range.Words(1) = "Figure " Then
            ComboBox1.AddItem "Figure " & _
               oPara.Range.Fields(1).Result
         End If
      End If
   Next
   ComboBox1.ListIndex = 0
End Sub
This makes a combobox with:

Figure 1
Figure 2
Figure 3
.....

It ignores other Caption styles/text like "Table 1".

I do not know what you are doing with the list, but just to add crap to the mix....
Code:
Private Sub GoToFigure_Click()
      Selection.GoTo What:=wdGoToGraphic, _
      Count:=Right(ComboBox1.Text, 1)
End Sub
With the list in the combobox (from my code) above, another commandbutton "GoToFigure", when clicked, will go to the Figure selected in the combobox list.

Gerry
 



Gerry,

You seem well perversed in all this...

"GoFigure" ;-)

Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
Once again, you crack me up, which I really needed today. My appreciation for you grows like a....hmmmmm, my mind boggles at the possible choices I have to complete that.

Gerry
 
Gerry said:
As Tony and PHV will no doubt mention (so don't bother) ...
OK, I won't bother [smile]

Whatever one does to get round this will be pretty inefficient. I wonder whether your check on paragraphs might be improved by using Find to identify the paragraphs rather than iterating over the whole paragraphs collection - I just wonder, I am by no means certain!

Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
Oh heck yes. Find would faster. Although I think it would take a massive document to see a truly detectable difference.
Code:
Private Sub UserForm_Initialize()
Dim r As Range
Set r = ActiveDocument.Range
With r.Find
   .Style = "Caption"
   Do While .Execute(FindText:="", Forward:=True) = True
      If InStr(1, r.Text, "Figure") > 0 Then
            ComboBox1.AddItem "Figure " & _
               r.Fields(1).Result
      End If
   Loop
End With
   ComboBox1.ListIndex = 0
End Sub
gives the same listing of Figures.

Gerry
 
fumei,

This code gets stuck in an infinite loop. The value of r never changes from the name of the first table.
 
Ummm, no, it does not.


I just made a new document, with three images and gave them captions (Figure 1, Figure 2, Figure 3).

I made a userform with a combobox and a commandbutton. The commandbutton is just an Unload Me.

I copied the userform initialize event directly from my post above.

It works perfectly. There is no infinite loop.

Further, the value of r is a range...not the name of...anything. Never mind a table. r is never the name of a table, so I fail to see how it "never changes from the name of the first table." Although I suppose that is sort of true...in that it never has a name of the "first" table in the "first" place.

Excuse me, but....what table are you talking about?

r.Find looks for any text that has the Caption style. If it finds any, it resets itself for that range. It then checks to see if the string "Figure" in its .Text value. If it is, it loads a string into the combobox. It then continues on.

r is not handled in any other way, and - in fact - it can't get into an infinite loop.

Let me repeat theat. I copied the code directly from the post and there was no infinite loop. If it did for you, then you changed something.

Gerry
 
fumei,

When I make an example similar to what you describe, it works fine, but if I add a table with caption "Table" before the 3 figures, the code gets stuck in the while loop.
 
Yes, I was just about to post an apology. How very odd. You are quite correct.

If it is images that are Captioned with Figure x, then it works just fine.

Yet, when i replaced the images with tables Captioned as Figure x...it does indeed go into an infinite loop.

I am not sure why.

However, as with all range code that infinite loops, the solution is always the same. Collapse the range.
Code:
Private Sub UserForm_Initialize()
Dim r As Range
Set r = ActiveDocument.Range
With r.Find
   .Style = "Caption"
   Do While .Execute(FindText:="", Forward:=True) = True
      MsgBox r.Text
      If InStr(1, r.Text, "Figure") > 0 Then
            ComboBox1.AddItem "Figure " & _
               r.Fields(1).Result
      End If
      [b]r.Collapse 0[/b]
   Loop
End With
   ComboBox1.ListIndex = 0
End Sub
No infinite loop.

Now as to WHY the range object does not proceed when it is tables, but DOES proceed when it is InlineShapes (an image), I will have to think about that.

But yes, if it is tables, it infinite loops. Just add the Collapse.

Gerry
 
Interesting. Very interesting.

IF the paragraph that is the Caption style is followed by an InlineShape (an image), then r.Text - the result of the .Find - includes the paragraph mark.

Thus the Forward:=True proceeds from there. That is, after the Found style.

IF the paragraph that is the Caption style is followed by a table, then r.Text - the result of the .Find - does NOT include the paragraph mark.

Thus the Forward:=True proceeds from there...and thus finds the same paragraph with the caption style, thus, yes, an infinite loop.

Not only that, but using the same "Figure x" caption, if you delete the table, and replace it with an inlineshape...it works perfectly. The paragraph mark is included and the loop proceeds correctly.

You can easily see this when you step through the code, and you have BOTH images and tables that use "Figure" in the Caption.

Checking value of r.Text for images shows "Figure x[]" - with the square symbol indicating a paragraph mark.

Checking value of r.Text for tables shows "Figure x" - with no square symbol indicating a paragraph mark.

OK, I'll bite. Tony? Why would a range.Find make this kind of difference? This is a new one for me. If you add a paragraph mark between the Caption style paragraph - and we all know that Captions are not really connected with the table/figure/image they are supposedly captioning... - then it works, even for tables.

Ohhhh.......it is because of the way range.find works in tables. Ahhhhh. owever, this is an odd thing. It seems that .Find is somehow checking ahead.

There is a table next...I will NOT include the paragraph mark.

There is no table next...I will include the paragraph mark.

For the same .Found.

Bizarre.


Gerry
 
Except there is something niggling at me regarding Range.Find and tables....

That does not detract from the fact it seems bizarre. I suspect that the continuation of .Find (that is Forward:=True) is in fact an internal Range.Collapse 0 (wdCollapseEnd). This causes the .Start of the new reset range (by a successful .Found) to be the .End of range.found..ummm..range to be that plus 1.

However, if that (new) .Start is the start of a table range, then the (new) .Start is the .End of range.found..ummm..range to be that minus 1.

While I admit some people (mostly those Excel people...you know who you are) often find Word truly insane, there is some method in their madness.

There is something about range.find in tables though.....

It is true that if you set a range object to a table range then range.find ignores that fact. It will continue the .Find outside of the table.
Code:
Dim r As Range
Set r = ActiveDocument.Table(1).Range

With r.Find
will NOT just action .Find for the declared range - that is table(1). It will (assuming Forward:=true) keep on going past the table range.

Ditto if you set the range object to be explicitly a Section range. If Forward:=true, then Word ignores the .End of the declared range object and keeps on going.

Help states that using .Wrap = wdFindStop means:

"The find operation ends when the beginning or end of the search range is reached."

However, this is not true. Setting Range to a table, or a Section, and using .Wrap = wdFindStop does NOT stop the search at the end of the search range.

I have a table with "Figure 1" in it, and that text uses the Caption style.

There is "Figure 2" - also using caption style - PAST the table.
Code:
Dim r As Range
Set r = ActiveDocument.Tables(1).Range
Debug.Print r.Start & vbTab & r.End
'  shows the correct Start  and End of the table [b]13  30[/b]
With r.Find
   .Style = "Caption"
   .Wrap = wdFindStop
   Do While .Execute(FindText:="", Forward:=True) = True
      Debug.Print r.Start & vbTab & r.End
      '  shows correct numbers for "Figure 1"   13  22
      '  shows correct numbers for "Figure 2"   49  58
      '  OUTSIDE the original range .Start and .End
   Loop
End With
Why, I have no idea.

Gerry
 
You're triggering memories in me now. Off the top of my head ...

When you do a Find on a Selection in the UI you get, potentially, two prompts - first (and I forget the exact text) "you have reached the end of the Range. Do you want to continue?" and then "you have reached the end of the Document. Do you want to continue from the beginning?". It is the second of these that is controlled by the Wrap parameter.

When you search on a Range in VBA, Wrap should be incidental; it should just stop at the end of the Range but it doesn't. It's a bug.

How any of this relates to tables, or what we're seeing here, I'm not sure.

Enjoy,
Tony

------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

I'm working (slowly) on my own website
 
A bug.

A bug????????

Tell me it ain't so, little grasshopper.

Gerry
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top