excel - Mac的最新Excel不再编译

标签 excel vba macos compiler-errors

以下代码在最新的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!

问题在于ActiveSheetObject,这意味着编译器无能为力: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.FillWith MyShape.Fill都不起作用(尽管在我的Windows机器上,它的确工作正常)。

通过用户反馈功能发送带有一些repro代码的皱眉应该会让您从Microsoft产品团队那里听到。我怀疑他们从任何地方都删除了任何东西-但是在某些看似无关的内部API的深处某个地方,有什么问题打破了接口(interface)的解析方式并非不可能:)

关于excel - Mac的最新Excel不再编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58124950/

相关文章:

macos - 更新到 OSX High Sierra 后出现 curl "no start line"LibreSSL 错误

macos - 在 Mac OS X 终端中确定目录是包还是包?

cocoa - 如何使用 Cocoa 将文本从一个应用程序粘贴到另一个应用程序?

c# - 使用 Microsoft.Office.Interop.Excel 读取所有行和列

vba - 用户窗体关闭事件

excel - VBA循环遍历电子邮件附件并根据给定条件保存

vba - 在 Excel VBA 中命名数组维度

c# - 从 Excel 工作表中读取日期时间值

excel - 如何使用excel 365在一张图表中显示两条回归趋势线

vba - 如何在VBA中动态引用对象属性