VBA errors when opening xl document - vba

I added some VBA code for my xl sheets .
This code seems to compile when i open the WorkBook.
An exemple of the type of error i got when i open the document .
Private Sub ComboBox1_Change()
If ComboBox1.Value = "GGS" Then
Sheets("Index").CommandButton2.Visible = True
==> Sheets("Index").Label6.Visible = True
Sheets("MNO").CommandButton5.Visible = True
Sheets("ServiceProvider").CommandButton5.Visible = True
Sheets("ServiceDeployer").CommandButton5.Visible = True
Sheets("CardVendor").CommandButton5.Visible = True
Sheets("LoadFile").CommandButton5.Visible = True
Else
Sheets("Index").Label6.Visible = False
Sheets("Index").CommandButton2.Visible = False
Sheets("MNO").CommandButton5.Visible = False
Sheets("ServiceProvider").CommandButton5.Visible = False
Sheets("ServiceDeployer").CommandButton5.Visible = False
Sheets("CardVendor").CommandButton5.Visible = False
Sheets("LoadFile").CommandButton5.Visible = False
End If
I got a "Run-time errror '438' : Object doesn't support the property or method " on the marked line
Sometimes there is the same error for this line in another sheet
Me.ListBox1.Clear
So I end the debuging , then all the code works properly ,even those last lines .
Is it possible to disable the auto compilation at the opening of the document ?
It seems that the VBA editor tries to run the code before the View is created.
The debug just drop an "Object required" .I checked before stoping debuging and the object was not in the objects list .When i stoped the debuging then checked the list, the object was there
(I'm French so there might have some english mistakes )
Thank you for reading me
Spikeze
EDIT :
I found the problem.
The "ComboBox1.Style " is on fmStyleDropDownList to avoid the user to edit the options .
But this option makes the Combobox automatically choose the first option when the document opens.
So I guess it runs "ComboBox1_Change()" when the first option is choosed but some view elements are not loaded at this time and the VBA editor drops an "Objec required".
I set the style to fmStyleDropDownCombo and fmStyleDropDownList when the sheets is active but if the WorkBook is saved and reopened the style is on fmStyleDropDownList again and I got the error again .
To solve it I had those sub
Private Sub Worksheet_Activate()
ComboBox1.Style = fmStyleDropDownList
End Sub
In the Index sheet code and
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Sheets("Index").ComboBox1.Style = fmStyleDropDownCombo
End Sub
In the WorkBook code .
Spikeze

You can just use error handling. Not the best solution, but it should work. If you are sure these objects exist, when you need them, you can use
On Error Resume Next
Or handle the error properly, with checking code error and resuming only on 438

Related

Where name created with "Application.Names.Add" go?

For learning and work purposes I needed to create mesage box that pop-ups first only first time opening workbook. For that task I found elegant solution in one of the old treads (old thread).
Working principle of sugested code is more or less clear to me exept part where named created with Application.Names.Add go? I checked under Forlulas -> name manager and did not find created name, I gues it went somwhere else?
Used Code:
Sub RunOnce()
Dim Flag As Boolean: Flag = False
For Each Item In Application.Names
If Item.Name = "FunctionHasRun" Then Flag = True
Next
If Flag = False Then
Call Application.Names.Add("FunctionHasRun", True, False)
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
Call RunOnceFunction
End If
End Sub
Formulas -> Names only shows you the ThisWorkbook.Names and Worksheet.Names (depending on the scope of your Name).
If you insert a breakpoint and look at View > Locals Window you can find the Application.Names in Me > Application > Names.
My preferred method of adding an "opened" flag is to add to the CustomDocumentProperties. I've never seen anyone use Application.Names for this.
If what you want is for a messagebox to pop up when the workbook is opened then the following code will do that for you, simply place it under ThisWorkbook.
Also I'm pretty sure the syntax in your code is incorrect, if you wanted to add a Named Range you would do it as follows: Sheet1.Range("A1:Z10").Name = "MyNamedRange" there would be no need for the Call before it, as it isn't calling another subroutine/function:
Private Sub Workbook_Open()
MsgBox "This will pop up when the Workbook is opened!", vbInformation, "My MessageBox Title"
End Sub
UPDATE:
If you only want it to run the very first time the workbook is opened and then never again, the following will achieve that for you:
Sub RunOnce()
Dim Flag As Boolean: Flag = False
For Each Item In Application.Names
If Item.Name = "FunctionHasRun" Then Flag = True
Next
If Flag = False Then
Sheet1.Range("$A$1:$A$1").Name = "FunctionHasRun"
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
Call RunOnceFunction
End If
End Sub
You cannot see it in the Name Manager because your third argument, Visible:=False, is set False.
Visible - True specifies that the name is defined as visible. False specifies that the name is defined as hidden. A hidden name does not appear in the Define Name, Paste Name, or Goto dialog box. The default value is True .
See Names.Add Method for more information.

Excel VBA Run-time error 438 first time through code

I'm a novice self-taught VBA programmer knowing just enough augment Excel/Access files here and there. I have a mysterious 438 error that only popped up when a coworker made a copy of my workbook (Excel 2013 .xlsm) and e-mailed it to someone.
When the file is opened, I get a run time 438 error when setting a variable in a module to a ActiveX combobox on a sheet. If I hit end and rerun the Sub, it works without issue.
Module1:
Option Private Module
Option Explicit
Public EventsDisabled As Boolean
Public ListBox1Index As Integer
Public cMyListBox As MSForms.ListBox
Public cMyComboBox As MSForms.Combobox
Public WB As String
Sub InitVariables()
Stop '//for breaking the code on Excel open.
WB = ActiveWorkbook.Name
Set cMyListBox = Workbooks(WB).Worksheets("Equipment").Listbox1
Set cMyComboBox = Workbooks(WB).Worksheets("Equipment").Combobox1 '//438 here
End Sub
Sub PopulateListBox() '//Fills list box with data from data sheet + 1 blank
Dim y As Integer
If WB = "" Then InitVariables
ListBox1Index = cMyListBox.ListBoxIndex
With Workbooks(WB).Worksheets("Equipment-Data")
y = 3
Do While .Cells(y, 1).Value <> ""
y = y + 1
Loop
End With
Call DisableEvents
cMyListBox.ListFillRange = "'Equipment-Data'!A3:A" & y
cMyListBox.ListIndex = ListBox1Index
cMyListBox.Height = 549.75
Call EnableEvents
End Sub
...
PopulateListBox is called in the Worksheet_activate sub of the "Equipment" sheet.
All my code was in the "Equipment" sheet until I read that was bad form and moved it to Module1. That broke all my listbox and combobox code but based on the answer in this post I created the InitVariables Sub and got it working.
I initially called InitVariables once from Workbook_open but added the If WB="" check after WB lost its value once clicking around different workbooks that were open at the same time. I'm sure this stems from improper use of Private/Public/Global variables (I've tried understanding this with limited success) but I don't think this is related to the 438 error.
On startup (opening Excel file from Windows Explorer with no instances of Excel running), if I add a watch to cMyComboBox after the code breaks at "Stop" and then step through (F8), it sets cMyComboBox properly without error. Context of the watch does not seem to affect whether or not it prevents the error. If I just start stepping or comment out the Stop line then I get the 438 when it goes to set cMyComboBox.
If I add "On Error Resume Next" to the InitVariables then I don't error and the project "works" because InitVariables ends up getting called again before the cMyComboBox variable is needed and the sub always seems to work fine the second time. I'd rather avoid yet-another-hack in my code if I can.
Matt
Instead of On Error Resume Next, implement an actual handler - here this would be a "retry loop"; we prevent an infinite loop by capping the number of attempts:
Sub InitVariables()
Dim attempts As Long
On Error GoTo ErrHandler
DoEvents ' give Excel a shot at finishing whatever it's doing
Set cMyListBox = ActiveWorkbook.Worksheets("Equipment").Listbox1
Set cMyComboBox = ActiveWorkbook.Worksheets("Equipment").Combobox1
On Error GoTo 0
Exit Sub
ErrHandler:
If Err.Number = 438 And attempts < 10 Then
DoEvents
attempts = attempts + 1
Resume 'try the assignment again
Else
Err.Raise Err.Number 'otherwise rethrow the error
End If
End Sub
Resume resumes execution on the exact same instruction that caused the error.
Notice the DoEvents calls; this makes Excel resume doing whatever it was doing, e.g. loading ActiveX controls; it's possible the DoEvents alone fixes the problem and that the whole retry loop becomes moot, too... but better safe than sorry.
That said, I'd seriously consider another design that doesn't rely so heavily on what appears to be global variables and state.

Excel VBA Application.StatusBar in Worksheet_Deactivate fails with 50290

I have a Worksheet, which updates the StatusBar based on which cell is selected (this works fine). My problem is, with the code that sets the StatusBar back to empty when the user goes to another Worksheet:
Private Sub Worksheet_Deactivate()
Application.StatusBar = vbNullString ' Run time error here
End Sub
Err.Description is: "Method 'StatusBar' of object '_Application' failed", Err.Number is: 50290.
This error occurs only if the user changes from Worksheet to Worksheet rapidly (by pressing Ctrl+PgUp or Ctrl+PgDown) and does not happen in case of switching to another Sheet slowly.
Why do I have this error?
Just set it to False
Application.StatusBar = False
from Microsoft:
This property returns False if Microsoft Excel has control of the status bar. To restore the default status bar text, set the property to False; this works even if the status bar is hidden.
I found the problem. When an event handler starts execution, the Excel Application may not be ready, so this has to be checked if the code refers to objects related to the Application:
Private Sub Worksheet_Activate()
If Application.Ready = False Then Exit Sub
' Rest of the code referring to Application.x or Me.y or ActiveSheet.z, etc.
End Sub

Reference a check box in another open workbook

I am trying to refer to the value of an ActiveX checkbox control in another worksheet. My goal is to make the value of the check box in my current workbook the same as the one in another open workbook.
I can do this between two checkboxes in the same workbook on different sheets:
Private Sub CommandButton1_Click()
If Sheets("Sheet2").Box2.Value = True Then
Box1.Value = True
Else: Box1.Value = False
End If
End Sub
But I'm receiving a Run-time error '9' "Subscript out of range" error when I run the following code:
Private Sub CommandButton2_Click()
If Worksheets("Book2").OLEObjects("Box3").Value = True Then
Box1.Value = True
Else: Box1.Value = False
End If
End Sub
The "If Worksheets" line is highlighted when I try to debug the code. I'm sure I'm referring to the other checkbox incorrectly, but I've searched high and low for the proper way to refer to this without any luck. Thank you in advance for your help!
If Worksheets("Book2").OLEObjects("Box3").Value = True Then
"Book2" is not the name of a Worksheet, presumably it is the name of the other book. In which case:
If WorkBooks("Book2").Worksheets(1).OLEObjects("Box3").Value = True Then
..or use whatever the name of the worksheet in the other book is called.

Excel dropdowns in VBA: "Unable to get the DropDowns property of the Worksheet class"

I have this code:
Sub addDropdown(Name)
ActiveSheet.DropDowns.Add(74.25, 60, 188.25, 87.75).Select
Set n = ActiveSheet.DropDowns(Name)
If Not (n Is Nothing) Then
ActiveSheet.DropDowns(Name).Delete
End If
With Selection
.ListFillRange = "$K$15:$M$19"
.LinkedCell = "$K$8:$L$11"
.DropDownLines = 6
.Display3DShading = False
.Name = Name
End With
ActiveSheet.DropDowns(Name).Display3DShading = True
End Sub
Which results in "Runtime error 1004: Unable to get the DropDowns property of the Worksheet class"
I am a VBA noob, so why is it refering to a property? According to the Object Browser DropDowns is a function (although that doesnt rime with the .Add later on).
Also, I can access this exact thing later on after having added something to DropDowns. I just dont get it.
What I want to do, is to delete any pre-existing dropdown with the same name.
You need to handle the error if the named Dropdown does not exist
on error resume next
Set n = ActiveSheet.DropDowns(Name)
on error goto 0