Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
625 views
in Technique[技术] by (71.8m points)

excel - Missing VBA compiler message for wrong method name

Consider the following code:

Public Sub VBACompilerIsMad()

    Dim Ap As Application     
    Dim Wb As Workbook
    Dim Ws As Worksheet

    Debug.Print Ap.XXX ' No compile error
    Debug.Print Wb.XXX ' No compile error
    Debug.Print Ws.XXX ' Compile error

End Sub

When I compile this, I get a compiler error for referring to an inexisting member of Worksheet. However, if I comment out the last line, there is no compiler error, even though neither Application nor Workbook have a method or property XXX. It is as if I declared Ap and Wb as Object variables.

Why does the compiler treat Application / Workbook differently from Worksheet?

Are there any other classes like this, that the compiler seems to treat as if they were Object?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As I have been explained (kudos go respectively), this is a COM feature.

By default COM assumes an interface is extensible, that is, it allows adding members at run time. If that is not the desired behaviour, one can apply the [nonextensible] attribute to the interface definition, which declares the interface only accepts methods explicitly defined in the type library.

dispinterface _Application and dispinterface _Workbook do not have this flag set in the Excel type library, dispinterface _Worksheet does.

Similarly, ADO's dispinterface _Connection does not have [nonextensible], dispinterface _Command does.

To learn which are extensible, add a reference to TypeLib Info in the project's References and run:

Dim t As tli.TLIApplication
Set t = New tli.TLIApplication

Dim ti As tli.TypeLibInfo
Set ti = t.TypeLibInfoFromFile("excel.exe")

Dim i As tli.InterfaceInfo
For Each i In ti.Interfaces
    If (i.AttributeMask And tli.TYPEFLAG_FNONEXTENSIBLE) <> tli.TYPEFLAG_FNONEXTENSIBLE Then
      Debug.Print i.Name
  End If
Next

You will see that almost all interfaces are extensible here, so most of them get pushed out of the debug window and you will only see the last ones. Change the <> to = to print those that are not extensible, there are much less of them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...