ActiveSheet.Name = "Amazon " + ActiveSheet.Range("B27")
ActiveSheet.Name 是 String。 "Amazon" 文字也是如此。我假设ActiveSheet 上的单元格$B$27 包含一个数值; + 运算符是 addition 运算符,VBA 抛出 type mismatch 因为它不知道如何 add 带有编号,因为您可以在 立即窗格 (Ctrl+G) 中轻松重现:
?"foo" + 42
'type mismatch
将+ 运算符替换为字符串连接 运算符& 修复了症状,并且“有效”:
?"foo" & 42
'foo42
但是您需要考虑真正发生了什么,并解决问题,而不仅仅是症状:当您使用string concatenation 运算符,VBA 将所有操作数隐式转换为字符串。您可以使用 CStr 函数明确转换:
?"foo" & CStr(42)
'foo42, this time without implicit conversions
但ActiveSheet.Range("B27") 是一个对象 - 一个Range 对象引用:
?TypeName(ActiveSheet.Range("B27"))
Range
这里还有另一个隐式操作:它不是您要转换为字符串(隐式或显式)的对象引用,而是其默认成员的值。如果您在对象浏览器 (F2) 中查看Range 对象,您会注意到它有一个隐藏的_Default 属性:
该默认属性显然是以获取/设置Range.Value的方式实现的;这就是这段代码编译的原因:
ActiveSheet.Range("B27") = 42
这段代码也是如此:
Dim foo As Long
foo = ActiveSheet.Range("B27")
如果没有 默认成员 隐式“重定向”对 Value 的调用,这些将是非法的,因为您无法在不使用 Set 关键字的情况下分配对象引用,并且您也不能将对象引用分配给值。
请注意此处Range("B27") 之间的区别:
If Not Intersect(Target, Range("B27")) Is Nothing Then
对比这里:
ActiveSheet.Name = "Amazon " + ActiveSheet.Range("B27")
前者是Range对象,后者是它的Value。另请注意,Range("B27") 隐含地引用了ActiveSheet,因此:
Range("B27")
和这个完全一样:
ActiveSheet.Range("B27")
没有理由不明确地用ActiveSheet 来限定它。事实上,只要查看vba 标记中的任意 100 个 Stack Overflow 问题,使用 Worksheet 对象限定所有 Range 调用,将会为您节省很多问题。
因此,编写处理程序的 显式 方式如下 - 请注意,有效的工作表名称必须为 32 个字符或更少,因此如果连接的字符串长于那。而且由于两个工作表不能具有相同的名称,如果截断的字符串导致工作簿中已经存在工作表名称,则需要执行 something:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.Range("B27")) Is Nothing Then
On Error Resume Next
ActiveSheet.Name = Left$("Amazon " & CStr(ActiveSheet.Range("B27").Value), 32)
On Error GoTo 0
If Err.Number <> 0 Then MsgBox "Could not rename worksheet '" & ActiveSheet.Name & "'."
End If
End Sub
此时无论您使用& 还是+ 运算符都无关紧要,因为+ 运算符非常适合连接字符串...当所有操作数都是 em> 字符串 - 除了一致性和可读性,您肯定希望在连接字符串时更喜欢使用 & 运算符。