MS word 2016中我的VBA for循环不工作

MS word 2016中我的VBA for循环不工作,vba,for-loop,ms-word,Vba,For Loop,Ms Word,我在MS word VBA中遇到以下代码问题 For i = 6 To ActiveDocument.Tables(2).Rows.Count z = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2 x = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2 b = ActiveDocument.Tables(2).Cell(i, 5).Range.

我在MS word VBA中遇到以下代码问题

For i = 6 To ActiveDocument.Tables(2).Rows.Count
    z = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2
    x = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2
    b = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText

    If (z = 0 And x = 0) Then
        If b = True Then
            MsgBox "Please do error 1!"
            If vbOK Then
                Exit Sub
            End If
        Else
            MsgBox "Please do error 2!"
            If vbOK Then
                Exit Sub
            End If
        End If
    Else
        If b = True Then
            MsgBox "Please do error 3!"
            If vbOK Then
                Exit Sub
            End If
        Else
            Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
            If Confirm = vbNo Then
                Exit Sub
            End If
        End If
    End If
Next i

for循环不会进入第二行检查z或x是否有值

我怀疑移动
下一个I
会解决任何问题。这段代码充满了恶意

我的印象是,您的代码旨在检查表中的三列(从第6行向下)-这似乎是一个一致性检查

命名
z
x
b
都不是很好的描述。使用像
lengthCol2
lengthCol3
haspocholdertext
这样的名称将帮助您更紧密地遵循逻辑

使用显式
选项
。总是

您使用标准的
MsgBox
调用,默认情况下只有一个按钮(“OK”)。
MsgBox
是一个阻塞代码元素,因此在用户单击“确定”之前,宏将不会进行

vbOK
是一个枚举值(值=1)。所以
如果vbOK那么
总是为真。总是。您似乎在寻找某种用户输入,但不清楚该输入是什么

解决这些简单步骤为我们提供了:

For i = 6 To ActiveDocument.Tables(2).Rows.Count
    lengthCol2 = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2
    lengthCol3 = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2
    hasPlaceHolderText = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText

    If (lengthCol2 = 0 And lengthCol3 = 0) Then
        If hasPlaceHolderText = True Then
            MsgBox "Please do error 1!"
            Exit Sub
        Else
            MsgBox "Please do error 2!"
            Exit Sub
        End If
    Else
        If hasPlaceHolderText = True Then
            MsgBox "Please do error 3!"
            Exit Sub
        Else
            Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
            If Confirm = vbNo Then
                Exit Sub
            End If
        End If
    End If
Next i
For i = 6 To ActiveDocument.Tables(2).Rows.Count
    lengthCol2 = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2
    lengthCol3 = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2
    hasPlaceHolderText = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText

    If (lengthCol2 > 0 OR lengthCol3 > 0) AND hasPlaceHolderText Then
         Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
         If Confirm = vbYes Then
             'Do submission code here - or call the submission procedure
         End If  ' Just do nothing if they say "No" - this is what your current code does.
    Else
        ' The next line could be used instead of the nested IF-the-else statements following.
        'MsgBox " Table contents are not valid, please ensure columns 2,3 and 5 are completed"
        If hasPlaceHolderText then
            If (lengthCol2 = 0 And lengthCol3 = 0) Then
                MsgBox  "Please do error 1!"
            Else
                MsgBox  "Please do error 2!"
            EndIF
        Else
            MsgBox  "Please do error 3!"
        End If
    End If
Next i
你的逻辑是消极偏见的——也就是说,你想找到不做某事的理由,而不是去做某事。积极偏见逻辑通常更容易理解和维护——编码者的意图更清晰

改写逻辑给我们提供了:

For i = 6 To ActiveDocument.Tables(2).Rows.Count
    lengthCol2 = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2
    lengthCol3 = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2
    hasPlaceHolderText = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText

    If (lengthCol2 = 0 And lengthCol3 = 0) Then
        If hasPlaceHolderText = True Then
            MsgBox "Please do error 1!"
            Exit Sub
        Else
            MsgBox "Please do error 2!"
            Exit Sub
        End If
    Else
        If hasPlaceHolderText = True Then
            MsgBox "Please do error 3!"
            Exit Sub
        Else
            Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
            If Confirm = vbNo Then
                Exit Sub
            End If
        End If
    End If
Next i
For i = 6 To ActiveDocument.Tables(2).Rows.Count
    lengthCol2 = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) - 2
    lengthCol3 = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) - 2
    hasPlaceHolderText = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText

    If (lengthCol2 > 0 OR lengthCol3 > 0) AND hasPlaceHolderText Then
         Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
         If Confirm = vbYes Then
             'Do submission code here - or call the submission procedure
         End If  ' Just do nothing if they say "No" - this is what your current code does.
    Else
        ' The next line could be used instead of the nested IF-the-else statements following.
        'MsgBox " Table contents are not valid, please ensure columns 2,3 and 5 are completed"
        If hasPlaceHolderText then
            If (lengthCol2 = 0 And lengthCol3 = 0) Then
                MsgBox  "Please do error 1!"
            Else
                MsgBox  "Please do error 2!"
            EndIF
        Else
            MsgBox  "Please do error 3!"
        End If
    End If
Next i
请注意,在您的逻辑中,第2列或第3列可以为空,并且(只要未显示占位符文本),您的文档已准备好提交。也许您的意思是
,而不是
(即所有列都应填写)

还有一个问题。你的循环。正如目前所写的那样,您在逻辑上循环,因此您要求用户检查错误或根据每行中的错误检查提交文档x次。但是,仅仅移动
下一个i
并不能解决问题,因为只保留最后一行中的结果。换句话说,前面的所有行都可能是坏的/无效的,但您仍然可以提交

我们可以通过创建累积逻辑来修复最后一点。换句话说,我们在一个短循环中跟踪错误,然后进入主逻辑。这看起来有点复杂,但实际上是相对直接的。但是,我们确实需要更多的
Boolean
s来使它工作

Dim rowsOK as Boolean
'explicit initialisation - I am working on a positive bias here.
    rowsOK = True

For i = 6 To ActiveDocument.Tables(2).Rows.Count
    Dim lengthCol2OK as Boolean  ' Use these just to make the logic clearer and the code cleaner
    Dim lengthCol3OK as Boolean
    Dim hasPlaceHolderTextOK as Boolean
    lengthCol2OK = Len(ActiveDocument.Tables(2).Cell(i, 2).Range.Text) > 2
    lengthCol3OK = Len(ActiveDocument.Tables(2).Cell(i, 3).Range.Text) > 2
    hasPlaceHolderTextOK = ActiveDocument.Tables(2).Cell(i, 5).Range.ContentControls.Item(1).ShowingPlaceholderText
    rowsOK = rowsOK And ((lengthCol2OK Or lengthCol3OK) And hasPlaceHolderTextOK)  ' Note: Using "Or" here as per original code logic
    ' Extra logic could go here to message the user if any of the above are false.
Next i

If rowsOK Then
    Confirm = MsgBox("Are you sure to submit?", vbYesNo, "Confirmation")
    If Confirm = vbYes Then
        'Do submission code here - or call the submission procedure
    End If  ' Just do nothing if they say "No" - this is what your current code does.
Else
    MsgBox " Table contents are not valid, please ensure columns 2,3 and 5 are completed"
End If
但是,此逻辑适用于所有行,因此在主循环中不可能识别单个行错误。您可以在下一个循环的
中使用额外的逻辑向用户发送错误消息

现在代码是可维护的,并且更可能实现您想要的功能

要点:

  • 使用显式
    选项
    。这可以防止输入错误,并确保您以您想要的方式使用变量
  • 使用有意义的变量名。让你更容易跟随你想做的事情
  • 不要将枚举值与函数返回值混淆。不要混淆常量和变量
  • 花些时间检查你的逻辑链,确保它们做你想做的事,而不是不做你不想做的事。后者丢失无效路径的可能性更大

解决了这个问题。下一个i应该放在If语句之前,以便进行循环。