方括号表达式在 M365 和 Excel 2016 中的计算方式不同
Square bracketed expression is evaluated differently in M365 vs Excel 2016
我工作的公司最近从 Office 2016 迁移到 M365。我们的一些启用宏的电子表格使用方括号表达式作为 Application.Evaluate 方法的快捷方式。例如:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim msg As String
On Error GoTo ErrHandler:
If Target.Columns.Count > 100 Then
Dim row As Range
For Each row In Target.Rows
RemoveRowBorders row:=row.row, firstColumn:=[colSourceDevice], lastColumn:=[colItemNumber]
Next
UpdateItemNumbers startingRow:=[rowStart], maxRange:=[maxRange]
GoTo My_Exit
End If
If Target.Column >= [colSourceDevice] And Target.Column <= [colItemNumber] Then
SetCalculations cellRange:=Target
End If
My_Exit:
Exit Sub
ErrHandler:
msg = "An error occurred on cell auto-update: " & vbNewLine & Err.Description
MsgBox msg
Resume My_Exit
End Sub
“colSourceDevice”是一个名为 range/object 的公式,它指的是 return 列号的公式,括号中的表达式是调用 Application.Evaluate 方法的快捷方式。 “colSourceDevice”中引用的公式为:
=VALUE(COLUMN('HS - Main'!$A))
在 Excel 2016 中,括号表达式 return 是列号 (Variant/Double).
在 M365 Excel 中,括号中的表达式 return 是一个数组 (Variant/Variant),其中包含一项 (Variant/Double)。
在 M365 Excel 中,这会导致类型不匹配错误。
我可以使用对象模型方法代替括号表达式并获得预期结果:
Application.Evaluate("colSourceDevice")(1) 'returns column number (Variant/Double)
为什么方括号表达式 return M365 与 Excel 2016 中的数据类型不同?
编辑:
正如 chris neilsen 所暗示的,Excel 计算引擎在 2018 年发生了重大变化。
看这里:
Excel: Microsoft unveils Dynamic upgrades
实现方括号表达式遗留行为的另一种方法是将新的隐式交集运算符 (@) 添加到方括号内的命名范围:
If Target.Column >= [@colSourceDevice] And Target.Column <= [@colItemNumber] Then
SetCalculations cellRange:=Target
End If
...如此处所述:
Microsoft makes major Dynamic Arrays modifications
我怀疑这个问题与 32/64 位无关,而是从 Excel 2016 到 355 的变化。这引入了动态范围,这是公式工作方式的根本变化。
由于您没有在您的命名范围内提供公式,我将根据一个示例公式来回答这个问题,该公式可能反映也可能不反映您的公式。
colSourceDevice Refers to = =COLUMN()
这表现出您描述的行为
它实际做的是return创建一个包含 1 个元素的动态数组。
为了 return 该值作为变体,通过将其包装在 INDEX
中修改命名范围
colSourceDevice2 Refers to = =INDEX(COLUMN(),1,1)
结果如你所愿
免责声明:
综上所述,这是对某些设计不当的代码的创可贴修复。我的建议:重构您的代码以消除这种和其他不良做法。
我工作的公司最近从 Office 2016 迁移到 M365。我们的一些启用宏的电子表格使用方括号表达式作为 Application.Evaluate 方法的快捷方式。例如:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim msg As String
On Error GoTo ErrHandler:
If Target.Columns.Count > 100 Then
Dim row As Range
For Each row In Target.Rows
RemoveRowBorders row:=row.row, firstColumn:=[colSourceDevice], lastColumn:=[colItemNumber]
Next
UpdateItemNumbers startingRow:=[rowStart], maxRange:=[maxRange]
GoTo My_Exit
End If
If Target.Column >= [colSourceDevice] And Target.Column <= [colItemNumber] Then
SetCalculations cellRange:=Target
End If
My_Exit:
Exit Sub
ErrHandler:
msg = "An error occurred on cell auto-update: " & vbNewLine & Err.Description
MsgBox msg
Resume My_Exit
End Sub
“colSourceDevice”是一个名为 range/object 的公式,它指的是 return 列号的公式,括号中的表达式是调用 Application.Evaluate 方法的快捷方式。 “colSourceDevice”中引用的公式为:
=VALUE(COLUMN('HS - Main'!$A))
在 Excel 2016 中,括号表达式 return 是列号 (Variant/Double).
在 M365 Excel 中,括号中的表达式 return 是一个数组 (Variant/Variant),其中包含一项 (Variant/Double)。
在 M365 Excel 中,这会导致类型不匹配错误。
我可以使用对象模型方法代替括号表达式并获得预期结果:
Application.Evaluate("colSourceDevice")(1) 'returns column number (Variant/Double)
为什么方括号表达式 return M365 与 Excel 2016 中的数据类型不同?
编辑:
正如 chris neilsen 所暗示的,Excel 计算引擎在 2018 年发生了重大变化。
看这里: Excel: Microsoft unveils Dynamic upgrades
实现方括号表达式遗留行为的另一种方法是将新的隐式交集运算符 (@) 添加到方括号内的命名范围:
If Target.Column >= [@colSourceDevice] And Target.Column <= [@colItemNumber] Then
SetCalculations cellRange:=Target
End If
...如此处所述: Microsoft makes major Dynamic Arrays modifications
我怀疑这个问题与 32/64 位无关,而是从 Excel 2016 到 355 的变化。这引入了动态范围,这是公式工作方式的根本变化。
由于您没有在您的命名范围内提供公式,我将根据一个示例公式来回答这个问题,该公式可能反映也可能不反映您的公式。
colSourceDevice Refers to = =COLUMN()
这表现出您描述的行为
它实际做的是return创建一个包含 1 个元素的动态数组。
为了 return 该值作为变体,通过将其包装在 INDEX
colSourceDevice2 Refers to = =INDEX(COLUMN(),1,1)
结果如你所愿
免责声明:
综上所述,这是对某些设计不当的代码的创可贴修复。我的建议:重构您的代码以消除这种和其他不良做法。