1
votes

I need to insert a cross reference to a particular numbered item (from a simple numbered list) given the text of the numbered item. The user selects the list item they want to cross reference as well as the location to insert the cross reference as shown below:

1. This is item 1
2. This is item 2  <-- user selects this line
3. This is item 3
------------------
[2]  This is a reference to item 2  <-- user ctrl selects this line too
 ^ macro will insert the 2 as a cross reference to the selected list item

However, there can be many numbered items with the same text so I need a way to determine which of the items is the selected one. I plan on selecting each of the items that have the correct text, checking to see it if is at the correct location in the document and if it is I now know its "ReferenceItem:" number so I can insert a cross reference to it. I loop through the results of:

ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)

to get reference numbers for the numbered items with the correct text but I can't figure out how to select each of the candidates so I can test its location. Something like:

ActiveDocument.Goto.CrossReferenceItem(81)

This is in Word 2010.

Code example (all error checking removed):

'Create a temporary character style
ActiveDocument.Styles.Add "_TEMP_STYLE_", wdStyleTypeCharacter

'Apply the temporary style to the discontiguous selection
Selection.Style = ActiveDocument.Styles("_TEMP_STYLE_")

Set olRange = ActiveDocument.Range

With olRange.Find
    .ClearAllFuzzyOptions
    .ClearFormatting
    .ClearHitHighlight
    .Style = ActiveDocument.Styles("_TEMP_STYLE_")
    .Text = ""
    .Wrap = wdFindStop

    'llNumberedParaStart is used in the check of a numbered item to see if it is
    'the right one 
    llNumberedParaStart = -1
    llChildParaStart = -1

    Do While .Execute
        If .Found Then
            If olRange.Paragraphs(1).Range.ListFormat.ListType = wdListSimpleNumbering Then
                llNumberedParaStart = olRange.Characters(1).Start
                ' Do some work before this to get the text to check for
                slNumberedParaText = Selection.Text
            Else
                llChildParaStart = olRange.Characters(1).Start
            End If
    Loop
End With

slaNumItems = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)

'Loop through all the numbered items and find the correct one
For ilRefItem = 0 To UBound(slaNumItems)

    If InStr(slNumberedParaText, slaNumItems(ilRefItem)) = 0 Then

        'Check to make sure the reference is the correct one
        ********** select the numbered item and check its position **********

        'Insert the cross reference after selecting the correct location
        Selection.InsertCrossReference ReferenceType:="Numbered item", _
             ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=ilRefItem, _
             InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False, _
             SeparatorString:=" "        

        Exit For

    End If
Next ilRefItem
1
by "can't figure out how to select each of the candidates" do you mean truly 'Select' the numbered item in the document?JohnZaj
I need to be able to test the numbered item's position in the document to see if it is the correct one to cross reference; selecting it is the most obvious way (to me). I have a numbered list in one table cell and in another cell in the table I want to put a reference to one of the entries (as part of a sentence). The user ctrl-selects the source list entry and the line of text to append the cross reference to so I know where they are in the document. Unfortunately, Word doesn't do well with discontiguous selections so I have to be indirect...RunDeep
Can you edit your question and show a visual representation of the table and sample content to avoid a lot of guesswork? I think the worst scenario is that this won't work the way you envisioned but definitely a way to solve thisJohnZaj
Hopefully this is clearer? There is a problem with the discontiguous selections and I am following the approach given here: stackoverflow.com/questions/1284867/…RunDeep
Right - that was my post actually. Il look at this tomorrow but I also think it would help me if I could see the code you have so farJohnZaj

1 Answers

0
votes

This maro parses all Cross Reference Items of type "wdRefTypeHeading" and compare their paragraph number with number of currently selected paragraph: if they match, text insertion point is moved one line above, and this text is added:

§xxx, p.yyy

Where xxx and yyy are of course paragraph number and page number.

Then the text is cut and put in clipboard, so original document is not affected.

NOTE: an empty line must be present before the heading, else any contents of above line will be cut.

Sub CreaRiferimento()
    Dim d As Document
    Set d = ActiveDocument
    Debug.Print "Current selection: " & Selection.Paragraphs(1).Range.ListFormat.ListString & " " & Selection.Paragraphs(1).Range
    n = GetRefNum()
    Debug.Print "Internal reference number = " & n

    ' Sposta punto inserimento sopra a titolo
    Selection.MoveUp Unit:=wdLine, Count:=1

    ' Scrive "§"
    Selection.TypeText Text:="§"

    ' Scrive riferimento a paragrafo
    Selection.InsertCrossReference ReferenceType:="Titolo", ReferenceKind:= _
        wdNumberRelativeContext, ReferenceItem:=Trim(Str(n)), InsertAsHyperlink:=True, _
        IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "

    ' Scrive "p." per la pagina
    Selection.TypeText Text:=", p."

    'Scrive riferimento a pagina del paragrafo
    Selection.InsertCrossReference ReferenceType:="Titolo", ReferenceKind:= _
        wdPageNumber, ReferenceItem:=Trim(Str(n)), InsertAsHyperlink:=True, _
        IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "

    ' Taglia in clipboard quanto appena scritto
    Selection.EndKey Unit:=wdLine
    Selection.HomeKey Unit:=wdLine, Extend:=wdExtend
    Selection.Cut

  End Sub

Function GetRefNum() As String
    CRI = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading)
    HeadNum = Selection.Paragraphs(1).Range.ListFormat.ListString
    CRINumber = 1
    For Each CR In CRI
        HeadingNumberFromFunction = Mid$(LTrim(CR), 1, InStr(LTrim(CR), " ") - 1)
        'Debug.Print HeadNum & " ? " & HeadingNumberFromFunction
        'Debug.Print "'" & CR & " ' = ReferenceItem n." & CRINumber
        If HeadingNumberFromFunction = HeadNum Then
            GetRefNum = CRINumber
            Exit Function
        End If
        CRINumber = CRINumber + 1
    Next

End Function