0
votes

I am iterating through paragraphs of a Word document using VB. The document contains bulleted lists.

I found how to test whether the current paragraph is an item of a bulleted list:

If (Not pParagraph.Range.ListFormat.List Is Nothing) Then
  ...
End If

I would like to distinguish between the two following situations in the Word document:

Situation 1:

  • First paragraph of first item

    Second paragraph of first item

  • First paragraph of second item

Situation 2:

  • First (and only) item of the first bulleted list

Some text between two bulleted lists

  • First (and only) item of the second bulleted list

When I parse the second paragraph, how can I know whether I am in the first or second situation?

More generally, if there are several levels of list, how can I know at which level my paragraph is?

(I am aware that I can test pParagraph.Range.ListFormat.ListLevelNumber, but this work only for paragraphs corresponding to new items; when there is a new paragraph without item, pParagraph.Range.ListFormat.List is nothing and level is always 1).

2
Your question isn't clear, I'm afraid... Can you narrow it down to a particular situation and give examples?Cindy Meister

2 Answers

1
votes

I only occasionally work with Word-VBA and that's only for writing in word from some cross platform application not for extensively processing any Word document. I can fairly call myself novice in Word_VBA. However, finding it interesting I went through some googling and come to learn some interesting points.

At least in Word 2007 (i am using 2007 only) there could be no paragraph within a list item (i.e.Situation 1: Second paragraph of first item). May please refer the link1 , link2 & link3.

Assuming you required to treat Manual Line Breaks as paragraph and required to have a corresponding range object,Text,List Level, List Value etc to process further, I somehow come to a working solution. It is working with a makeshift sample of 3 level of nested list and Manual Line Breaks. May try the code

Sub test()
Dim Pg As Paragraph, Sl As Long, Rng As Range, LineRng As Range
Dim PgType As String, ListNo As Long, LevelNo As Long, PgTxt As String, LIneTxt As String
Dim ManNewLine As Long, St As Long
Sl = 0
    For Each Pg In ThisDocument.Paragraphs
        If Pg.Range.ListFormat.List Is Nothing Then
        PgType = "Normal Para"
        Else
        PgType = "List Para"
        End If
    Set Rng = Pg.Range
    ListNo = Pg.Range.ListFormat.ListValue  ' Document level Paragraph will return zero as ListValue. 
    LevelNo = Pg.Range.ListFormat.ListLevelNumber
    PgTxt = Pg.Range.Text

    'Add the below section code for treating Manual Line breaks as pargarph
    'Start of code section
    St = 1
    ManNewLine = InStr(St, PgTxt, Chr(11))
        If ManNewLine > 0 Then
            Do While ManNewLine > 0 And St <= Len(PgTxt)
            Sl = Sl + 1
            LineRng.SetRange Start:=Rng.Characters(St).Start, End:=Rng.Characters(ManNewLine).End
            LIneTxt = LineRng.Text
            'Debug.Print St, ManNewLine, LIneTxt
            'Process Paragraph based on LineRng, PgType, ListNo, LevelNo, LIneTxt, Sl
            ProcessParagraph LineRng, PgType, ListNo, LevelNo, LIneTxt, Sl
            St = ManNewLine + 1
            ManNewLine = InStr(St, PgTxt, Chr(11))
            ManNewLine = IIf(ManNewLine <= 0, Len(PgTxt), ManNewLine)
            Loop
        Else
        Sl = Sl + 1
        Set LineRng = Rng
        LIneTxt = PgTxt
        'Process Paragraph based on LineRng, PgType, ListNo, LevelNo, LIneTxt, Sl
        ProcessParagraph LineRng, PgType, ListNo, LevelNo, LIneTxt, Sl
        End If
    'End of code section
    Next Pg
End Sub
Private Sub ProcessParagraph(LineRng As Range, PgType As String, ListNo As Long, LevelNo As Long, LIneTxt As String, Sl As Long)
'Remark = "Para Type:" & PgType & " List No=" & ListNo & " ListLevel=" & LevelNo & "*" & LIneTxt & "*"
'Debug.Print "Sl=" & Sl & Remark
'add your code to Process Paragraph based on LineRng, PgType, ListNo, LevelNo, LIneTxt, Sl
End Sub

glad if found useful.

0
votes

I finally found a way to do what I wanted.

Each time I have a paragraph corresponding to a list opening, I record the left indent of that paragraph using pParagraph.LeftIndent. Since there may be several levels of list, I record a stack containing the indent of each level currently opened.

When I have a new paragraph which is not a list opening, I can infer its list level (or the fact it is not part of the list at all) by comparing its left indent to the indent of each opened level of list.

For instance in this example:

  • Item 1 level 1

    • Item 1 level 2

      Line 1

    Line 2

Line 3

I can infer "Line 1" is part of "Item 1 level2", "Line 2" is part of "Item 1 level 1" and "Line 3" is out of the list.