如果语句VBA
我在Excel VBA中使用If
和ElseIf
语句为数据库search写脚本。 search是通过一个UserForm
进行的,该UserForm
有两个字段,标记为Country
和Category
并在脚本中定义如下:
Dim country As String Dim Category As String country = Sheets("Results").Range("D5").Value Category = Sheets("Results").Range("D6").Value
信息在search国家方面被search和呈现,因此search运行所需的最小值是用户提供的国家在数据库中的国家。
根据用户input的标准,search将在名为“ Database
的工作表中运行一个数据表,并将结果粘贴到另一个名为“ Results
表中。 根据search条件,脚本将运行If
语句指定的几个选项。
scheme1 – 用户提供了一个国家和一个类别,并且:
-
country
存在于数据库中,但是; - 该
Category
不存在于特定的国家。
在这种情况下, MsgBox
会popup,说用户提供的国家和类别的特定组合不存在于数据库中。 该消息将询问用户是否希望针对所提供的国家的所有条目进行search,在这种情况下。 我已经写了相应的代码如下:
finalrow = Sheets("Database").Range("A200000").End(xlUp).Row For i = 2 To finalrow If Sheets("Database").Cells(i, 1) = country And _ (Category <> "" Or Sheets("Database").Cells(i, 3) <> Category) Then Dim question As Integer question = MsgBox("Unfortunately, the Database has no sources regarding " & Category & " in " & country & ". Would you perhaps want to broaden your search and see all sources regarding " & country & "?", vbYesNo + vbQuestion, "Empty Sheet") If question = vbYes Then Sheets("Results").Range("D6").ClearContents Category = Sheets("Results").Range("D6").Value boolRestart = True Else Sheets("Results").Range("D5").ClearContents Sheets("Results").Range("D6").ClearContents Me.Hide WelcomeForm.Show Exit Sub End If
scheme2 – 用户提供了一个country
和:
-
country
存在于数据库中; - 用户还提供了针对特定国家的数据库中存在的
Category
; - 用户已将
Category
字段留空。
在这种情况下,search将运行。 这是写在脚本如下:
ElseIf Sheets("Database").Cells(i, 1) = country And _ (Sheets("Database").Cells(i, 3) = Category Or Category = "") Then 'Copy the headers of the "Database" sheet With Sheets("Database") .Range("A1:I1").Copy End With Sheets("Results").Range("B10:J10").PasteSpecial 'Copy the rows of the table that match the search query With Sheets("Database") .Range(.Cells(i, 1), .Cells(i, 9)).Copy End With Sheets("Results").Range("B20000").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats End If
我试图以几种不同的方式编写脚本,但search引擎不能按我的意愿工作。 现在发生的事情是,当我input一个我知道在数据库中的国家时,无论是否input一个Category
, OPTION 1总是被触发。 我已经尝试完全删除OPTION 1 ,只运行一个带有OPTION 2的If
语句,并且search运行正常,并填写了Country
和Category
,但是,只要OPTION 1在代码中,无论用户input什么内容,这总是运行的选项。
完整的代码在这里,供您参考:
Dim country As String 'Search query country, user-inputted Dim Category As String 'Search query category user-inputted Dim finalrow As Integer Dim i As Integer 'row counter Dim ws As Worksheet Set ws = Sheets("Database") country = Sheets("Results").Range("D5").Value Category = Sheets("Results").Range("D6").Value finalrow = Sheets("Database").Range("A200000").End(xlUp).Row For i = 2 To finalrow If Sheets("Database").Cells(i, 1) = country And _ (Category <> "" Or Sheets("Database").Cells(i, 3) <> Category) Then Dim question As Integer question = MsgBox("Unfortunately, the Database has no sources regarding " & Category & " in " & country & ". Would you perhaps want to broaden your search and see all sources regarding " & country & "?", vbYesNo + vbQuestion, "Empty Sheet") If question = vbYes Then Sheets("Results").Range("D6").ClearContents Category = Sheets("Results").Range("D6").Value boolRestart = True Else Sheets("Results").Range("D5").ClearContents Sheets("Results").Range("D6").ClearContents Me.Hide WelcomeForm.Show Exit Sub End If ElseIf Sheets("Database").Cells(i, 1) = country And _ (Sheets("Database").Cells(i, 3) = Category Or Category = "") Then 'Copy the headers of the "Database" sheet With Sheets("Database") .Range("A1:I1").Copy End With Sheets("Results").Range("B10:J10").PasteSpecial 'Copy the rows of the table that match the search query With Sheets("Database") .Range(.Cells(i, 1), .Cells(i, 9)).Copy End With Sheets("Results").Range("B20000").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats End If Next I
非常感谢您的帮助。
问题是如果任何一行不符合标准,你的代码将进入选项1,而如果每一行都不符合标准,我们只希望它失败。 因此,我们需要对数据进行两次扫描,首先检查是否有任何传递行(如果不是那么我们提供清除类别),然后再复制相关数据。
尝试这个:
Option Explicit Private Sub CommandButton1_Click() Dim country As String 'Search query country, user-inputted Dim Category As String 'Search query category user-inputted Dim finalrow As Integer Dim i As Integer 'row counter Dim ws As Worksheet Dim foundMatch As Boolean foundMatch = False Set ws = Sheets("Database") country = Sheets("Results").Range("D5").Value Category = Sheets("Results").Range("D6").Value finalrow = Sheets("Database").Range("A200000").End(xlUp).Row For i = 2 To finalrow If Sheets("Database").Cells(i, 1) = country And _ (Sheets("Database").Cells(i, 3) = Category Or Category = "") Then foundMatch = True End If Next i If Not foundMatch Then Dim question As Integer question = MsgBox("Unfortunately, the Database has no sources regarding " & Category & " in " & country & ". Would you perhaps want to broaden your search and see all sources regarding " & country & "?", vbYesNo + vbQuestion, "Empty Sheet") If question = vbYes Then Sheets("Results").Range("D6").ClearContents Category = Sheets("Results").Range("D6").Value Else Sheets("Results").Range("D5").ClearContents Sheets("Results").Range("D6").ClearContents Me.Hide WelcomeForm.Show Exit Sub End If End If For i = 2 To finalrow If Sheets("Database").Cells(i, 1) = country And _ (Sheets("Database").Cells(i, 3) = Category Or Category = "") Then 'Copy the headers of the "Database" sheet With Sheets("Database") .Range("A1:I1").Copy End With Sheets("Results").Range("B10:J10").PasteSpecial 'Copy the rows of the table that match the search query With Sheets("Database") .Range(.Cells(i, 1), .Cells(i, 9)).Copy End With Sheets("Results").Range("B20000").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats End If Next i End Sub
我认为你应该把你的代码分成三个独立的子程序: – 第一个将在用户触发search时运行,然后它必须检查country
是否有一个有效的值(如果没有给出错误消息),然后检查Category
是否有值,如果它有值,则转到第二个子程序,如果它是空的,则转到第三个子程序; – 第二个子程序必须得到country
和Category
variables的值,并返回预期的结果; – 第三个子程序只能得到country
variables并返回预期的结果。
你可以把这两个variables放在模块的开头(在任何Sub
之前,使用Private
而不是Dim
),以使它们可以被该模块中的任何子程序访问,或者你可以创build带有参数的子程序,在这里你可以传递值到另一个Sub
而不使它们该模块中的所有Sub
都可以访问。 我更喜欢第二种select。 如果你不知道如何将parameter passing给另一个模块,那就是一个例子:
Sub QueryCountryAndCategory (QCountry as String, QCategory as String)
在这个Sub
, QCountry
和QCategory
是只能在该模块中访问的variables,它将接收调用者子例程传递的值,如下所示(使用variables):
QueryCountryAndCategory(country, Category)
或者像这样:
QueryCountryAndCategory(QCountry:=country, QCategory:=Category)
请记住,长码难以维护,难以testing。 当你的代码变长的时候,总是考虑把它分成几个Sub
或者Function
(它会返回一个值)。 testing也比较容易,因为你可以单独运行每个Sub来查看它是否正常工作。
On (Category <> "" Or Sheets("Database").Cells(i, 3) <> Category) Then
将OR
replace为AND
该检查必须考虑两者
- 该
category
不是空的AND - 该
category
未find
中频工作的方式是,如果其中任何一个都会触发
-
category
不是空的(所以,如果你在category
input任何东西,它将在这里匹配) - 该
category
不匹配(如果该category
是空的,但它实际上有什么在列表上)