How do I generate a numbered paragraph Word Cross Reference field in VB?

Anonymous
2010-10-06T22:23:01+00:00

Hi There,

Does anyone know how the 9 digit unique number used in a Microsoft Word 2003 SP3 cross reference field for a numbered paragraph is derived or calculated, and what VB function I can use to extract or create it?

I use a macro (see below) that creates and inserts a cross reference field. The aim is to quickly create a cross reference from a button rather than go through the tedious "insert>reference>cross reference and select" menus.

The macro tags the reference with a letter "b" followed by an 8 digit random number (eg toggle field codes shows "{ REF b70554752 \n \h }.

The behaviour of this method of cross referencing works well most of the time, but has a couple of annoying flaws.  

Firstly, the small risk that a cross reference may be given the same number (ie the random number generator kicscks out the same number twice in a document!). Not really concerned about this as it is very unlikely to occur.

Secondly, and by far the biggest problem, is where a cross reference is created to a numbered paragraph, and the numbered paragraph is subsequently deleted. Instead of the cross reference going to "Error! - Reference Not Found" (as a 'manually inserted' cross reference does), it updates to a different, usually nearby, numbered paragraph.

On comparing the format of a 'manually inserted' cross reference field with my macro generated field, it appears that the "Microsoft" cross reference uses a 9 digit number that is somehow created uniquely based on the paragraph (for example "{ REF _Ref274201605 \n \h }"). This means that if the paragraph referred to is deleted, the reference is no longer valid and the bookmark (correctly) errors ever time.

Does anyone know how the 9 digit unique number used in a Microsoft Word 2003 SP3 cross reference field for a numbered paragraph is derived or calculated, and what VB function I can use to extract or create it?

Many thanks in advance!

Cheers

...Steve

For reference, the current macro is as follows:

___________________

Sub Add_crossRef_to_selected_para()

Dim n As Long

Dim myBookmark As String

n = Int(Rnd() * 100000000) + 1

With ActiveDocument.Bookmarks

.Add Range:=Selection.Range, Name:="b" & n

.DefaultSorting = wdSortByLocation

.ShowHidden = True

End With

Selection.InsertCrossReference ReferenceType:="Bookmark", ReferenceKind:= _

wdNumberNoContext, ReferenceItem:="b" & n, InsertAsHyperlink:=True, _

IncludePosition:=False

End Sub

________________________

Microsoft 365 and Office | Word | For home | Windows

Locked Question. This question was migrated from the Microsoft Support Community. You can vote on whether it's helpful, but you can't add comments or replies or follow the question.

0 comments No comments

41 answers

Sort by: Most helpful
  1. Anonymous
    2010-10-11T03:57:12+00:00

    Hi macropod,

    on my test document, it's horribly slow on initial and subsequent runs of the macro.

    Also inserts a bookmark to the begining of para 1 (HEading 1) in the few times I tried it, and incorrect in subsequent (eg inserts 2.2(b) in clause 2.2.3)

    Did you downlaod and try your macro in my test document?

    Cheers

    ...Steve

    Was this answer helpful?

    0 comments No comments
  2. Paul Edstein 82,871 Reputation points Volunteer Moderator
    2010-10-11T03:42:42+00:00

    Hi Steve,

    Try this iteration:

    Sub CrossRefThisListPara()

    Application.ScreenUpdating = False

    Dim i As Integer, xRefs As Variant, rngTmp As Range

    xRefs = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)

    With Selection

      .Collapse wdCollapseEnd

      On Error Resume Next

      For i = 1 To UBound(xRefs)

        If ActiveDocument.ListParagraphs(i).Range.BookmarkID = 0 Then

          Set rngTmp = ActiveDocument.ListParagraphs(i).Range

          With rngTmp

            .End = .Start

            .InsertCrossReference ReferenceType:=wdRefTypeNumberedItem, _

              ReferenceKind:=wdNumberFullContext, ReferenceItem:=i

            .MoveEnd wdCharacter, 1

            .Fields(1).Delete

          End With

        End If

      Next

      .InsertCrossReference ReferenceType:=wdRefTypeNumberedItem, ReferenceKind:=wdNumberFullContext, _

        ReferenceItem:=.Paragraphs.First.Range.BookmarkID, InsertAsHyperlink:=True, IncludePosition:=False

    End With

    Application.ScreenUpdating = True

    End Sub

    What I've done is to add some code to ensure each list para has a bookmark ID allocated by Word, then simply insert the cross-reference to the current paragraph's bookmark ID. The code might run a little slowly the first time on a document with lots of list paragraphs that haven't been bookmarked, but thereafter should be quite quick.


    Cheers,

    macropod MS MVP - Word

    Was this answer helpful?

    0 comments No comments
  3. Anonymous
    2010-10-11T01:21:10+00:00

    Hi macropod,

    Fixed the speed problem - well done!

    But (I think - I may be getting confused!!) it introduced a new one:-(

    In heading 4 and heading 5 it inserts a crossref to the first instance of the para that has the same text. eg inserting (in the test document) a cross ref at 4.1.3(b)(i) gives a value of 2.1(b)(i).

    Also tried it on one of my 'live' documents which uses multiple styles with heading numbering such asC1-61.3.11.1 for a level 3 heading, but lets get it working for the standard headings first:-)

    Cheers

    ...steve

    Was this answer helpful?

    0 comments No comments
  4. Paul Edstein 82,871 Reputation points Volunteer Moderator
    2010-10-11T00:20:36+00:00

    Hi Steve,

    It surprises me that you'd get a spurious cross-reference with the last version, since it's testing for range equivalence rather than contents.

    It think the following should be significantly quicker on a large document:

    Sub CrossRefThisListPara()

    Dim i As Integer, xRefs As Variant, strNum As String

    xRefs = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)

    With Selection

      .Collapse wdCollapseEnd

      strNum = .Range.ListFormat.ListString

      On Error Resume Next

      For i = 1 To UBound(xRefs)

        If Split(Trim(xRefs(i)), " ")(0) = strNum Then

          If ActiveDocument.ListParagraphs(i).Range = .Paragraphs(1).Range Then

            .InsertCrossReference ReferenceType:=wdRefTypeNumberedItem, ReferenceKind:=wdNumberFullContext, _

            ReferenceItem:=i, InsertAsHyperlink:=True, IncludePosition:=False

            Exit Sub

          End If

        End If

      Next

    End With

    End Sub


    Cheers,

    macropod MS MVP - Word

    Was this answer helpful?

    0 comments No comments
  5. Anonymous
    2010-10-10T23:32:13+00:00

    Hi macropod.

    Nearly there again! Initial testing has it working pretty much as expected. Some issues when there is a duplicate para, but that's quite rare and easy to fix in the pasted result (just delete the spurious xref).

    On large documents it takes a while  (15 seconds on the test doc) to give control back. Can anything be done about that?

    Cheers

    ...Steve

    Was this answer helpful?

    0 comments No comments