列表中有新段落时如何获取列表级别

时间:2018-12-14 17:04:47

标签: vba ms-word word-vba

我正在使用VB遍历Word文档的各个段落。该文档包含项目符号列表。

我发现了如何测试当前段落是否为项目符号列表中的项目:

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

我想在Word文档中区分以下两种情况:

情况1:

  • 第一项的第一段

    第一项第二段

  • 第二项的第一段

情况2:

  • 第一个项目符号列表的第一(也是唯一)项

两个项目符号列表之间的一些文本

  • 第二个项目符号列表的第一(也是唯一)项

当我分析第二段时,如何知道我处于第一还是第二种情况?

更笼统地说,如果列表有多个级别,我怎么知道我的段落在哪个级别?

(我知道我可以测试pParagraph.Range.ListFormat.ListLevelNumber,但这仅适用于与新项目相对应的段落;当有一个新段落不包含项目时,pParagraph.Range.ListFormat.List什么都不是,级别始终为1)

2 个答案:

答案 0 :(得分:1)

我只是偶尔使用Word-VBA,但这仅用于从某些跨平台应用程序中写入单词,而不能广泛地处理任何Word文档。我可以称自己是Word_VBA的新手。但是,发现有趣的地方后,我进行了一些谷歌搜索并学习了一些有趣的观点。

至少在Word 2007(我仅使用2007)中,列表项(即情况1:第一项的第二段)中不能有任何段落。请参考link1link2link3

假设您需要处理手动换行符作为段落,并且需要具有相应的范围对象,文本,列表级别,列表值等才能进一步处理,得出一个可行的解决方案。它正在使用3个级别的嵌套列表和手动换行符的临时示例。可以尝试代码

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

很高兴(如果发现有用)。

答案 1 :(得分:0)

我终于找到了一种做自己想做的方法。

每次我有一个与列表开头相对应的段落,我都使用pParagraph.LeftIndent记录该段落的左缩进。由于列表可能有多个级别,因此我记录了一个堆栈,其中包含当前打开的每个级别的缩进。

当我有一个不是列表开头的新段落时,可以通过将其左缩进与每个打开的列表级别的缩进进行比较来推断其列表级别(或事实上它根本不是列表的一部分)

例如在此示例中:

  • 项目1级别1

    • 项目1级别2

      第1行

    第2行

第3行

我可以推断出“第1行”是“第1级项目2”的一部分,“第2行”是“第1级项目1”的一部分,而“第3行”不在列表中。