我写了一些VBA代码,循环遍历开放式Excel数据表的行,执行Evaluate(Index(Match))
语句,我在网上找到,在第二个Excel工作簿中搜索2个值(LastName和LabCat)。结果(FirstName)从第二个Excel工作簿返回并存储在本地变量中。我通过以下语句成功返回了我正在寻找的值:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""Cain""&""ABO1"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
但我无法解决的是如何用局部变量替换硬编码值,例如这句话(我用变量strLastName替换字符串“cain”,并用变量替换字符串“ABO1”) strLabCat):
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""strLastName""&""strLabCat"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
此语句将“Error 2042”返回到strFirstName。
你几乎拥有它,但很容易混淆你在字符串中需要的所有“”双“”引号,以便为字符串的值赋予“双引号”。
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""Cain""&""ABO1"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
...但是,您想要从问题中所述的字符串变量中获取值,而不是硬编码Cain
和AB01
,将行更改为:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
备份一下,考虑以下简单的字符串示例分配给变量:
Option Explicit
Sub varTest1()
Dim myGreeting As String
myGreeting = "Hello, My name is Juan and I live in Mexico"
MsgBox myGreeting
End Sub
运行此子例程会弹出一条消息,其中包含来自Juan的问候语。非常基本,但请注意:
As String
部分的情况下工作,但总是指定数据类型是很好的编码实践。Option Explicit
。如果使用,它必须是模块中的第一行,并且每个模块只出现一次。通过在编译期间或代码执行之前生成“pickier”错误,强制您通过生成“pickier”错误来强制您声明所有变量并正确处理对象。为什么你想要更多的错误?现在比[意外]更好,并且强烈建议新编码员和/或进行故障排除。接下来,让我们用另一个变量替换Juan的硬编码名称。
还是很简单,像这样:
Sub varTest2()
Dim myGreeting As String, myName As String
myName = "Juan"
myGreeting = "Hello, My name is " & myName & " and I live in Mexico"
MsgBox myGreeting
End Sub
基本上你只是concatenating a string。加号符号+
用于将字符串或数字加在一起,但同样,最佳做法是坚持使用专门用于字符串的字符串,即&符号&
。
让我们再次添加另一个变量:
Sub varTest3()
Dim myGreeting As String, myName As String, myCountry As String
myName = "Juan"
myCountry = "Mexico"
myGreeting = "Hello, My name is " & myName & " and I live in " & myCountry
MsgBox myGreeting
End Sub
与#2相同的想法;我添加示例#2的原因是为了证明如果变量位于字符串的末尾,则不需要额外的"
引用。
但是,如果我们想在句子结尾处有一段句子,那么该行看起来像:
myGreeting = "Hello, My name is " & myName & " and I live in " & myCountry & "."
请注意,所有上述示例都具有相同的结果。
这是"
双引号可能会有点混乱的地方,因为它们需要围绕您分配给字符串的文本,但我们如何将它们放在字符串中呢?那么有几种方法。
再次备份,我们可以在名称周围添加单引号'
,如下所示:
myGreeting = "Hello, My name is 'Juan' and I live in Mexico."
...而字符串将包含:
您好,我的名字是'Juan',我住在墨西哥。
...但是如果我们想要使用双引号"
在字符串中出于美观的原因(例如这些示例),或者出于强制性原因(如公式中的要求)(我的示例),我们可以执行以下两项操作之一:
"
字符代码34添加ASCII符号.VBA中的函数将是Chr(34)
和工作表函数CHAR(34)
。"
双引号,我们一起使用两个双引号""
(或我称之为四引号。)例如,硬编码:
Sub varTest4()
Dim myGreeting As String
myGreeting = "Hello, My name is ""Juan"" and I live in Mexico."
MsgBox myGreeting
End Sub
这将显示一个弹出消息框,显示:
您好,我的名字是“胡安”,我住在墨西哥
或者,我们可以再次使用带有名称的变量和围绕它的双引号:
Sub varTest5()
Dim myGreeting As String, myName As String
myName = """Juan"""
myGreeting = "Hello, My name is " & myName & " and I live in Mexico"
MsgBox myGreeting
End Sub
...将产生与前一个例子相同的结果(#4)。
或者我们可以添加双引号到myGreeting
而不是通过myName
:\
Sub varTest6()
Dim myGreeting As String, myName As String
myName = "Juan"
myGreeting = "Hello, My name is """ & myName & """ and I live in Mexico"
MsgBox myGreeting
End Sub
......我们将再次获得与上述完全相同的结果。
并且,为了演示如果我们想要名称和国家/地区的双引号会是什么样子(因此在字符串的最末端出现双引号):
Sub varTest7()
Dim myGreeting As String, myName As String, myCountry As String
myName = "Juan"
myCountry = "Mexico"
myGreeting = "Hello, My name is """ & myName & """ and I live in """ & myCountry & """"
MsgBox myGreeting
End Sub
至少有几种方法可以在字符串中添加双引号:
""
“quad-quote”,或者,...因为有时所有这些过多的引用都会让人感到困惑。
例如,要显示三个双引号,如下所示:
"""
我需要使用:
MsgBox """"""""
...这是八个双引号:一个用于开始字符串,一个用于结束字符串,另外三个用于显示每个字符串。 (这会被称为Octo-quote?!)
我们可以显示这个:
"Juan"
有:
MsgBox """Juan"""
...或完全相同的结果(但在我的脑海里有点清洁):
MsgBox Chr(34) & "Juan" & Chr(34)
...因此改变示例#7中的行,这:
myGreeting = "Hello, My name is " & Chr(34) & myName & Chr(34) & _
" and I live in " & Chr(34) & myCountry & Chr(34)
......会产生与例子#7相同的结果:
您好,我的名字是“胡安”,我住在“墨西哥”
最后,还有一个想法来自你的问题的例子,关于清晰与混乱的字符串。您可以使用下划线_
作为“行继续符号”将多行代码分解为多行,使其更易于在VBA编辑器(VBE)中读取,以及其他人读取或复制/在这样的网站上发布代码时粘贴!
例如,我对您的代码行的“更正”是:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
......一条loooong线(他们可以得到much loooonger!)
在我解释引号之前,我不想让我的原始响应更加混乱我添加额外的符号,但是编写冗长行的“更干净”是在下一行的任何地方添加下划线,如下所示:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000, " & _
"MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]" & _
"MySheet'!$B$2:$B$1000'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
您不必在VBE中向右滚动以查看代码,并注意Stack Overflow如何不必添加水平滚动条。
像泥一样清楚? :-)
祝好运! (而且你的问题也是很好的问题。欢迎,顺便说一下!)
有时使用令牌替换方法比尝试进行多串连接更容易。
Ef。:
Dim sht As Worksheet, f, strFirstName
Set sht = Workbooks("MyMatrix.xlsm").Worksheets("MySheet")
f = "INDEX($C$2:$C$1000,MATCH(""{LastName}""&""{LabCat}"",$B$2:$B$1000&$H$2:$H$1000,0))"
f = Replace(f, "{LastName}", "Cain")
f = Replace(f, "{LabCat}", "AB01")
strFirstName = sht.Evaluate(f) '<< note using the Worksheet.Evaluate form here