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 sizbut on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Help with Range rather than Selection 1

Status
Not open for further replies.

mintjulep

Technical User
Aug 20, 2004
1,551
JP
This little bit of code in Word inserts a cross reference to the paragraph number of the paragraph where the cursor is located. The cross reference is bracketed by some fixed text, so that the result is:

[CDRL crossref]

Then it marks that text as a TOA entry.

It works, but as you can see it's nasty in it's use of selection.extend and selection.typetext.

Code:
Public Sub InsertCDRL()
Dim CurrentPosition As String

CurrentPosition = Selection.Range.ListFormat.ListString

myHeadings = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)
Application.ScreenUpdating = False

For i = 1 To UBound(myHeadings)
    If InStr(LCase$(myHeadings(i)), CurrentPosition & " ") Then
        Selection.TypeText Text:="[CDRL "
        Selection.InsertCrossReference ReferenceType:="Numbered item", _
        ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=CStr(i), _
        InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False, _
        SeparatorString:=" "
        Selection.TypeText Text:="]"
        
        Selection.MoveLeft unit:=wdSentence, Count:=1
        Selection.Extend ("]")
        
            ActiveWindow.ActivePane.View.ShowAll = True
    ActiveDocument.TablesOfAuthorities.MarkCitation Range:=Selection.Range, _
        ShortCitation:="[CDRL " & CurrentPosition & "]", LongCitation:="[CDRL " & CurrentPosition & "]", _
        LongCitationAutoText:="", Category:=1
    ActiveWindow.ActivePane.View.ShowAll = Not ActiveWindow.ActivePane.View. _
        ShowAll
    End If

Next i

Application.ScreenUpdating = True
End Sub

Any pointers on cleaning this up to use Range rather than selection would be appreciated.
 
1. Please state what version of the application you are asking about, when posting. It helps. You seem to be using 2007, as there are parameters that do not exist on my version (2002).

2. You do not appear to be using Option Explicit. I strongly suggested you start doing so. It forces you to explicitly declare your variables.

3. Use With statements. However, even changing it to:
Code:
      With Selection
         .TypeText Text:="[CDRL "
         .InsertCrossReference _
            ReferenceType:="Numbered item", _
            ReferenceKind:=wdNumberRelativeContext, _
            ReferenceItem:=CStr(i), _
            InsertAsHyperlink:=True, _
            IncludePosition:=False  
[COLOR=red]' these are not valid with 2002 version
'            SeparatorString:=" "
'            SeparateNumbers:=False  '  ,[/color red]
         .TypeText Text:="]"
         .MoveLeft unit:=wdSentence, Count:=1
         .Extend ("]")
      End With
I am having a very hard time figuring out what you are doing.

This appears to create a bunch of TA at the Selection point. But there is no testing for where that is.

1. The quick brown fox jumps over the lazy dog.
2. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
3. The quick brown fox jumps over the lazy dog.

Now if the Selection is BELOW that list, you end up with:

1. The quick brown fox jumps over the lazy dog.
2. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
3. The quick brown fox jumps over the lazy dog.

[CDRL 1][CDRL 3][CDRL 2]

Notice the order.

If the Selection is in, say #2 after the first "fox", then you get:

1. The quick brown fox jumps over the lazy dog.
2. The quick brown fox[CDRL 2] jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
3. The quick brown fox jumps over the lazy dog.

So, unless it becomes clearer as to what exactly is your purpose, it is hard to offer suggestions as to using Range. Although I have no doubt that using range is most likely better.

"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
Thanks for the insight Gerry.

I'm using 2003.

As you can probably tell, my original is cobbled together from scraps of macro recorder sessions. The options for the insertcrossreference that you flagged were generated by the recorder. 2002 compatibility isn't an issue for me, but I'll have to figure out what they are just to know.

I am trying to generate the bracketed CrossReference at the selection point and mark it as a TA entry.

Good catch on the lack of testing for the location of the insertion point. The intended use of this sub is for the user to place the cursor at the desired location and invoke the code manually. I have the fortunate option of having users that can be trusted to do this, however I see now that a bit of testing could improve things and enforce some consistency.

Even better catch with the results if the selection point is outside of the list. I definitely need to trap this.
 
Revised, in case anyone is interested.

Code:
Public Sub InsertCDRL()
Dim CurrentPosition, ItemText As String
Dim Rng As Range
Dim myHeadings As Variant

If Selection.Range.ListFormat.ListType <> wdListOutlineNumbering Then
    MsgBox ("Cursor must be in a paragraph with an allowable style applied.")
    End
End If

ActiveDocument.TablesOfAuthoritiesCategories(1).Name = "CDRL"
Application.ScreenUpdating = False
CurrentPosition = Selection.Range.ListFormat.ListString
Set Rng = Selection.Range
With Rng
    .Expand (wdParagraph)
    .Collapse (wdCollapseStart)
    .Expand (wdSentence)
End With

ItemText = Rng.Text

Rng.Collapse (wdCollapseStart)

myHeadings = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)

For i = 1 To UBound(myHeadings)
    If InStr(LCase$(myHeadings(i)), CurrentPosition & " ") Then
        With Rng
        .InsertBefore "[CDRL ]"
        .Collapse (wdCollapseEnd)
        .MoveEnd wdCharacter, -1
        .InsertCrossReference ReferenceType:="Numbered item", _
        ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=CStr(i), _
        InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False, _
        SeparatorString:=" "
        .Expand (wdParagraph)
        .Collapse (wdCollapseStart)
        .Expand (wdSentence)
        End With
            ActiveWindow.ActivePane.View.ShowAll = True
    ActiveDocument.TablesOfAuthorities.MarkCitation Range:=Rng, _
        ShortCitation:=" ", LongCitation:=CurrentPosition & ": " & ItemText, _
        LongCitationAutoText:="", Category:=1
    ActiveWindow.ActivePane.View.ShowAll = Not ActiveWindow.ActivePane.View. _
        ShowAll
    End If

Next i

Application.ScreenUpdating = True
End Sub
 
Hmmm. Methinks you could also use a paragraph object. But let's start with:
I am trying to generate the bracketed CrossReference at the selection point and mark it as a TA entry.
Really? Are you sure? Although you seem to have fixed this by collapsing the range.


You may want to consider an Exit Sub, if the Selection is not in the proper paragraph. Otherwise, all the other instructions will execute anyway.
Code:
If Selection.Range.ListFormat.ListType <> wdListOutlineNumbering Then
    MsgBox ("Cursor must be in a paragraph with an allowable style applied.")
    [highlight]End[/highlight][COLOR=red]'  what is this???[/color red]
    [b]Exit Sub[/b]
End If


"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
Really? Are you sure?

It's my requirement and I can change it if I want to [yinyang]

From Word VBA help:

End Terminates execution immediately. Never required by itself but may be placed anywhere in a procedure to end code execution, close files opened with the Open statement and to clear variables.
 
Hi mintjulep,

It's my requirement and I can change it if I want to
Yes, but it helps if you let those trying to understand what you're trying to do that the requirement has changed.

You could also streamline the code:
Code:
Public Sub InsertCDRL()
Dim CurrentPosition, ItemText As String
Dim Rng As Range
Dim myHeadings As Variant

If Selection.Range.ListFormat.ListType <> wdListOutlineNumbering Then
    MsgBox ("Cursor must be in a paragraph with an allowable style applied.")
    End
End If

With ActiveDocument
  .TablesOfAuthoritiesCategories(1).Name = "CDRL"
  myHeadings = .GetCrossReferenceItems(wdRefTypeNumberedItem)
End With

Application.ScreenUpdating = False
CurrentPosition = Selection.Range.ListFormat.ListString

Set Rng = CurrentPosition.Range
With Rng
  .Expand (wdParagraph)
  .Collapse (wdCollapseStart)
  .Expand (wdSentence)
  ItemText = .Text
  .Collapse (wdCollapseStart)
  For i = 1 To UBound(myHeadings)
    If InStr(LCase$(myHeadings(i)), CurrentPosition & " ") Then
      .InsertBefore "[CDRL ]"
      .Collapse (wdCollapseEnd)
      .MoveEnd wdCharacter, -1
      .InsertCrossReference ReferenceType:="Numbered item", SeparatorString:=" ", _
      ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=i, _
      InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False
      .Expand (wdParagraph)
      .Collapse (wdCollapseStart)
      .Expand (wdSentence)
      ActiveWindow.ActivePane.View.ShowAll = True
      ActiveDocument.TablesOfAuthorities.MarkCitation Range:=Rng, _
      ShortCitation:=" ", LongCitation:=CurrentPosition & ": " & ItemText, _
      LongCitationAutoText:="", Category:=1
      ActiveWindow.ActivePane.View.ShowAll = False
    End If
  Next i
End With
Application.ScreenUpdating = True
End Sub


Cheers
[MS MVP - Word]
 
Sorry mint, I am NOT trying to be critical. The original question was Range vs. Selection. My "Really? Are you sure?" was in respone to
I am trying to generate the bracketed CrossReference at the selection point
My bolding.

In fact, you do not - I think - want to do that. Because the Selection point can be anywhere. You want to put your reference at a specific place in relation to the current selection point.

Anyway, I hope this has moved this forward.

"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
>From Word VBA help:

What Word VBA help doesn't say, but should, is that End is a hangover from much older versions of Basic and should be avoided whenever possible.

It does point out that
VBA Help said:
Note
The End statement stops code execution abruptly, without invoking the Unload, QueryUnload, or Terminate event, or any other Visual Basic code. Code you have placed in the Unload, QueryUnload, and Terminate events of forms and class modules is not executed. Objects created from class modules are destroyed, files opened using the Open statement are closed, and memory used by your program is freed. Object references held by other programs are invalidated.

The End statement provides a way to force your program to halt. For normal termination of a Visual Basic program, you should unload all forms. Your program closes as soon as there are no other programs holding references to objects created from your public class modules and no code executing.

I'd hazard that Gerry was questioning your use of the statement, not what the statement actually did
 
Thank you. Precisely. I was trying to point out that the intent is to - ahem - exit the Sub if a condition is not met.
Code:
If Selection.Range.ListFormat.ListType <> wdListOutlineNumbering Then
So, why not instruct VBA to do exactly (and only) that - Exit the Sub?

True, End does exit the Sub, but it does so by blowing the hull (of the Sub.....) to pieces, destroying everything. Thus, it is perhaps not appropriate for - ahem - the intent.

"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
Thanks guys.

Gerry,

I got the point of "Really?". Originally I did want to put the crossref at the selection point. Since the users will be me and one other who I could trust to put the the cursor at the desired point that was a good requirement at the time.

As you can see the version 2 code does in fact allow the cursor to be anywhere within a paragraph and will place the crossref "in front" of the paragraph.

As to how I wound up with "End" rather than "Exit Sub", well...

"End Sub" didn't work, "Exit" by itself didn't work, "Quit" didn't work, "End" did, so I stopped trying.
 


Hey mint!

I think that SOMEONE deserves a [purple]LITTLE purple star[/purple]!

Skip,

[glasses]Just traded in my old subtlety...
for a NUANCE![tongue]
 
Let's get back to the original question though. Range vs Selection.

I still do not understand precisely what you are trying to do. Will you ONLY use the code for whatever you have actually selected? Or do you want to action across the whole document, not just what you Select? If so, then using a Paragraph object may be useful, something like ...
Code:
Option Explicit

Sub Mint()
Dim oPara As Paragraph
Dim CurrentPosition
For Each oPara In ActiveDocument.Paragraphs
   If oPara.Range.ListFormat.ListType = _
            wdListOutlineNumbering Then
 [COLOR=red]     ' following actions will ONLY be applied to
      ' paragraphs that are wdListOutlineNumbering[/color red]
       CurrentPosition = oPara.Range.ListFormat.ListString
 [COLOR=red]     ' etc. etc. etc.
      ' [b]NOW[/b] you can start to use Range vs. Selection[/color red]
      With oPara.[b]Range[/b]
         .InsertBefore "[CDRL ]"
         ' yadda yadda
      End With
   End If
Next
End Sub
In the above there is NO use of Selection at all.

"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
Only certain paragraphs are important enough to deserve having the crossref and TOA marking applied, and the selection process is manual by the user.

However For each paragraph in activedocument.paragraphs may be helpful for some other clean-up efforts.
 
and the selection process is manual by the user"

Well then, you are pretty much stuck with using Selection then. However.......you can still use For Each paragraphs within the Selection.
Code:
Sub Mint()
Dim oPara As Paragraph
Dim CurrentPosition
For Each oPara In [b]Selection[/b].Paragraphs
   If oPara.Range.ListFormat.ListType = _
            wdListOutlineNumbering Then
      ' following actions will ONLY be applied to
      ' paragraphs that are wdListOutlineNumbering
       CurrentPosition = oPara.Range.ListFormat.ListString
      ' etc. etc. etc.
      ' NOW you can start to use Range vs. Selection
      With oPara.Range
         .InsertBefore "[CDRL ]"
         ' yadda yadda
      End With
   End If
Next
End Sub
This could be handy if the user made a selection that covers paragraphs that are NOT wdListOutlineNumbering. Say a paragraph mark before or after the list. Those will be ignored.

"A little piece of heaven
without that awkward dying part."

advertisment for Reese's Peanut Butter Cups (a chocolate/peanut butter confection)

Gerry
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top