Mac的最新Excel不再编译 [英] Latest Excel for Mac no longer compiles

查看:60
本文介绍了Mac的最新Excel不再编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在最新的Excel Windows以及Mac的Excel 16.28上均能正常运行.但是在最新的Mac版Excel(16.29和16.30)上,它会在代码行 MyShape.Select 上生成以下错误:编译错误:未找到方法或数据成员".

The following code works fine on latest Excel Windows and also on Excel 16.28 on Mac. But on the latest Excel for Mac (16.29 and 16.30) it generates this error: "Compile error: Method or data member not found" on the code line MyShape.Select.

我假设有一种替代方法可以执行编译器将批准的操作,但是我不知道它会是什么.作为一种替代方法,我尝试不选择形状而是仅引用形状,但是随后在 With MyShape.ShapeRange.Fill 行上遇到了相同的错误.

I assume that there is an alternative way to do what I want that the compiler will approve of, but I don't know what it would be. As an alternative, I tried not selecting the shape and just referring to it, but then I get the same error but on the With MyShape.ShapeRange.Fill line.

  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时,如果允许上述操作,将还原为旧版本,但是假设不是这种情况,有什么解决方法吗?

I'm hoping that a newer version of Mac Excel, when released, will revert to the older version in allowing the above, but assuming that's not the case, any workarounds?

推荐答案

我喜欢你明确地指的是 ActiveSheet ,恭喜!

I like that you're explicitly referring to ActiveSheet, kudos!

问题是 ActiveSheet Object ,这意味着编译器无能为力: ActiveSheet.Shapes 会编译,但是> ActiveSheet.Shapess -即使指定了 Option Explicit .整个表达式在运行时求值.

The problem is that ActiveSheet is an Object, wich means the compiler is helpless: ActiveSheet.Shapes compiles, but so will ActiveSheet.Shapess - even with Option Explicit specified. The entire expression is evaluated at run-time.

首先解决问题:

Dim sheet As Worksheet
Set sheet = ActiveSheet

现在 sheet.Shapes 获得智能感知和编译时验证,以及随后的 .AddShape 成员调用.您甚至可以在输入参数列表时获得参数工具提示!

Now sheet.Shapes gets intellisense and compile-time validation, along with subsequent the .AddShape member call. You even get parameter tooltips as you type up the argument list!

接下来发生的事情很有趣:您将 MyShape 声明为 Shape ,但是它不是您要查看的 Shape -code> Shape 类没有 ShapeRange 属性,因此... MyShape.ShapeRange 从何而来?

What happens next is interesting: you declared MyShape as a Shape, but it's not a Shape you're looking at - the Shape class doesn't have a ShapeRange property, so... where does MyShape.ShapeRange come from then?

如果在 MyShape.Select 调用后中断执行(使用F9设置断点),然后调出立即窗格(Ctrl + G),则答案为出现:

If you break execution (F9 to set a breakpoint) after the MyShape.Select call, and then bring up the immediate pane (Ctrl+G), the answer appears:

?typename(selection)
Rectangle

如果您在单词矩形 ...

If you press Shift+F2 on the word Rectangle...

Dim myRectangle As Excel.Rectangle '<~ here

... VBE似乎无法弄清楚(光标下的标识符未被识别").因此,我们按F2键,然后右键单击某个位置并勾选显示隐藏的成员"选项-可以肯定的是:

...the VBE doesn't seem to figure it out ("identifier under cursor is not recognized"). So we press F2, then right-click somewhere and tick the "Show hidden members" option - and sure enough, there it is:

因此您的代码说让我们使用 Shape 界面",但可以与 Rectangle 对象一起使用.既然可以了,那就意味着 Rectangle 是一个 Shape :这两个接口只是通过不同的镜头描述了相同的对象,所以两者都可以起作用...但是然后 Shape.ShapeRange 看起来不太正确,因为 Shape 类未定义该成员,而这正是我们明确表示要使用的接口.

So your code says "let's use the Shape interface", but works with a Rectangle object. And since that works, it means a Rectangle "is a" Shape: the two interfaces simply describe the same object through different lens, so either works... but then Shape.ShapeRange doesn't look quite right, since the Shape class doesn't define that member and that's the interface we explicitly said we were going to be working with.

如果我们要调用 Rectangle 的成员,则可以-并且由于我们现在在对象浏览器中显示隐藏的成员,因此intellisense也可以显示隐藏的类型和成员.如果整个 With 块是早期绑定的,那么一切就更有意义了:

If we want to invoke the members of Rectangle, we can - and since we're now showing hidden members in the object browser, intellisense displays the hidden types and members too. If the entire With block is early-bound, everything makes much more sense:

With myRectangle.ShapeRange.Fill

...并说明 ActiveSheet 上的后期绑定代码如何在运行时工作以解决成员调用,现在编译器需要一种完全其他的策略来编译VBA代码:也许可以使事情彻底动摇,使其正常工作,也许不会.至少类型歧义和编译器忽略的语句都消失了:)

...and explains how the late-bound code off ActiveSheet would work at run-time to resolve the member call, and now the compiler needs a completely other strategy to compile the VBA code: maybe that could shake things up enough to get it to work, maybe it won't. At least the type ambiguities and ignored-by-compiler statements are all gone :)

令人惊讶的是,您不能使用VBA用户代码来做到这一点.如果使用 DoSomething 方法创建了 MyShape 类:

The thing that's surprising here, is that you can't do that with VBA user code. If you made a MyShape class with a DoSomething method:

'@ModuleDescription "A metaphorical Shape"
Option Explicit

Public Sub DoSomething()
    MsgBox TypeName(Me)
End Sub

然后是实现 MyShape MyRectangle 类,并在其自己的公共接口上公开成员,从而产生 MyShape 对象引用:

And then a MyRectangle class that implements MyShape and exposes a member on its own public interface, that yields a MyShape object reference:

'@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

现在在任何标准模块中,我们都可以对其进行测试-首先,在所有早期绑定中,我们将拥有一个工厂方法,该方法返回 MyShape ,以模仿 Shapes.CreateShape:

And now in any standard module, we can test this - first, all early-bound, and we'll have a factory method that returns a MyShape, to 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上运行此代码,并且我希望代码无法编译:

So we run this (on Windows), and I expected, the code doesn't compile:

但是后期绑定...

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

...行得通吗?不:

...works? Nope:

我们不是在查看 MyRectangle 对象吗?否:我们正在研究VBA中后期绑定多态性的限制-我们创建了 New MyRectangle ,但对于编译器 CreateRect 返回 MyShape 对象引用.如果我们在 End Function 上放置一个断点,运行它,然后在击中该断点时在立即窗格(Ctrl + G)中键入?TypeName(CreateRect)尽管声明的类型 MyShape ,但运行时类型显然是 MyRectangle .

Are we not looking at a MyRectangle object? No: we're looking at the limits of late-binding polymorphism in VBA - we created a New MyRectangle, but to the compiler CreateRect returns a MyShape object reference. If we place a breakpoint on End Function, run it, and then type ?TypeName(CreateRect) in the immediate pane (Ctrl+G) when the breakpoint is hit, then despite the declared type being MyShape, the runtime type is clearly MyRectangle.

应该有效-但事实并非如此.错误438,找不到成员:与未找到方法或数据成员"的后期绑定/运行时等效的编译错误.

And it should work - but it doesn't. Error 438, member not found: the late-bound/run-time equivalent of the "method or data member not found" compile error.

如果我们使用该界面,那真的意味着可以使用...

And if we use the interface we really mean to work with...

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

...然后一切正常":

...then everything "just works":

现在,我没有在Mac上运行它,但是这段代码可以为我编译...

Now, I'm not running this on a Mac, but this code compiles for me...

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 not Shape (!!?!??).证明,如果我们使 CreateRect 返回一个 Excel.Rectangle ,则现在我们在尝试分配该函数的返回值时就得到了类型不匹配错误,并且不再有意义.:发生了一件奇怪的事情,而且,我没主意-尽管 TypeName(选择)声明类型为(毕竟出于某种原因该类是隐藏/未记录的!),这...几乎摧毁了所有希望,尤其是如果 With Selection.Fill 使用MyShape.Fill 可以正常工作(尽管在我的Windows机器上确实可以正常工作).

...and systematically raises run-time error 13 as soon as CreateRect returns and the Shape reference gets assigned to a Rectangle - error 13 being "type mismatch". In other words, a Rectangle is not a Shape (!!?!??). Proof, if we make CreateRect return a Excel.Rectangle, we now get the type mismatch error as soon as we try to assign the function's return value, and nothing makes sense anymore: there's something weird going on, and, well, I'm out of ideas - there doesn't appear to be any way to work early-bound with a Rectangle, despite what TypeName(Selection) claims the type is (the class is hidden/undocumented for a reason after all!), which... pretty much destroys all hope, especially if neither With Selection.Fill nor With MyShape.Fill work (it does work perfectly fine here on my Windows box though).

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

Sending a frown with some repro code through the user feedback feature should get you heard from the product team at Microsoft. I doubt they removed anything from anywhere - but it's not impossible something broke how interfaces are resolved, somewhere deep down in some seemingly unrelated piece of internal API :)

这篇关于Mac的最新Excel不再编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆