Workbook not opening at startup (splash screen frozen) - vba

I use Excel 2016. The file I am using runs some code in workbook Open event handler.
Depending on what the code does the workbook may never get opened (visible).
in Workbook_Open the event handler establishes a connection with a data base and load some data eventually warn the user if an error occurs for instance.
Establishing the connection with a data base and load some data works most of the time. Some times it does not and the Excel splash screen remains on the screen for ever. After closing the splash screen clicking on the close cross, the Excel process continues running in the background.
If an error occurs I don't see the pop up form which is opened to warn the user as long as the workbook is not visible.
when I kill the process an reopen Excel (not the workbook), Excel suggest to retrieve the file which was opened earlier proving somehow that it has in deed been opened.
The second process just does not work unless the workbook is visible. If I run Excel and then open the workbook it s ok (in case an error occurs the warning pop up form is opened).
If Excel is closed and i open the workbook it does not work (splash screen frozen).
what is the proper way to start a VBA application where It is necessary to manage some cosmetics tasks (show some sheets, hide some other) and run a connection to a data base?
Here is a simplified version of the code (can't provide it all - too complex - too long)
In this code the function bConnectToTheDatabase is forced to return False which make the bLogin function useless (the code is not provided for this reason).
Private mLoginForm As frmLgn ' a form to login the application (see image)
Private mCustomMsgBox As frmMsgBox ' a form to display custom messages (see image)
Public Const gsPFU_VBA_PWD as String = "my secret password"
Public Const gsBLANK_WKS_NAME As String = "Blank"
Private Sub Workbook_Open()
'
Call HidShowSomeSheets()
' start the application up
Call LoginIntoTheApplication()
End Sub
' hide all sheets but the one named gsBLANK_WKS_NAME
' protect/unprotect to chnage visibility
Sub HidShowSomeSheets()
With Application.Workbooks(ThisWorkbook.Name())
.Unprotect (gsPFU_VBA_PWD)
.Sheets(gsBLANK_WKS_NAME).Visible = xlSheetVisible
For Each wks In .Sheets
With wks
.Unprotect (gsPFU_VBA_PWD)
End With
Next wks
For Each wks In .Sheets
With wks
If (StrComp(gsBLANK_WKS_NAME, .Name) <> 0) Then
.Unprotect (gsPFU_VBA_PWD)
On Error Resume Next
.Visible = xlSheetVeryHidden
Else
.Protect (gsPFU_VBA_PWD)
.Activate
End If
End With
Next wks
.Protect (gsPFU_VBA_PWD)
End With
End Sub
Sub LoginIntoTheApplication()
if( bConnectToTheDatabase() ) then
call bLogin
else
'create a custom form (it has it own even handler - block the execution flow)
'set mCustomMsgBox= new frmMsgBox
'mCustomMsgBox.Show vbModeless 'this does not work
MsgBox "something went wrong" 'this works
end if
end Sub
Function bLogin() as Boolean
'login into the application
End Function
Function bConnectToTheDatabase() as Boolean
'do the connection
'get the data
'etc ....
bConnectToTheDatabase= False 'fore it to False for the purpose of the explanation
End Function
The login form
The custom message box

Related

VBA - Run-time error '1004'

A bit of context, this is my first time programming using VBA in excel,
and I'm trying to create a form that fills out a spreadsheet.
I'm currently getting the error message: "Run-time error '1004': Method 'Worksheets'of object '_Global' failed
I've searched online and have tried various solutions, but I think basically it comes down to a lack of understanding on my part.
Private Sub CommandButton1_Click()
'When pressing save, save values in spreedsheet locations
ActiveSheet.range("c8").Value = ContactName.Value
ActiveSheet.range("b19").Value = ModelNumber.Value
ActiveSheet.range("d19").Value = SerialNumber.Value
ActiveSheet.range("g19").Value = IncidentNumber.Value
ActiveSheet.range("j19").Value = Description.Value
ActiveSheet.range("c7").Value = PortLocation.Value
'save file
ActiveWorkbook.SaveAs Filename:= _
"D:\Users\611281\Downloads\Zebra\EmailMeToZebra.xlsx", FileFormat:=xlOpenXMLWorkbook, ReadOnlyRecommended:=False, CreateBackup:=False
End 'after pressing save, close down sheet.
End Sub
Private Sub UserForm_Initialize()
Me.PortLocation.List = Worksheets("Data lookup_ports").range("e3:e200").Value
Dim MyTempWkBk As Workbook
Dim MyCurrentWin As Window
Set MyCurrentWin = ActiveWindow
Set MyTempWkBk = Workbooks.Open("D:\Users\611281\Downloads\Zebra\GUI.xlsm")
MyCurrentWin.Activate 'Allows only a VERY brief flash of the opened workbook
MyTempWkBk.Windows.Visible = False 'Only necessary if you also need to prevent
'the user from manually accessing the opened
'workbook before it is closed.
'Operate on the new workbook, which is not visible to the user, then close it...
End Sub
Private Sub UserForm_Terminate()
End 'when pressing x, close down window, do not save.
End Sub
I'm getting the error on the code:
Me.PortLocation.List = Worksheets("Data lookup_ports").range("e3:e200").Value
Which is just me trying to populate a ListBox from a spreadsheet range
Have you tried naming the workbook? This is assuming the line with the error is referring to a cell range in thisworkbook. Also, make sure to check the name of the sheet you are referring to for exact spelling (if spelling appears correct, also check for lagging spaces.) Also, is the worksheet hidden? If so, this may need to be added before calling the sheet.
wb.sheets("Data lookup_ports").Visible = True
Can try the below edit in the meantime.
Private Sub UserForm_Initialize()
Dim MyTempWkBk As Workbook
Dim MyCurrentWin As Window
Dim WB as Workbook
Set WB = ThisWorkBook
wb.sheets("Data lookup_ports").Visible = True
Me.PortLocation.List = WB.Sheets("Data lookup_ports").Range("E3:E200").Value
Set MyCurrentWin = ActiveWindow
Set MyTempWkBk = Workbooks.Open("D:\Users\611281\Downloads\Zebra\GUI.xlsm")
MyCurrentWin.Activate
MyTempWkBk.Windows.Visible = False 'Only necessary if you also need to prevent
'the user from manually accessing the opened
'workbook before it is closed.
'Operate on the new workbook, which is not visible to the user, then close it...
End Sub
Private Sub UserForm_Terminate()
End 'when pressing x, close down window, do not save.
End Sub

Running excel macros only on one sheet

Hi Iam new to writing VBA code and need assistance. My VBA code and Macro works fine as long as I am on the active sheet.
My Problem:
My VBA code and macro, stops running automatically, when i change from the active sheet to another within the same workbook and
My VBA code and macro, stops running automatically, when i open a new excel workbook
Solution required:
Run the VBA code and macro only on desired worksheet and prevent it from running on other worksheets and workbooks.
Background:
I have an excel file, named "Net Weight" with two sheets. sheet 1 is named : "weight", sheet 2: is named "base data".
sheet 1 is used as a user input form.
In sheet 1- cell B1 : user will type in a product code , in cell E1: a look up formula will place the description of the product code using the data from sheet 2
I have setup a VBA code and macro that does the following:
As soon as a user inputs a product code into cell B1, in sheet 1, sheet 1 is saved as PDF file into a predefined folder location data from cell B1 and E1
A macro saves and overwrties the PDF file every 10 seconds.
This process is repeated every time a new product code is entered
There are no buttons on sheet 1, everything is done automatically.
Here is my current code:
Sheet 1: set as Worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$1" Then
Call Macro1
End If
End Sub
Module 1 macro : set as general
Sub Macro1()
Application.DisplayAlerts = False
If ThisWorkbook.Name = "Nett Weight.xlsm" And ActiveSheet.Name = "Weight" Then
Sheets("Weight").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:="C:\Nett weight\" & Range("B1 ").Text & Range(" E1").Text
Application.OnTime Now + TimeValue("00:00:10"), "Macro1"
Else
Exit Sub
End If
End Sub
First, you need to create a public variable to hold your timer, otherwise you'll never be able to cancel it so it will continue trying to fire even when your workbook is closed. You should also create a public variable to store when the timer is running, so you can check before creating a new timer.
At the top of a code module put:
Public nextTime As Date
Then in your Workbook_BeforeClose() event method (within ThisWorkbook), disable the existing timer so it doesn't keep trying to fire after the workbook is closed.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
End Sub
In Macro1() you should explicitly and directly reference your workbook components - ThisWorkbook always refers to the workbook the code is running from, so you don't need your If statement. Then you set the nextTime and activate the timer using that variable if it is not already running.
Sub Macro1()
Dim sht As Worksheet ' Creates a variable to hold your Weight worksheet
Set sht = ThisWorkbook.Sheets("Weight") ' Sets the reference
Application.DisplayAlerts = False
sht.ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\Nett weight\" & sht.Range("B1").Text & sht.Range("E1").Text ' Remember to preceed Range with sht. to explicitly reference the range of your Weight worksheet
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
nextTime = Now + TimeSerial(0, 0, 10) ' Adds 10 seconds to Now
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=True
timerIsRunning = True
Application.DisplayAlerts = True ' Remember to enable alerts at the end of code
End Sub
Your Worksheet_Change() event method can stay as is. Now if there is a change in B1 it will call Macro1(). Macro1() will save the Weight worksheet as a PDF regardless of whether the workbook or worksheet is active, and create a new timer to re-run Macro1() every 10 seconds after deactivating an existing timer. When you're finished with the workbook, you close it and the existing timer is also deactivated.
EDIT:
Fortunately (as it fixes a spreadsheet of my own) I have figured out why the solution I originally provided wasn't working. Placing the Public variables under ThisWorkbook meant they no longer held their values after code execution. The remedy was to place them in a module instead. Once that was sorted out, I also realised that when the timer fires to call Macro1() it will throw an error when trying to unschedule the existing timer (as none exists unless Macro1() was called ad hoc by the Worksheet_Change() event).
Long story short: Public variables have been moved to a code module, and the timerIsRunning flag has been removed entirely and errors when attempting to unschedule the timer are simply ignored in the event that no timer exists.

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

How to disable a ribbon button in Excel if a particular worksheet exists with VBA

I'm building an Excel add-in which allows users to interact with PowerPoint and export data. The users have an option to insert a template into an existing workbook via a button in the ribbon. When they click this, the button becomes disabled as you can't have two templates in one workbook.
The user may then save their workbook and come back to it at a later point. My issue is that I need to detect that they have the template inserted into an existing workbook and I do this by trying to detect if a named range exists (called LoadedToken).
The issue I have is that both the onLoad function of the Ribbon and the VBA class Auto_Open launch before a large workbook is fully loaded. Therefore I'm not actually detecting if the template exists and can't actually disable the button.
Is there such a thing as events in Excel which can be called at a worksheet level (like worksheet_open) but detected in a class?
My code is:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' When the Ribbon loads
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub OnRibbonLoad(ribbonUI As IRibbonUI)
Set MyRibbonUI = ribbonUI
Dim Authenticate As New AuthenticationClass
On Error Resume Next
' Enable/Disable buttons based on authentication status
If Authenticate.Authentify = False Then
Authenticated = False
Debug.Print ("Unauthorized!")
Else
Authenticated = True
Debug.Print ("Authorized!")
End If
' If the template doesn't exist then disable a grouping on the ribbon
If TemplateExists = False Then
Call RefreshRibbon(Tag:="Grouping1")
Else
Call RefreshRibbon(Tag:="Grouping2")
End If
End Sub
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Check if the Template sheet is visible and prevent other buttons from working
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function TemplateExists()
Dim Helpers As New HelpersClass
If Helpers.IsNamedRange("LoadedToken") Then
TemplateExists = True
Else
TemplateExists = False
End If
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' From the Helpers Class - Check if a named range exists
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IsNamedRange(RName As String) As Boolean
Dim N As name
IsNamedRange = False
For Each N In ActiveWorkbook.Names
If N.name = RName Then
IsNamedRange = True
Exit For
End If
Next
End Function
Note: The authentication class is just another class to connect to my API.

Excel 2013 - issue when closing multiple workbooks if one workbook is hidden

I've written a program in Excel VBA which uses a UserForm to enter data by the users. Specifically, it is a Telemarketing Tracker tool: the user fills in the details of the call in a text box on the UserForm and then clicks the relevant button to indicate whether it was a good or bad call, and can then continue with the next call.
This data is stored on a worksheet and our users often prefer to hide the workbook and just view the UserForm. I have developed a couple of methods of hiding the workbook. If there is just one workbook open, I hide the Excel Application. If there is more than one workbook open, I just hide the window. Here is the code I use for this:
Private Sub HideUnhideButton_Click() 'User clicks Hide/Unhide button
If Workbooks.Count > 1 Then
Windows(ThisWorkbook.Name).Visible = Not Windows(ThisWorkbook.Name).Visible
HideUnhideButton.Tag = Windows(ThisWorkbook.Name).Visible
Else
ThisWorkbook.Application.Visible = Not ThisWorkbook.Application.Visible
HideUnhideButton.Tag = ThisWorkbook.Application.Visible
End If
ThisWorkbook.Activate
End Sub
This works well but obviously certain issues arise when the user has the workbook hidden and then open a different Excel Workbook. I've worked round most of these issues, but there is one thing I can't seem to work out: if the Telemarketing workbook is hidden, with another workbook open, if I click the Close button, both workbooks try to close.
I've tried creating a class module with an Application Level event tracker so that all workbooks' close events are monitored. But my problem is that when I click the close button, the first workbook that tries to close is the hidden workbook. So I can catch the close event and prevent the hidden workbook from closing but if I set Cancel to True, it prevents all the workbooks from closing!
The only workaround I can think of is when the user tries to close a workbook, I cancel the Close Event and Unhide the hidden workbook. But I don't know how to identify which workbook the user was attempting to close - so I can't work out how to automatically close the correct workbook.
I have currently set up the WorkbookBeforeClose event as follows:
Public WithEvents A As Excel.Application
Private Sub A_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
If Workbooks.Count > 1 Then
If Windows(ThisWorkbook.Name).Visible = False Then
If Wb.Name = ThisWorkbook.Name Then
Cancel = True
End If
End If
End If
End Sub
If I step through this code, I find that the Wb.Name is the name of the Telemarketing Workbook (even though it's hidden) and the name of the workbook that the user is actually trying to close does not appear at all - as far as I can work out.
Can anyone make any further suggestions?
The other thing I should mention is that it needs to work over Excel 2013 and Excel 2010.
I'm sorry to post an answer to my own question so quickly. It sort of indicates I didn't do quite enough research beforehand. However, for anyone who has a similar problem, here's my solution. This code needs to be posted in a class module and an instance of the class needs to be created before it will work, of course.
Note: in the below example, "TT" relates to the Telemarketing Tracker
Public WithEvents A As Excel.Application
Private Sub A_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
Dim VIS As Boolean, myAW As Workbook
If Workbooks.Count > 1 Then 'if there is more than one workbook open...
If Windows(ThisWorkbook.Name).Visible = False Then 'and if TT is invisible...
If ActiveWorkbook.Name = ThisWorkbook.Name Then 'and if the workbook being closed is the TT.
Windows(ThisWorkbook.Name).Visible = True
Else 'more than one wb open, TT is invisible, and the workbook being closed is NOT the TT.
Set myAW = ActiveWorkbook
Cancel = True
Windows(ThisWorkbook.Name).Visible = True
Application.EnableEvents = False
myAW.Close
Application.EnableEvents = True
If TelesalesForm.HideUnhideButton.Tag = "False" Then 'NB: I use a tag on the Hide/Unhide button on the UserForm to store whether the workbook should be hidden or not.
If Workbooks.Count > 1 Then
Windows(ThisWorkbook.Name).Visible = False
Else
ThisWorkbook.Application.Visible = False
End If
End If
Exit Sub
End If
ElseIf ActiveWorkbook.Name <> ThisWorkbook.Name Then
'more than one workbook open and the TT is visible and the workbook being closed is NOT the TT
Exit Sub
End If
End If
'code gets to this point ONLY under the following circumstances:
'There is only one workbook open (i.e. the TT) OR
'There is more than one WB open and the WB being closed is the TT.
'The rest of the code goes here for managing the closing of the TT.
End Sub
If anyone thinks of any other embellishments or improvements to the code then I would be very glad to hear of them!