Latest Excel for Mac no longer compiles - excel

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.
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
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?

I like that you're explicitly referring to ActiveSheet, kudos!
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.
Let's fix that first:
Dim sheet As Worksheet
Set sheet = ActiveSheet
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!
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?
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
...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:
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.
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
...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 :)
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
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
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
So we run this (on Windows), and I expected, the code doesn't compile:
Late binding however...
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:
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.
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":
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
...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).
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 :)

Ok, I think it is figured out. In Mac Excel version 16.29 Microsoft has deleted certain class members for, at least, Shapes. For instance "Fill" and "Select" are no longer available. So any code that refers to them will generate an error.
I'm not sure how extensive this is or any other ramifications, but I do know that the code works fine in version 16.28, and also that the member list in 16.28 shows both "fill" and "select" but not in 16.29. Thanks to Mathieu Guindon above for the input and also to a poster who deleted his thread - both of these people really helped. I've reported the issue to Microsoft.

Answer from Steve Rindsberg (MVP):
Iterate through the .ShapeRange collection:
For x = 1 To .ShapeRange.Count
With .ShapeRange(x)
'...stuff....
End With
Next
I've had a few similar weird ones on Mac where perfectly good code (on
Windows) errors or sometimes make the Mac app go POOF! And disappear.
Iterating the collections this way has been the fix.

Related

How do I Late Bind a Class Module from my Project?

I have two class modules in my project, "ClassAlfa" and "ClassBeta". I have separated the code between the two classes so that if an end-user does not have ClassBeta included in their project, then any of ClassAlfa's late bound references to it gracefully fail. Where I'm having trouble is making the script work if the end-user DOES have ClassBeta available.
Within ClassAlfa, I have the following code:
Option Explicit
Public myClass as Object
Private Sub Class_Initialize()
On Error Resume Next
Set myClass = Application.Run("ClassBeta")
If Err = 0 Then 'End user has this class available, go ahead and use it.
'Do code with ClassBeta
Else
'Do code without ClassBeta
End If
On Error GoTo 0
End Sub
This throws the following error on the Set line:
Run-time error '1004':
Cannot run the macro 'ClassBeta'. The macro may not be available in this workbook or all macros may be disabled.
I have also tried replacing the Set line with this:
Set myClass = CreateObject("ClassBeta")
which instead throws the error
Run-time error '429':
ActiveX component can't create object
Also does not work:
Set myClass = CreateObject("'" & ThisWorkbook.Name & "'!" & "ClassBeta")
What is the proper way to late bind a custom class from my own project?
There is no mechanism in VBA that would allow you to check if a class exists by it's name and to create a new instance if it is.
However, it is possible to achieve. Let's dissect the problems and see how we can work around them.
Problem 1
You need to create an instance of a class that you are not sure it exists in the current project. How?
As you already tried, Application.Run and CreateObject do not work.
Application.Run is only capable of running methods in standard .bas modules (not class modules). It does not create instances of classes.
CreateObject does a few things behind the scenes. First, it calls CLSIDFromProgIDEx using the ProgID (the string) you are passing. Then, it calls CoCreateInstance. The problem is that VBA classes do not have their ProgIDs in the registry so CreateObject simply doesn't work. You would need to have your class in a registered .dll file of ActiveX.exe to make this work.
That leaves us with the New keyword to instantiate a new ClassBeta. That obviously works when the class is present but gives a 'User-defined type not defined' compiler error when it's not. There are only 2 ways to supress this compiler error:
Have a compiler directive
Not have the New ClassBeta at all
A compiler directive would look like this in ClassAlfa:
Option Explicit
#Const BETA_EXISTS = False
Sub Test()
Dim myBeta As Object
#If BETA_EXISTS Then
Set myBeta = New ClassAlpha
#End If
Debug.Print "Type of 'myBeta' is: " & TypeName(myBeta)
End Sub
This compiles fine without having the ClassBeta in the project but you could never make the BETA_EXISTS conditional compiler constant to turn True because:
Only conditional compiler constants and literals can be used in expression
So, the last option is not to have the New ClassBeta anywhere in the project. Except, we do. We can put it in the ClassBeta itself as a factory:
Option Explicit
Public Function Factory() As ClassBeta
Set Factory = New ClassBeta
End Function
When the class is missing, the factory is missing and the New ClassBeta will not throw a compiler error.
Problem 2
How do we call the .Factory method on the ClassBeta?
Well, we obviously cannot create a new instance of ClassBeta because that is our first problem.
What we can do is to make sure that ClassBeta always has a default global instance (like userforms have). To do that we need to export the class to a .cls text file and edit it with a text editor (like Notepad). The text should look like this:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "ClassBeta"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Public Function Factory() As ClassBeta
Set Factory = New ClassBeta
End Function
Notice that I've changed the VB_PredeclaredId attribute to True (manually, in the text editor). Now we can import the class back. We can check if it worked by typing ?Typename(ClassBeta.Factory) in the Immediate window and then pressing Enter. We should see:
The code in ClassAlfa can now be written as:
Option Explicit
Sub Test()
Dim myBeta As Object
On Error Resume Next
Set myBeta = ClassBeta.Factory
On Error GoTo 0
Debug.Print "Type of 'myBeta' is: " & TypeName(myBeta)
End Sub
Problem 3
If we remove ClassBeta from the project, the following line does not compile:
Set myBeta = ClassBeta.Factory
But, compared to problem 1, this time the compiler error is 'Variable not defined'.
The only way that I could think of, to get rid of this new compiler error, is to turn off Option Explicit. Yeah! That bad!
ClassAlfa:
'Option Explicit 'needs to be off to be able to compile without the ClassBeta class
Sub Test()
Dim myBeta As Object
On Error Resume Next
Set myBeta = ClassBeta.Factory
On Error GoTo 0
Debug.Print "Type of 'myBeta' is: " & TypeName(myBeta)
End Sub
Final Thoughts
You could do the development while Option Explicit is on and turn it off for your users.
If your users will use the ClassAlfa with Option Explicit off, the the code should work fine. But if they want ClassBeta as well, then the only way they could get it would be via importing the .cls file. Copy-pasting code won't work because they would lose the global instance of ClassBeta (the one we set in the VB_PredeclaredId hidden attribute).
I must say that I do not recommend removing Option Explicit because that could lead to other issues. I do not think there is a way to achieve what you want in a 'clean' way.

EXCEL VBA Type mismatch with "Next" highlighted

I'm creating small project in Excel, and because I'm a VBA newbie I do encounter a lot of problems that I'm trying to resolve on my own. However i can't cope with this:
I created Sub that accepts two objects: FormName and ControlName.
What i want it to do, is to loop through every Control in specific UserForm and populate every ListBox it encounters, from another ListBox.
I created this funny string comparison, because I need to operate on objects in order to execute the line with AddItem. This comparison actually works well, no matter how ridiculous it is. However when I launch the program, I got
Type Mismatch error
and to my surprise "Next" is being highlighted. I have no idea how to fix this, nor what is wrong.
Public Sub deploy(ByRef FormName As Object, ByRef ControlName As Object)
Dim i As Integer
Dim O As msforms.ListBox
i = 0
For Each O In FormName.Controls
If Left(FormName.Name & O.Name, 16) = Left(FormName.Name & ControlName.Name, 16) Then
O.AddItem (FormName.PodglÄ…d.List(i))
i = i + 1
End If
Next
End Sub
I call this sub using:
Call deploy(UserForm1, UserForm1.ListBox3)
Above, I use Listbox3 because otherwise i got error saying that variable is not defined. However in my comparison I kinda override this.
If someone can explain in simple words, how to fix this type mismatch issue or how to write it in more elegant way

VBA UserForm gives run-time error 91 for one of its parameters

I am trying to create multiple instances of the same modeless UserForm in excel-VBA, with parameters, through a Sub.
I can make it work with two of the three parameters I want to assign, but the third one keeps returning me
"Run-time Error '91': Object variable or With block variable not set"
and I can't figure out why.
It may be an obvious typo that I didn't see, but I really can't point out the problem.
Here is my code:
Sub AskToClose(targetWksht As Worksheet, targetRow As Integer, test As String)
Dim newInstanceOfMe As Object
Set newInstanceOfMe = UserForms.Add("MOVE_TO_CLOSED") 'MOVE_TO_CLOSED is the name of my UserForm
newInstanceOfMe.targetWksht = targetWksht 'If I comment this line it works just fine, otherwise Run-time error 91
newInstanceOfMe.targetRow = targetRow
newInstanceOfMe.test = test
newInstanceOfMe.Show vbModeless
End Sub
_____________________________________________________________________
Sub test()
Dim openWksht As Worksheet
Set openWksht = Worksheets("OPEN WO") 'The worksheet exists and works just fine everywhere else
Call AskToClose(openWksht, 2, "test 2")
Call AskToClose(openWksht, 3, "test 3")
Call AskToClose(openWksht, 4, "test 4")
Set openWksht = Nothing 'I tried to comment this line just in case, same result...
End Sub
_____________________________________________________________________
'My MOVE_TO_CLOSED UserForm parameters
Public targetWksht As Worksheet
Public targetRow As Integer
Public test As String
newInstanceOfMe.targetWksht = targetWksht
This statement produces an error-level code quality inspection result for Value Required inspection in Rubberduck (an open-source VBIDE add-in project I manage). The inspection explains the situation as follows:
Object used where a value is required
The VBA compiler does not raise an error if an object is used in a place that requires a value type and the object's declared type does not have a suitable default member. Under almost all circumstances, this leads to a run-time error 91 'Object or With block variable not set' or 438 'Object doesn't support this property or method' depending on whether the object has the value 'Nothing' or not, which is harder to detect and indicates a bug.
There are two types of assignments in VBA: value assignment (Let), and reference assignment (Set). The Let keyword is redundant/optional/obsolete for value assignments:
Dim foo As Long
foo = 2 + 2
Let foo = 2 + 2 '<~ exactly equivalent to the above
So unless the Set keyword is present, VBA attempts to make a value assignment. If the object has a default member, that might just work - the VBA specs define how let-coercion mechanisms make that happen. That's how you can assign a Range to a value:
Sheet1.Range("A1") = 42
That's implicitly assigning to Range.Value, via an implicit member call to Range.[_Default], a hidden property of the Range class.
If the right-hand side of the assignment was also an object, then let-coercion would be happening on both sides of the operator:
Sheet1.Range("A1") = Sheet1.Range("B1") '<~ implicit default member calls galore!
Sheet1.Range("A1").Value = Sheet1.Range("B1").Value
But we're not looking at a Range here, we're looking at a UserForm, and a UserForm does not have a default member, so let-coercion can't happen... but the compiler won't validate that, so the code gets to run anyway... and blows up at run-time instead.
So, we're looking at a Let assignment with both sides holding an object reference, for a class type that doesn't define a default member.
Something.SomeObject = someOtherObject
But VBA doesn't care that there's no default member - because there's no Set keyword, it tries as hard as it can to do what you told it to do, and coerce these objects into values... and fails, obviously.
If Something.SomeObject (left-hand side) is Nothing, then the let-coercion attempt will try to invoke the inexistent default member -- but since the object reference is Nothing, the call is invalid, and error 91 is raised.
If Something.SomeObject is already holding a valid object reference, then the let-coercion attempt will go one step further, and fail with error 438 because there's no default member to invoke.
If Something.SomeObject has a default member (and the reference isn't Nothing), then the value assignment succeeds, no error is raised... but no object reference was assigned, and this might be a subtle bug!
Adding a Set keyword makes the assignment a reference assignment, and now everything works fine.

Calling a VBA form from a button causes UserForm_Initialize to run twice, breaking my code?

Hello wonderful VBA community,
I'm still really new to vba and am trying to learn a lot. Thank you in advance for looking through my code and my description of the issue I'm facing.
I have a button on a page that calls a new Userform.
CODE SNIPPET 1:
Sub btnShowDetails_Click()
Call frmShowDeets.ShowDeets
End Sub
... which calls the next bit of code in the 'frmShowDeets' UserForm:
CODE SNIPPET 2:
Public Sub ShowDeets()
Dim frm As frmShowDeets
Set frm = New frmShowDeets 'this line triggers the Userform_Initialize() event below
frm.Show
End Sub
... triggering:
CODE SNIPPET 3:
Private Sub UserForm_Initialize()
Dim comboBoxItem As Range
For Each comboBoxItem In ContactList.Range("tblContactList[CompanyName]")
'^refers to unique values in a named range
With Me.boxCompanySelection
.AddItem comboBoxItem.Value
End With
Next comboBoxItem
End Sub
So at this point, the form I want to display has values loaded in its one combobox for user selection. The user selects a company and the Combobox_Change event triggers other routines that pull information for that company.
CODE SNIPPET 4:
Public Sub boxCompanySelection_Change()
Call frmShowDeets.PullData
End Sub
Sub PullData()
Dim numCompanies As Long
numCompanies = ContactList.Range("B6").Value 'this holds a count of the rows in the named range
Dim FoundCell As Range
Set FoundCell = ContactList.Range("tblContactList[Company Name]").Find(What:=boxCompanySelection.Text, LookIn:=xlValues, LookAt:=xlWhole)
Dim CompanyRow As Long
CompanyRow = FoundCell.Row
With ContactList
'pull a bunch of the company's details
End With
End Sub
Here is where it gets weird... Once the form is shown and the user selects one of the combo box items, triggering the Combobox_Change event the code breaks because the 'What:=boxCompanySelection.Text' part of the Range().Find method reads as "" empty (even though Code Snippet 3 is meant to load in company names and Code Snippet 4 is only triggered when the user selects one of those company names from the combobox) and I shouldn't need to build something to handle 'not found' exceptions since the only possible values should be the ones pulled in from my named range.
From stepping through the code, I have determined that for some reason, Code Snippets 2 and 3 run TWICE before Snippet 4 is run. Does anyone know what about my code is causing this to happen? I'm thinking there's a disconnect between the form that is shown and loaded with combobox values and whatever Code Snippet 4 is reading data from.
What is weirder is that if I run the code starting from Code Snippet 2 (ignoring the button call in Code Snippet 1), the form works as intended and from what I can tell 2 and 3 are only run once.
The problem is probably something simple I'm overlooking but I just cannot figure out what it is. Thanks again!
You have to understand that a form is an object - exactly as any other class module, except a form happens to have a designer and a base class, so UserForm1 inherits the members of the UserForm class.
A form also has a default instance, and a lot of tutorials just happily skip over that very important but rather technical bit, which takes us exactly here on Stack Overflow, with a bug involving global state accidentally stored on the default instance.
Call frmShowDeets.ShowDeets
Assuming frmShowDeets is the name of the form class, and assuming this is the first reference to that form that gets to run, then the UserForm_Initialize handler of the default instance runs when the . dot operator executes and dereferences the object. Then the ShowDeets method runs.
Public Sub ShowDeets()
Dim frm As frmShowDeets
Set frm = New frmShowDeets 'this line triggers the Userform_Initialize() event below
frm.Show
End Sub
That line triggers UserForm_Initialize on the local instance named frm - which is an entirely separate object, of the same class. The Initialize handler runs whenever an instance of a class is, well, initialized, i.e. created. The Terminate handler runs when that instance is destroyed.
So ShowDeets is acting as some kind of "factory method" that creates & shows a new instance of the frmShowDeets class/form - in other words whatever happened on the default instance is irrelevant beyond that point: the object you're working with exists in the ShowDeets scope, is named frm, and gets destroyed as soon as it goes out of scope.
Remove the ShowDeets method altogether. Replace this:
Call frmShowDeets.ShowDeets
With this:
With New frmShowDeets
.Show
End With
Now the Initialize handler no longer runs on the default instance.
What you want, is to avoid using the default instance at all. Replace all frmShowDeets in the form's code-behind, with Me (see Understanding 'Me' (no flowers, no bees)), so that no state ever accidentally gets stored in the default instance.
Call frmShowDeets.PullData
Becomes simply:
Call Me.PullData
Or even:
PullData
Since Call is never required anywhere, and the Me qualifier is always implicit when you make a member call in a class module's code.

Excel VBA Missing Reference - PI Osisoft

I have an VBA code where I use many objects from PISDK, which I have to add as reference to my project.
I must explicitly declare the variables otherwise the code won't work. I don't know why. Excel throws an error ("types doesn't match") if I declare, for example, pt as object instead of PIPoint.
Here is part of my code:
Dim srv As Server
Dim pt As PIPoint
Dim pv As PIValue
Dim dt As New PITimeFormat
The problem is: when user doesn't have this reference installed, Excel gives me an compilation error, so it's impossible to catch and handle this error. Since this code runs on a user-defined function, as soon as the user opens the workbook, he gets stuck with compiling errors.
I must be able to catch this error.
I can't find documentations to fully implement late binding on this code. I don't know if it's really possible to do it. I know it could solve my problem.
Also, I know I could check if the reference is installed, thru:
thisworkbook.vbproject.references
But if the user doesn't allow access to the vbaProject object under Excel options, I am not able to do this.
Any idea?
I managed to solve my problem declaring everything as object and then using createobject afterwards.
The main problem doing this was using functions, like this one:
I have the function "arcValue". It takes three arguments:
arcValue(TimeStamp as PITimeFormat, Mode as RetrievelTypeConstants, Optional asynchStatus as PIAyncnStatus)
The way I use it doing early binding is:
dim pt as PIPoint
dim pv as PIValue
set pv = pt.data.arcValue("01/09/2014 17:00:00", rtInterpolated)
This works. But when I do:
Dim myPISDK As Object
Dim srv As Object
Dim pt As Object
Dim pd as Object
Dim pv as Object
Set myPISDK = CreateObject("PISDK.PISDK")
Set pv = CreateObject("PISDK.PIValue")
Set srv = myPISDK.Servers.defaultserver
Set pd = pt.DATA
Set pt = srv.PIPoints("piTAG")
Set pv = pd.ArcValue("01/09/2014 17:00:00", rtInterpolated)
It doesn't work. But why?
There were two problems:
First: When I use late binding (createobject) I don't have access to "rtInterpolated" constant, so I have to use its equivalent number.
Set pv = pd.ArcValue("01/09/2014 17:00:00", 3)
But this still doesn't work. So I had to do this to make it work:
Set pv = pd.ArcValue("01/09/2014 17:00:00", 3, Nothing)
And then everything started working. I don't know why, but VBA makes me write something do all parameters, even if they are optional.
This way, I am able to detect erros in runtime, so I used this code:
If myPISDK Is Nothing Then
piVerified = "Erro PI"
Exit Function
End If
Also, I had to remove all references (they are not used anymore, anyway) because it was causing malfunction on other parts of my code not related to this one when the references were missing.
You can use something like that:
Sub NotUsed()
Dim pt As PIPoint
End Sub
Function ReferenceCheck() As Boolean
On Error GoTo NoRef
pt = Acrobat.AV_DOC_VIEW ' PIPoint
ReferenceCheck = True
Exit Function
NoRef:
ReferenceCheck = False
End Function
Sub Test()
If ReferenceCheck Then NotUsed
End Sub
The function refer to a proprieties of the object. If the reference it's ok return true otherwise false.
In the phase of init you can check like that.
The sub NotUsed, don't create Error because not called...
In my sample I use the ADOBE Object ...

Resources