我有一个 Excel 文件,我想让人们填写特定内容。如果行中的第一个单元格已填写,我想将行中的一系列单元格设置为必填。例如,如果单元格 A7 已填写,则单元格 B7-O7 也需要填写。这个过程会重复,直到 A 列中有一个单元格未填写。
我在这里尝试了一些不太好的 VBA 编码
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Sheets("Sheet1").Range("A7").Value <> "" And Sheets("Sheet1").Range("B7").Value = "" Or Range("C7").Value = "" Or Range("D7").Value = "" Or Range("E7").Value = "" Or Range("F7").Value = "" Or Range("G7").Value = "" Or Range("H7").Value = "" Or Range("I7").Value = "" Or Range("J7").Value = "" Or Range("K7").Value = "" Or Range("L7").Value = "" Or Range("M7").Value = "" Or Range("N7").Value = "" Or Range("O7").Value = "" Then
MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
Cancel = True
ElseIf Sheets("Sheet1").Range("A8").Value <> "" And Sheets("Sheet1").Range("B8").Value = "" Or Range("C8").Value = "" Or Range("D8").Value = "" Or Range("E8").Value = "" Or Range("F8").Value = "" Or Range("G8").Value = "" Or Range("H8").Value = "" Or Range("I8").Value = "" Or Range("J8").Value = "" Or Range("K8").Value = "" Or Range("L8").Value = "" Or Range("M8").Value = "" Or Range("N8").Value = "" Or Range("O8").Value = "" Then
MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
Cancel = True
ElseIf Sheets("Sheet1").Range("A9").Value <> "" And Sheets("Sheet1").Range("B9").Value = "" Or Range("C9").Value = "" Or Range("D9").Value = "" Or Range("E9").Value = "" Or Range("F9").Value = "" Or Range("G9").Value = "" Or Range("H9").Value = "" Or Range("I9").Value = "" Or Range("J9").Value = "" Or Range("K9").Value = "" Or Range("L9").Value = "" Or Range("M9").Value = "" Or Range("N9").Value = "" Or Range("O9").Value = "" Then
MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
Cancel = True
End If
End Sub
它一直有效直到我到达:
ElseIf Sheets("Sheet1").Range("A9").Value <> "" And Sheets("Sheet1").Range("B9").Value = "" Or Range("C9").Value = "" Or Range("D9").Value = "" Or Range("E9").Value = "" Or Range("F9").Value = "" Or Range("G9").Value = "" Or Range("H9").Value = "" Or Range("I9").Value = "" Or Range("J9").Value = "" Or Range("K9").Value = "" Or Range("L9").Value = "" Or Range("M9").Value = "" Or Range("N9").Value = "" Or Range("O9").Value = "" Then
MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
Cancel = True
End If
然后即使 A9 没有填写,MsgBox 也会弹出。
我知道这不是实现我想要的最佳方式,但这就是我想出的办法。有没有更好的代码建议?
答案1
您的条件链中有一个错误:
cond1 And cond2 Or cond3 Or cond4
如果或True
中的一个(或两个)为 ,则始终会求值为。这是因为会在 之前求值。参见cond3
cond4
True
And
Or
文档了解更多信息。
您可以使用括号来调整评估顺序:
cond1 And (cond2 Or cond3 Or cond4)
此表达式True
仅当cond1
和任何cond2, cond3, cond4
都是True
。
对于您来说,我建议对您的代码进行以下改进:
- 首先,阅读有关 VBA 中的循环。
For ... Next
这Do ... Loop
是您需要了解的两种类型。 - 然后,为了让事情更清楚一点(也就是说,让你的意图在代码中可见),把验证代码放入其自己的子程序/函数中。
- 最后,为了让发生的事情更加明显,你可以拆分这些长链条件。
如果我们现在看一下该Workbook_BeforeSave
过程,它在那里做什么并不明显(对你来说可能很明显,因为你刚刚把代码放在那里,它在你的脑海中还很新鲜 - 但在 3/6/12 个月后回到这张表,你首先需要了解它在做什么)。让我们来解决这个问题:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = IsUserInputMissing
End Sub
Private Function IsUserInputMissing() as Boolean
' Validation code goes in here
End Function
现在,每个查看代码的人都可以一眼看出保存工作簿时会发生什么。
这行
If Sheets("Sheet1").Range("A7").Value <> "" And Sheets("Sheet1").Range("B7").Value = "" Or Range("C7").Value = "" Or Range("D7").Value = "" Or Range("E7").Value = "" Or Range("F7").Value = "" Or Range("G7").Value = "" Or Range("H7").Value = "" Or Range("I7").Value = "" Or Range("J7").Value = "" Or Range("K7").Value = "" Or Range("L7").Value = "" Or Range("M7").Value = "" Or Range("N7").Value = "" Or Range("O7").Value = "" Then
看起来不太友好。逐字逐句地写着If FirstCellIsNotEmpty And AnyFollowingCellIsEmpty Then
。让我们这样编码。
Dim FirstCellIsEmpty as Boolean
FirstCellIsEmpty = Sheets("Sheet1").Range("A7").Value = ""
Dim AnyFollowingCellIsEmpty as Boolean
AnyFollowingCellIsEmpty = WorksheetFunction.CountBlank(Sheets("Sheet1").Range("B7:O7")) > 0
If Not FirstCellIsEmpty And AnyFollowingCellIsEmpty Then
MsgBox "I don't know any Swedish. But please fill out the necessary cells."
End If
请注意使用WorksheetFunction.CountBlank
以避免必须输入要检查的每个单元格。
最后,我将举例说明你的IsUserInputMissing
功能可以看起来像。(不过,仍有很大的改进空间。)
Private Function IsUserInputMissing() As Boolean
' Easy way to set the beginning of the range
Const FirstRowToBeChecked As Long = 7
' Set a reference to the sheet that needs checking
Dim Ws As Worksheet
Set Ws = ThisWorkbook.Worksheets("Sheet1")
Dim iRow As Long
iRow = FirstRowToBeChecked
Do
Dim FirstCellIsEmpty As Boolean
FirstCellIsEmpty = Ws.Cells(iRow, 1).Value = vbNullString ' vbNullString is a clearer way of saying ""
' Exit loop at the first empty row
If FirstCellIsEmpty Then Exit Do
Dim AnyFollowingCellIsEmpty As Boolean
AnyFollowingCellIsEmpty = WorksheetFunction.CountBlank(Ws.Range(Ws.Cells(iRow, 2), Ws.Cells(iRow, 15))) > 0
If AnyFollowingCellIsEmpty Then
' Any time the requirements are not met, notify user and abort checking and saving
' This is not as elegant as checking the whole range and collecting info about all missing inputs
' But it's way easier to code :)
MsgBox "I don't know any Swedish. But please fill out the necessary cells. Tack!"
IsUserInputMissing = True
Exit Function
End If
' Don't forget to increment the counter, otherwise you've got yourself an endless loop
iRow = iRow + 1
Loop
' If execution reaches this line, all rows fulfil the requirement
' IsUserInputMissing will have its Default value: False
End Function
慢慢来,慢慢解决。我尽量把事情说清楚。但如果有什么不清楚的地方,请随时询问。:)