首页 > 解决方案 > 一旦我使用 With...End With,Word 宏就不起作用

问题描述

我今天在制作宏时遇到了一些奇怪的事情。我有很多使用相同模板的文档,所以我的宏扫描其中一个并根据标题(级别和编号)做一些事情。无论如何,这并不重要。这是代码

Private Sub MyMacro()
     Selection.HomeKey Unit:=wdStory

        While Not (Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 1) = "3")  'go to Title n°3
            Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
        Wend

        While ((Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 1) = "3"))  'do not go further than title n°3
            'if the curent title level is 2 and ended with 1,2 or 3 then
            If Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 2 And Selection.Paragraphs(1).Range.ListFormat.ListValue < 4 Then
                'Do Something
            ElseIf Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 3 And Selection.Paragraphs(1).Range.ListFormat.ListValue <> 4 And Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 4) = "3.1." Then
                'Do something else
            ElseIf Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 4 And Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 5) = "3.2.1" Then
                'and a last one
            End If
            'go to the next title in the document
            Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
        Wend
End Sub

这段代码有效,但正如您所见,它不是很容易阅读......我尝试插入一条With...End With语句来改进它。

    With Selection.Paragraphs(1).Range.ListFormat
        'isert here the same code as before with only .ListString and .ListLevelNumber
    End With

不幸的是,这使我的While循环失败了,我不知道为什么。我监视了输出,它似乎ListString总是返回第一个标题(宏开始的地方)。你知道为什么吗?

非常感谢提前

问候

编辑:最终代码应该是这样的

Private Sub MyMacro()
Selection.HomeKey Unit:=wdStory

With Selection.Paragraphs(1).Range.ListFormat
    While Not (Left(.ListString, 1) = "3")  'go to Title n°3
        Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
    Wend

    While ((Left(.ListString, 1) = "3"))  'do not go further than title n°3
        'if the curent title level is 2 and ended with 1,2 or 3 then
        If .ListLevelNumber = 2 And .ListValue < 4 Then
            'Do Something
        ElseIf .ListLevelNumber = 3 And .ListValue <> 4 And Left(.ListString, 4) = "3.1." Then
            'Do something else
        ElseIf .ListLevelNumber = 4 And Left(.ListString, 5) = "3.2.1" Then
            'and a last one
        End If
        'go to the next title in the document
        Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
    Wend
End With
End Sub

标签: vbams-word

解决方案


您尝试的原因不起作用With是始终Selection.Paragraphs(1).Range 在调用此行时引用并测试最左边的字符是否为“3”。由于第一段开头的数字永远不会改变,因此代码不会像您希望的那样工作。如果你把它放在Debug.Print .ListString前面,Wend你可以看到它永远不会改变。

这是编写代码以使其更易于遵循的另一种方法,只是为了让您了解如何使用Range对象。它循环文档中所有编号(“列表”)的段落,并将跳过任何未编号的段落。在您的情况下,这可能不是最佳选择 - 因为您没有提供有关文档的任何详细信息,所以很难知道。

Sub MyMacro()
    Dim rng As Word.Range
    Dim paras As Word.ListParagraphs
    Dim para As Word.Paragraph
    Dim lvl As Long, listVal As Long

    Set paras = ActiveDocument.ListParagraphs

    For Each para In paras
        Set rng = para.Range
        If Left(rng.ListFormat.ListString, 1) = "3" Then
            lvl = rng.ListFormat.ListLevelNumber
            listVal = rng.ListFormat.ListValue
            Select Case lvl
                Case 2
                    If listVal < 4 Then
                        Debug.Print "Case 2: lvl " & lvl & "; listVal " & listVal
                    End If
                Case 3
                    If listVal <> 4 And Left(rng.ListFormat.ListString, 4) = "3.1." Then
                        Debug.Print "Case 3: lvl " & lvl & "; listVal " & listVal
                    End If
                Case 4
                    If Left(rng.ListFormat.ListString, 5) = "3.2.1" Then
                        Debug.Print "Case 4: lvl " & lvl & "; listVal " & listVal
                    End If
                Case Else
                    Debug.Print "Case else"
            End Select
        End If
    Next
End Sub

推荐阅读