以下代码在最新的Excel Windows以及Mac的Excel 16.28上均能正常运行。但是在最新的Mac版Excel(16.29和16.30)上,它会在代码行MyShape.Select
上生成以下错误:“编译错误:未找到方法或数据成员”。
我假设有另一种方法可以执行编译器将批准的操作,但是我不知道它会是什么。作为一种替代方法,我尝试不选择形状而是仅引用它,但是随后在With MyShape.ShapeRange.Fill
行上出现了相同的错误。
Dim MyShape As Shape
'Other stuff
Set MyShape = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 400, 400, DistanceBetweenCells, LineWidth)
MyShape.Select
With Selection.ShapeRange.Fill
'stuff here
End With
我希望发行新版本的Mac Excel时,如果允许上述操作,将还原为旧版本,但是如果不是这种情况,有什么解决方法吗?
最佳答案
我喜欢您明确指的是ActiveSheet
!
问题在于ActiveSheet
是Object
,这意味着编译器无能为力:ActiveSheet.Shapes
可以编译,但是ActiveSheet.Shapess
也会编译-即使指定了Option Explicit
。整个表达式在运行时求值。
让我们先解决这个问题:
Dim sheet As Worksheet
Set sheet = ActiveSheet
现在,
sheet.Shapes
获得智能感知和编译时验证,以及后续的.AddShape
成员调用。您甚至可以在输入参数列表时获得参数工具提示!接下来发生的事情很有趣:您将
MyShape
声明为Shape
,但并不是要查看的Shape
-Shape
类没有ShapeRange
属性,所以... MyShape.ShapeRange
从何而来?如果在
MyShape.Select
调用后中断执行(使用F9设置断点),然后调出立即 Pane (Ctrl + G),则会出现以下答案:?typename(selection)
Rectangle
如果您在
Rectangle
单词上按Shift + F2键...Dim myRectangle As Excel.Rectangle '<~ here
... VBE似乎无法弄清楚(“光标下的标识符无法识别”)。因此,我们按F2键,然后右键单击某个位置并勾选“显示隐藏的成员”选项-可以肯定的是:
因此,您的代码说“让我们使用
Shape
接口(interface)”,但可以使用Rectangle
对象。既然这样行得通,那就意味着Rectangle
是一个Shape
:这两个接口(interface)只是通过不同的镜头描述了相同的对象,所以两者都可以起作用...但是Shape.ShapeRange
看起来不太正确,因为Shape
类没有定义该成员,这就是我们明确表示要使用的接口(interface)。如果我们想调用
Rectangle
的成员,则可以-并且由于我们现在在对象浏览器中显示隐藏的成员,因此intellisense也显示隐藏的类型和成员。如果整个With
块是早期绑定(bind)的,那么一切就更有意义了:With myRectangle.ShapeRange.Fill
...并解释了
ActiveSheet
的后期绑定(bind)代码如何在运行时工作以解决成员调用,现在编译器需要一种完全不同的策略来编译VBA代码:也许可以将其彻底震动以获取它工作,也许不会。至少类型的歧义和编译器忽略的语句都消失了:)这里令人惊讶的是,您无法使用VBA用户代码来做到这一点。如果使用
MyShape
方法制作了DoSomething
类:'@ModuleDescription "A metaphorical Shape"
Option Explicit
Public Sub DoSomething()
MsgBox TypeName(Me)
End Sub
然后是一个
MyRectangle
类,该类实现MyShape
并在其自己的公共(public)接口(interface)上公开一个成员,从而产生MyShape
对象引用:'@ModuleDescription "A metaphorical Rectangle"
Option Explicit
Private sh As MyShape
Implements MyShape
Public Property Get Thing() As Object
Set Thing = sh
End Property
Private Sub Class_Initialize()
Set sh = New MyShape
End Sub
Private Sub MyShape_DoSomething()
MsgBox TypeName(Me)
End Sub
现在,在任何标准模块中,我们都可以进行测试-首先,在所有早期绑定(bind)中进行测试,并且我们将拥有一个工厂方法,该方法返回
MyShape
到mimick Shapes.CreateShape
:Public Sub WorksMaybe()
Dim r As MyShape
Set r = CreateRect
r.Thing.DoSomething
End Sub
Private Function CreateRect() As MyShape
Set CreateRect = New MyRectangle
End Function
因此,我们在Windows上运行了此代码,我希望代码不会编译:
但是,后期绑定(bind)...
Public Sub WorksMaybe()
Dim r As Object
Set r = CreateRect
r.Thing.DoSomething
End Sub
Private Function CreateRect() As MyShape
Set CreateRect = New MyRectangle
End Function
...作品?不:
我们不是在看
MyRectangle
对象吗?否:我们正在研究VBA中后期绑定(bind)多态性的局限性-我们创建了New MyRectangle
,但向编译器CreateRect
返回了MyShape
对象引用。如果将断点放置在End Function
上,运行它,然后在击中断点时在即时 Pane (Ctrl + G)中键入?TypeName(CreateRect)
,则尽管声明的类型为MyShape
,但运行时类型显然是MyRectangle
。而且应该可以工作-但事实并非如此。错误438,找不到成员:“未找到方法或数据成员”的后期绑定(bind)/运行时等效的编译错误。
如果我们使用该界面,那真的意味着可以使用...
Public Sub WorksMaybe()
Dim r As MyRectangle
Set r = CreateRect
r.Thing.DoSomething
End Sub
Private Function CreateRect() As MyShape
Set CreateRect = New MyRectangle
End Function
...然后一切“正常”:
现在,我没有在Mac上运行它,但是这段代码为我编译了...
Option Explicit
Const DistanceBetweenCells As Long = 50
Const LineWidth As Long = 2
Public Sub WorksMaybe()
Dim r As Excel.Rectangle
Set r = CreateRect
r.ShapeRange.Fill.BackColor.RGB = vbRed
End Sub
Private Function CreateRect() As Excel.Shape
Set CreateRect = Shapes.AddShape(msoShapeRectangle, 40, 40, DistanceBetweenCells, LineWidth)
End Function
...并在
CreateRect
返回并且Shape
引用被分配给Rectangle
后系统地引发运行时错误13-错误13为“类型不匹配”。换句话说,Rectangle
不是Shape
(!!?!??)。证明,如果我们使CreateRect
返回Excel.Rectangle
,那么我们现在立即在尝试分配函数的返回值时得到类型不匹配错误,并且不再有意义:发生了一些奇怪的事情,而且,我已经离开了想法-尽管Rectangle
声称类型是什么(毕竟出于某种原因,该类是隐藏的/未记录的),但似乎没有任何方法可以早期绑定(bind)TypeName(Selection)
。这...几乎摧毁了所有希望,尤其是如果With Selection.Fill
和With MyShape.Fill
都不起作用(尽管在我的Windows机器上,它的确工作正常)。通过用户反馈功能发送带有一些repro代码的皱眉应该会让您从Microsoft产品团队那里听到。我怀疑他们从任何地方都删除了任何东西-但是在某些看似无关的内部API的深处某个地方,有什么问题打破了接口(interface)的解析方式并非不可能:)
关于excel - Mac的最新Excel不再编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58124950/