In one of the sheets from my macro enabled workbook I have a couple of ActiveX controls, among them a ToggleButton and an InkPicture control (the latter inserted by means of ActiveX Controls -> More Controls). I use the toggle button to show or hide a form positioned relative to the button and Excel's zoom level (based on the code here), and the ink picture control to detect changes in Excel's zoom level (based on the suggestion here).
Everything in the code works fine, but there is something that bothers me: everytime I save the workbook and open it again, I get a "Method or data member not found" error in the Sub where I set the form's position (this Sub is triggered by changes in the size of the ink control, which in turn are triggered by the changes in Excel's zoom level, probably because of the fact that the object is repainted on that occasion). After further investigation into the matter, I concluded that the error (which can be avoided using the workaround of stopping the debugger, re-compiling the VBA project and saving it afterwards) has to do with the fact that the ink picture's SizeChanged
event happens before the toggle button is created (in some of my tests, I even noticed that the event occured before the workbook's Open
event!). So, what I would need is a method of postponing the execution of the ink picture's SizeChanged
code until the toggle button is created and can be accessed as a property of the worksheet. And yes, I know I can use some variable(s) to check and possibly delay execution based on whether it was the first time the code was executed or not, but I would be interested in a more elegant/standard solution, if any.
This is my code in the ink picture's SizeChanged
event (it belongs to the MapSheet
sheet referenced further below):
Private Sub ZoomDetectorInkPicture_SizeChanged(ByVal Left As Long, ByVal Top As Long, ByVal Right As Long, ByVal Bottom As Long)
SetFormArea
End Sub
This is my form positioning code (it belongs to a "public" module in my workbook) - don't bother with the custom Subs there, the important thing is that they are fine and the error appears when trying to access the .ControlMenuToggleButton
property of MapSheet
on the second to last line of code in the Sub (i.e. that's the text on a blue background in the VBA editor).
Public Sub SetFormArea()
Dim pointcoordinates As pointcoordinatestype, horizontaloffsetinpoints As Double
' Set the column where the form is placed to the same byte width in points,irrespective of zooming
MapSheet.Columns(1).EntireColumn.ColumnWidth = Minimum(formsizeinchars * (100 / ActiveWindow.Zoom), 255)
' Get the size of the 3D border around the form in points, to position the form based on its frame
horizontaloffsetinpoints = (ControlMenuUserForm.Width - ControlMenuUserForm.InsideWidth) / 2
' Test the intersection between the target range and each pane's visible range (split/frozen must)
Call GetPointCoordinates(MapSheet.Cells(1, 1), pointcoordinates)
ControlMenuUserForm.Left = pointcoordinates.Left - horizontaloffsetinpoints + MapSheet.ControlMenuToggleButton.Left * (ActiveWindow.Zoom / 100)
ControlMenuUserForm.Top = pointcoordinates.Top + (MapSheet.ControlMenuToggleButton.Height + MapSheet.ControlMenuToggleButton.Top) * (ActiveWindow.Zoom / 100)
End Sub
By the way, what I've tried and worked (but unfortunately only until the next workbook save) was to add DoEvents
as the SetFormArea()
's first line of code, or - even better - set the toggle button's AutoLoad
property to True
, in an attempt to create the button before the ink picture or something like that (this latter method failed as well after the workbook was saved again, as the AutoLoad
property reverted to False
by itself - you know, the usual strange things that can happen in Excel).
EDIT: Apparently, what I've said in the paragraph above is not entirely true, as the error dissapears on the next workbook save even without doing the above (not even the workaround step of recompiling the project that I mentioned). The problem is that it reappears on a second save (just a simple save, not doing anything else).