none
Use VBA to find the activedocument.paragraph Item count the cursor is in RRS feed

  • Question

  • Word 2010/VBA

    Is it possible to determine which paragraph your cursor is located, through VBA.  For example if  the ActiveDocument.Paragraphs.Count is equal to 5 and my cursor is somewhere in paragraph 2,

    Is there a way to return the value of 2 representing paragraph 2?  If the cursor is in paragraph 3, then the value returned would be 3 and so on.

    I have worked a little more in Excel and just use activecell.  I cannot locate anything equivalent. 

    I am trying to launch a macro that will locate the cursor in the current paragraph and then allow the user to move forward or backwards through all the paragraphs, performing certain tasks.   

    Thanks.

    Tuesday, April 2, 2013 12:39 AM

Answers

  • How about this :

    Sub TestGetParagraphIndex()
        Dim r As word.Range
        
        Set r = Selection.Range
        Debug.Print GetParagraphIndex(r)
    End Sub
    
    Function GetParagraphIndex(r As word.Range) As Long
        Dim p As word.Paragraph
        Dim rParas As word.Range
        
        Set p = r.Paragraphs(1)
        Set rParas = ActiveDocument.content
        rParas.End = p.Range.End
        GetParagraphIndex = rParas.Paragraphs.Count
    End Function
    


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by GolfNwhiting Tuesday, April 2, 2013 5:34 PM
    Tuesday, April 2, 2013 10:05 AM
    Moderator
  • It works exactly as I had hoped.  I was heading down the wrong path all together.  I had tried to DIM r as Paragraph.Range. I then tried to set a variable like "Set r = ActiveDocument.Content.paragraphs". I was very confused.  With my background in Excel, I was still kinda thinking in terms of cell references.

    I can see from debugging the code you provided in VB Editor that my background in Excel caused me to think there was an exact reference to the cursor locations through something like "ActiveParagraph.count.index" or something that you could access to get the current index value of the paragraph.

    I was way off.  Let me go through the code and see if I have a basic understanding of the magic.

    Dim r as word.Range

    'A variable that stores the range object through Selection method.  Nothing needs to be selected to reference the selection method....I always thought you had to select char, word, sentence or paragraph to to use "Selection". My bad.

    Set r = Selection.Range

    'I assume this assigns a Range Object associated with the cursor location and the paragraph.  I could not tell what the context of the Range object.  I assume WORD object or just the SYTLE object. The "Add Watch window" in VB Macro Editor shows the range object contains only ITEM 1, r.paragraphs.item 1 through a expanded view of the variable r(in the debug watch window), since only 1 paragraph is listed in the range object.  There are 10 paragraphs in my test document.  This appears to set the range to the ACTIVE paragraph.  However, you do not know which paragraph in the document Item 1 references since you do not have the paragraph index number.  This is accomplished using your function.

    Debug.Print GetParagraphIndex(r) 

    'execute the function.  

    Dim p As word.Paragraph

    'Limit the variable to a single Paragraph object.  I was unclear if you put Word.Paragraphs, if  it means more than one paragraph object. 

    Dim rParas As word.Range

    'Can stores contents of the entire active document.  

    Set p = r.Paragraphs(1)

    'Set p to Paragraph properties stored in r.  Appears to narrow the object properties to a single paragraph object allowing you set the RANGE end or all the contents of the active document up to that paragraph.

    Set rParas = ActiveDocument.content

    'Set rParas to range of all content in active document.

    rParas.End = p.Range.End


    'Set the content range of rParas to the content up to and including in range of p.

    GetParagraphIndex  =  rPara.Paragraphs.Count

    'Count the number of paragraphs in new range rPara.  This gives you the last paragraph in the range up to your cursor location.  Well done and Thanks!

    Let me know if my thought process are heading down the right path.

    For example could you have done:

    GetParagraphIndex = p.Paragraphs.count

    or is that not a valid reference because the object p references a single paragraph object which is why you assigned the Range.END value to the .END value of the rPara, which contained the entire contents of the active document, and then counted the paragraphs?

    • Marked as answer by GolfNwhiting Tuesday, April 2, 2013 5:37 PM
    Tuesday, April 2, 2013 5:34 PM
  • <<Dim r as word.Range

    'A variable that stores the range object through Selection method.  Nothing needs to be selected to reference the selection method....I always thought you had to select char, word, sentence or paragraph to to use "Selection". >>

    The blinking cursor is also a "Selection". Basically, Selection = where the focus is in the document.

    <<Set r = Selection.Range

    'I assume this assigns a Range Object associated with the cursor location and the paragraph.>>

    This assigns a Range object to the exact SELECTION. It could be a blinking cursor, or a "real" selection, of any length. The Range will encompass exactly those characters (and related graphical objects, etc.) By association, the Range can intersect paragraphs, tables and these other things, which can be addressed through it.

    If you use an index value - Range.Paragraphs(index) it will pick up that index associated with the Range (as opposed to the index relative to the entire document). This works with almost, but not all things. Thus, Range.Paragraphs(1) will return the first paragraph in or surrounding the Range. The same applies to Tables. (The "surrounding" does not, however, work with Field or ContentControl objects.)

    <<'Limit the variable to a single Paragraph object.  I was unclear if you put Word.Paragraphs, if  it means more than one paragraph object. >>

    Paragraphs would be a collection of Paragraph objects - multiple paragraphs. A Range can contain multiple paragraphs, but the collection could contain only one paragraph.

    <<For example could you have done:

    GetParagraphIndex = p.Paragraphs.count>>

    No, that would not have worked because p is a single paragraph object and would thus always return 1.

    The .Start and .End properties of the Range object return the index value of the characters of the start and end points of the Range. Theoretically, you could count through the text to get those values, but in practice this often yields an incorrect result due to "hidden" things in the document content.

    So, yes, what I do is set a Range to inlcude all paragraphs from the beginning of the document to the end of the first paragraph associated with the Selection, then count the paragraphs that encompasses.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, April 3, 2013 5:31 PM
    Moderator

All replies

  • How about this :

    Sub TestGetParagraphIndex()
        Dim r As word.Range
        
        Set r = Selection.Range
        Debug.Print GetParagraphIndex(r)
    End Sub
    
    Function GetParagraphIndex(r As word.Range) As Long
        Dim p As word.Paragraph
        Dim rParas As word.Range
        
        Set p = r.Paragraphs(1)
        Set rParas = ActiveDocument.content
        rParas.End = p.Range.End
        GetParagraphIndex = rParas.Paragraphs.Count
    End Function
    


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by GolfNwhiting Tuesday, April 2, 2013 5:34 PM
    Tuesday, April 2, 2013 10:05 AM
    Moderator
  • It works exactly as I had hoped.  I was heading down the wrong path all together.  I had tried to DIM r as Paragraph.Range. I then tried to set a variable like "Set r = ActiveDocument.Content.paragraphs". I was very confused.  With my background in Excel, I was still kinda thinking in terms of cell references.

    I can see from debugging the code you provided in VB Editor that my background in Excel caused me to think there was an exact reference to the cursor locations through something like "ActiveParagraph.count.index" or something that you could access to get the current index value of the paragraph.

    I was way off.  Let me go through the code and see if I have a basic understanding of the magic.

    Dim r as word.Range

    'A variable that stores the range object through Selection method.  Nothing needs to be selected to reference the selection method....I always thought you had to select char, word, sentence or paragraph to to use "Selection". My bad.

    Set r = Selection.Range

    'I assume this assigns a Range Object associated with the cursor location and the paragraph.  I could not tell what the context of the Range object.  I assume WORD object or just the SYTLE object. The "Add Watch window" in VB Macro Editor shows the range object contains only ITEM 1, r.paragraphs.item 1 through a expanded view of the variable r(in the debug watch window), since only 1 paragraph is listed in the range object.  There are 10 paragraphs in my test document.  This appears to set the range to the ACTIVE paragraph.  However, you do not know which paragraph in the document Item 1 references since you do not have the paragraph index number.  This is accomplished using your function.

    Debug.Print GetParagraphIndex(r) 

    'execute the function.  

    Dim p As word.Paragraph

    'Limit the variable to a single Paragraph object.  I was unclear if you put Word.Paragraphs, if  it means more than one paragraph object. 

    Dim rParas As word.Range

    'Can stores contents of the entire active document.  

    Set p = r.Paragraphs(1)

    'Set p to Paragraph properties stored in r.  Appears to narrow the object properties to a single paragraph object allowing you set the RANGE end or all the contents of the active document up to that paragraph.

    Set rParas = ActiveDocument.content

    'Set rParas to range of all content in active document.

    rParas.End = p.Range.End


    'Set the content range of rParas to the content up to and including in range of p.

    GetParagraphIndex  =  rPara.Paragraphs.Count

    'Count the number of paragraphs in new range rPara.  This gives you the last paragraph in the range up to your cursor location.  Well done and Thanks!

    Let me know if my thought process are heading down the right path.

    For example could you have done:

    GetParagraphIndex = p.Paragraphs.count

    or is that not a valid reference because the object p references a single paragraph object which is why you assigned the Range.END value to the .END value of the rPara, which contained the entire contents of the active document, and then counted the paragraphs?

    • Marked as answer by GolfNwhiting Tuesday, April 2, 2013 5:37 PM
    Tuesday, April 2, 2013 5:34 PM
  • <<Dim r as word.Range

    'A variable that stores the range object through Selection method.  Nothing needs to be selected to reference the selection method....I always thought you had to select char, word, sentence or paragraph to to use "Selection". >>

    The blinking cursor is also a "Selection". Basically, Selection = where the focus is in the document.

    <<Set r = Selection.Range

    'I assume this assigns a Range Object associated with the cursor location and the paragraph.>>

    This assigns a Range object to the exact SELECTION. It could be a blinking cursor, or a "real" selection, of any length. The Range will encompass exactly those characters (and related graphical objects, etc.) By association, the Range can intersect paragraphs, tables and these other things, which can be addressed through it.

    If you use an index value - Range.Paragraphs(index) it will pick up that index associated with the Range (as opposed to the index relative to the entire document). This works with almost, but not all things. Thus, Range.Paragraphs(1) will return the first paragraph in or surrounding the Range. The same applies to Tables. (The "surrounding" does not, however, work with Field or ContentControl objects.)

    <<'Limit the variable to a single Paragraph object.  I was unclear if you put Word.Paragraphs, if  it means more than one paragraph object. >>

    Paragraphs would be a collection of Paragraph objects - multiple paragraphs. A Range can contain multiple paragraphs, but the collection could contain only one paragraph.

    <<For example could you have done:

    GetParagraphIndex = p.Paragraphs.count>>

    No, that would not have worked because p is a single paragraph object and would thus always return 1.

    The .Start and .End properties of the Range object return the index value of the characters of the start and end points of the Range. Theoretically, you could count through the text to get those values, but in practice this often yields an incorrect result due to "hidden" things in the document content.

    So, yes, what I do is set a Range to inlcude all paragraphs from the beginning of the document to the end of the first paragraph associated with the Selection, then count the paragraphs that encompasses.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, April 3, 2013 5:31 PM
    Moderator