How to require password to terminate a userform in VBA - excel

I want to prevent the user from closing the form and editing the spreadsheet if they don't know the password. I can get the Userform to stay open but I cannot figure out how to initialize the form so all of the command buttons still function.
I have tried using an if statement as described below. The userform stays open but isn't initialized so the user is unable to enter a password or run the userform at all.
Private Sub UserForm_Terminate()
Password = InputBox("Enter Password")
If Password = "syntax" Then
UserForm1.Hide
ElseIf Password <> "syntax" Then
UserForm1.Show
End If
End
End Sub
There aren't any error messages, but if the VBA editor window isn't open the user has to close Excel completely. Any advice on what to try next is appreciated. Thanks in advance

You can use UserForm_QueryClose to intercept all 'close' actions on a userform. This code would go in the userform itself.
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Dim password As String
password = InputBox("Enter Password")
If password = "syntax" Then
Cancel = False 'If password is correct, allow close event to proceed
ElseIf password <> "syntax" Then
Cancel = True 'If password is incorrect, cancel the close event
End If
End Sub
Like K.Dᴀᴠɪs pointed out, this still won't prevent anyone from pausing the code execution and manually closing the form (Excel just doesn't provide that level of security).

Related

VBA Red Close Event did not close workbook properly

I have written a vba in which when a user opens the xlsm file, vba will set Application.Visible = False and shows user a userform to enter their credentials before setting Application.Visible = True become for user to use the excel.
While testing various scenarios, there is one that seems odd.
If user closed the Userform using the red cross at the top right corner before they successfully entered their credentials, and when I double click on the same xlsm file again, the Application becomes visible without the Userform.
I suspect when user closed with the red cross, only the UserForm is closed and the application was not. How can I make the red cross close the application so that when I double click on the xlsm again, it will run the marco for Userform to pop out?
Update:
The following did close the workbook with the red cross but I noticed even if user close the UserForm with CommandButton, it will still close the workbook. Is there a sub that only detects red cross?
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Detecting user closing with top cross
Sheet4.Range("B4") = CloseMode
If CloseMode = 1 Then Cancel = 0
ThisWorkbook.Save
ThisWorkbook.Close
End Sub
So the doc for the _QueryClose event is here: https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/queryclose-event
I am not familiar with your code, but you probably want something like this:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Detecting user closing with top cross
If CloseMode = 0 Then
' 0 = vbFormControlMenu (the [X] was clicked)
Cancel = 1 ' this keeps the form from closing
'(or whatever you want to do here)
End if
End Sub

Excel VBA - Bypass my own code that requires a password to save, or pass the password from one sub to another

I have an Excel file with some complex functions, so I setup the following code to prevent some of my coworkers from making unintended changes and then saving the file. Straightforward, and it works. Unfortunately, I've outsmarted myself.
The same file requires occasional semi-manual updates that pull filename information from our network drives. I wrote a macro that accomplishes this. It runs when the user clicks on a button. [It's semi-manual because we work on different continents and while that update takes 90 seconds in France, it takes 30 minutes in the US.] That also works.
My problem is that I want everyone to be able to run the macro update and then allow the file to autosave afterwards, but I don't want to give out the password to everyone in the group. Currently, the update macro stalls when it hits the "beforesave" code. Is there a way to either
bypass this password request when running the save from the update macro, or
put the password into the update macro in a way that the "beforesave" code will recognize and accept it
Code:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim Password As String Dim EnteredPassword As String
Password = "NOTMYACTUALPASSWORD"
EnteredPassword = InputBox("Enter password to save changes")
If EnteredPassword <> Password Then
Cancel = True
MsgBox ("Password incorrect, file not saved")
End If
End Sub
You can't tell Excel to skip the BeforeSave block, but you can make your code exit before the code that stops saving.
' In a new module
Public Update_Active As Boolean ' defaults to False when not set
' At the end of your update macro before save is called
Update_Enable = True
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Update_Active Then
Update_Active = False
Exit Sub
End If
Dim Password As String Dim EnteredPassword As String
Password = "NOTMYACTUALPASSWORD"
EnteredPassword = InputBox("Enter password to save changes")
If EnteredPassword <> Password Then
Cancel = True
MsgBox ("Password incorrect, file not saved")
End If
End Sub

Excel Userform Run-Time Error when trying to launch a 2nd time after initial 'Cancel' or close on red 'X'

Problem: I am building a Userform that has a 'Submit' and 'Cancel' button. I want the entire form to clear any entered data and close the form if the user hits the 'Cancel' button but I also am trying to build in the same functionality if the user hits the red 'X' in the top right corner. I'm unclear where I need to unload the form. I currently have it placed within the btnCancel_Click() method and I'm able to launch the form, enter some data and hit Cancel and it will close the form down.
But when I try to re-launch the form a 2nd time I get an error (I attached a picture of that message) that says
"Run-Time error '-2177418105 (80010007): Automation Error - The Callee (server [not server application]) is not available and disappeared; all connections are invalid. The call may have executed.
If I remove Unload Me from btnCancel_Click() then the form can close and re-open just fine, but any data I entered the first time will still be on the form and isn't cleared properly. I'm wondering if this is an Unload Me error or do I need to reset all form controls when I initialize the form?
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' how was the form closed?
' vbFormControlMenu = X in corner of title bar
If CloseMode = vbFormControlMenu Then
' cancel normal X button behavior
Cancel = True
' run code for click of Cancel button
btnCancel_Click
End If
End Sub
'******************************************************************
Private Sub btnCancel_Click()
mbCancel = True
Me.Hide
Unload Me
End Sub
'*********************************************************************
Private Sub UserForm_Initialize()
'Populate values for 2 combo boxes
lastEmp = Sheets("Form_Ref").Cells(Rows.Count, 1).End(xlUp).Row
Me.cmbBoxEmpName.List = Sheets("Form_Ref").Range("A2:A" & lastEmp).Value
lastBld = Sheets("Form_Ref").Cells(Rows.Count, 2).End(xlUp).Row
Me.cmbBoxBuildingName.List = Sheets("Form_Ref").Range("B2:B" & lastBld).Value
End Sub
'******************************************************************
Public form As New CheckOutForm
Sub testFormOptions()
'Button pressed within Excel will start program and show the userform
form.Show
End Sub
This is the easiest quick and dirty solution:
Delete Public form As New CheckOutForm from the code. Then add it in the testFormOptions():
Sub testFormOptions()
Dim form As New CheckOutForm
form.Show
End Sub
Some not-that-good VBA books/tutorials would even go a bit like this, but this is brutal:
Sub testFormOptions()
CheckOutForm.Show
End Sub
Anyway, now the problem with the predefined values in the form is solved.
For the clean and not-so-easy solution, consider writing a MVC framework around the form:
https://codereview.stackexchange.com/questions/154401/handling-dialog-closure-in-a-vba-user-form
this blogpost (disclaimer - mine!), which pretty much says what the above link proposes, but it does not have the errors from the question.
the old StackOverflow tutorial for UserForms
If you execute Unload, you destroy the form object. With other words, your (global) variable form gets invalid and if you issue a new form.show, you get the runtime error.
When, on the other hand, you just unhide the form, the form-object stays valid (it's just currently not visible) and all controls keep their value.
Either you do some housekeeping by resetting all controls when a form is displayed (use the UserForm_Activate-event), or you have to create a new form-object every time you want to display it (I would strongly advice not to use the name form as variable name to avoid confusion).
Sub testFormOptions()
dim myForm as CheckOutForm
myForm.Show
End Sub

Select ComboBox AfterUpdate Excel VBA

I am writing a script for a UserForm through which users can register to gain access to a Database. The UserForm has three fields, Username, Password and Confirm Password.
I have made it so that, after the user chooses a username, the script runs a VLookUp through the existing usernames to check if the username chosen already exists. If so, a MsgBox pops up, advising the selection of another username. In this case, all three fields of the UserForm are cleared. I would like to make the cursor be positioned in the Username field so that the user can straight away fill in a different username. However, after all fields are cleared, the password filed is the one selected instead. How can I solve this? Thank you for your help.
This is the code I have written:
Private Sub usernameinput_AfterUpdate()
Dim username As String
username = usernameinput.Text
Dim temp As String
On Error Resume Next
temp = WorksheetFunction.VLookup(Me.usernameinput.Value, Range("Usernames"), 1, 0)
If username = temp Then
MsgBox ("The username chosen already exists. Please chose a different username."), vbOKOnly + vbInformation, "Existing Username"
Err.Clear
temp = ""
Me.usernameinput.Value = ""
Me.passwordinput.Value = ""
Me.passwordconfirm.Value = ""
Me.usernameinput.SetFocus
On Error GoTo 0
End If
End Sub
you could act like follows:
in your UserForm code pane:
declare a userform scoped variable
Dim reset As Boolean
insert this Sub
Private Sub HandleReset()
If reset Then
Me.usernameinput.SetFocus
reset = False
End If
End Sub
add all other UserForm controls Enter event handler to call HandleReset() like follows:
Private Sub passwordconfirm_Enter()
HandleReset
End Sub
Private Sub passwordinput_Enter()
HandleReset
End Sub

Encrypt password on VBA password box

I have a couple of userforms for my excel spreadsheet and I need to setup an admin panel for certain tasks that I don't want most people to access.
The problem I have is that I can setup a simple password protection form however the text is always visible. I want to try and encrypt it so if anyone is looking over my should or one of the other admins shoulders then they cannot see the password.
Is there anyway to have the text appear as **** or something similar?
Thanks
Al
Private Sub CommandButton1_Click()
Dim MyValue As Variant
MyValue = InputBox("Enter Password")
If MyValue = "lemonade" Then 'lemonade being the password
Application.Visible = True
Else
MsgBox ("Password Incorrect")
End If
End Sub
Edit - I have amended it to follow your suggestion as I had it to bring up an input box instead of creating my own userform.
If Pword2.Value = "lemonade" Then
AddPick1.Hide
Report1.Hide
Unload Me
Admin1.Show vbModal
Else
MsgBox ("Password Incorrect")
End If
When the password is incorrect it gives the incorrect password error however when it is correct it gives me the following error (Must close of hide topmost modal form first) However I have it to set to hide all other forms before loading the Admin1 form?
In the TextBox properties there is a property called PasswordChar. Enter your preferred 'hidden' character in here.
You can also add a button to your form to reveal the password if you wish using the Mouse-Up and Mouse
_Down events. MouseDown would look like the following on a textbox called TextBox1 and using a button called CommandButton1:
Private Sub CommandButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
TextBox1.PasswordChar = vbNullChar
End Sub
I'll leave you to code the Mouse_Up event.
This link will give you the usage but you will find plenty of examples with a Google search.

Resources