VBA unprotect-blank entry and exit handling [duplicate] - excel

This question already has an answer here:
How to handle the InputBox cancel button?
(1 answer)
Closed 1 year ago.
The below code unprotects all sheets in the workbook and prompts for the password only once.
What I am trying to achieve is:
If user presses "cancel" on the password input window, the sub exits.
If user presses "ok" without entering anything, it should behave in the same way as entering the wrong password i.e. go to the error popup.
The issue is on pressing "ok" or "cancel" it doesnt behave as above, rather, in both cases, it brings up the default password prompt 3 more times, 1 for each sheet.
I am struggling with perfecting the if/then logic and have swapped things around many times, almost getting there but never quite.
Sub UnprotectAllSheets()
Dim ws As Worksheet
Dim pass As String
If ActiveSheet.ProtectContents = False Then
MsgBox "Already Unprotected"
Exit Sub
Else
pass = InputBox("Password?")
On Error GoTo Popup:
For Each ws In ThisWorkbook.Worksheets
ws.Unprotect pass
Next ws
If ActiveSheet.ProtectContents = False Then
MsgBox "Sheets now Unprotected"
ElseIf StrPtr(pass) = "" Then 'if press OK on blank entry
MsgBox "Incorrect Password", vbCritical, "Admin"
ElseIf pass = 0 Then 'if press CANCEL
Exit Sub
End If
End If
Popup:
If err.Number = 1004 Then
MsgBox "Incorrect Password", vbCritical, "Admin"
End If
End Sub

InputBox behaves similarly for cases of pressing Cancel, inputting an empty string or pressing window corner x, in terms of String return.
The next sub gives a possibility to separate the above cases:
Sub testInputBox()
Dim pass
pass = InputBox("Password?")
'standard behavior without checking the result:
MsgBox "Pass is " & pass 'it will be an empty string in case of Cancel, empty string, pressing window corner X
If StrPtr(pass) = 0 Then
MsgBox ("Cancel pressed...") 'the same message if window corner `X` is pressed
ElseIf pass = vbNullString Then
MsgBox ("Empty string..") 'OK for an empty string
Else
MsgBox ("You entered " & pass)
End If
End Sub
No need of error handling if you use the above way of identification.
And I should modify your code to act in this way:
Sub UnprotectAllSheets()
Dim ws As Worksheet, pass As String, myPass As String, i As Long
myPass = "1234"
TryAgain:
pass = InputBox("Password?")
If StrPtr(pass) = 0 Then Exit Sub 'for Cancel and window corner 'X' pressed
If pass = vbNullString Then MsgBox "You did not enter any password!", vbCritical, "Admin": Exit Sub
If pass <> myPass Then
MsgBox "Incorrect Password" & vbCrLf & _
IIf(i < 3, "Please, try again!", "We stop here..."), vbCritical, "Admin"
If i >= 3 Then Exit Sub
i = i + 1
GoTo TryAgain
End If
For Each ws In ThisWorkbook.Worksheets
If ws.ProtectContents = True Then
ws.Unprotect pass
End If
Next ws
End Sub

Related

how to retrieve a value from an userform

I'm trying to write a code to trace every change made by the user on any worksheet. The user will input data and from time to time will erase said data and/or correct the original value they inserted. If the change is either deletion or modification, an Userform will pop up and the user will include a reason for that change. Right now I'm able to display the form everytime the user makes one of the changes mentioned before, but I'm not able to retrieve the reason, could you guys help me?
This is what I have for the UserForm
Private Sub CommandButton1_Click()
Dim msgvalue As VbMsgBoxResult
Dim value As String
msgvalue = MsgBox("Do you wish to save the change?", vbYesNo + vbInformation, "Confirm")
If msgvalue = vbNo Then GoTo Command
If msgvalue = vbYes Then
value = UserForm1.txtCmmt.Value
If value = "" Then GoTo Command
End
End If
Command:
MsgBox ("A reason must be provided")
With UserForm1
.txtCmmt.Value = ""
End With
End Sub
So if a user tries to delete a value, the code is the following:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sLastAction As String
Dim Cell As Range
sLastAction = Application.CommandBars("Standard").Controls("&Undo").List(1)
For Each Cell In Target
If sLastAction = "Clear" Or sLastAction = "Delete" Or Left(sLastAction, 9) = "Typing ''" Then
UserForm1.Show 'this is where I'm stuck, I'm not sure how to retrieve the value from the form
End If
'the code continues to retrieve other info from the changes made, including the "reason"
Thanks for the help!
Try the next way, please:
Let us say that your text box where the comment will be written is named "txtComment".
Put this code in its Exit event:
Private Sub txtComment_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If Me.txtComment.text <> "" Then
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
Sheets("LogDetails").Range("A" & rows.count).End(xlUp).Offset(0, 5).Value = Me.txtComment.text
Application.EnableEvents = True
Unload Me
End If
End If
End Sub
Let the existing Worksheet_Change event as it is, only launching the form and maybe making a Public boolean variable (from a standard module) True (something boolStop) which will not allow changing anything in any worksheet until it is not False.
Then fill the text you need in the text box ("txtComment", or however you named it) and press Enter. If my above suggestion looks interesting for you, the last line of the text box event will be boolStop = False.
If you understand how to implement the above simple solution, you maybe will forget about a user form and use a simple InputBox, as in the next example:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) <> "E1" Then Exit Sub
Dim sLastAction As String, comValue As String
Dim Cell As Range
sLastAction = Application.CommandBars("Standard").Controls("&Undo").list(1)
For Each Cell In Target
If sLastAction = "Clear" Or sLastAction = "Delete" Or left(sLastAction, 9) = "Typing ''" Then
WritePlease:
comValue = InputBox("Please write the reason for cell """ & Cell.Address & """ (" & sLastAction & ").", "Reason, please")
If comValue = "" Then GoTo WritePlease
If ActiveSheet.Name <> "LogDetails" Then
Application.EnableEvents = False
'Stop
Sheets("LogDetails").Range("A" & rows.count).End(xlUp).Offset(0, 5).Value = comValue
Application.EnableEvents = True
End If
End If
Next
End Sub

Excel VBA password protect a command button

I've got a very large and somewhat fragile spreadsheet that I'm working on, and I'd like to limit access to more complicated macros--ones that delete or add data. I'm less worried about security than I am about someone who doesn't know what they're doing deleting unfortunate things. I've used the 'inputbox' password trick, but it becomes slightly annoying to have to keep putting in the password over and over. Is there any way to have the macro 'remember' that I put in the password once, and then reset after I close the sheet, without storing it in a cell somewhere?
Here's the code I'm currently using:
Sub ControlPanel()
Dim PassProtect As Variant
PassProtect = InputBox(Prompt:="Please enter the password to unlock the updater." & vbCrLf & "(Case Sensitive)", Title:="Control Panel")
If PassProtect = vbNullString Then Exit Sub
If PassProtect = "password" Then
ControlPanelForm.Show vbModeless
Else: MsgBox Prompt:="Incorrect password. Please try again.", Buttons:=vbOKOnly
End If
End Sub
Thanks!
You can use a public variable to store a value when the workbook is open, so the code would become:
Public pblnEnteredPassword As Boolean
Sub ControlPanel()
Dim PassProtect As Variant
If pblnEnteredPassword Then GoTo DoStuff
PassProtect = InputBox(Prompt:="Please enter the password to unlock the updater." & vbCrLf & "(Case Sensitive)", Title:="Control Panel")
If PassProtect = vbNullString Then Exit Sub
If PassProtect = "password" Then
pblnEnteredPassword = True
GoTo DoStuff
Else
MsgBox Prompt:="Incorrect password. Please try again.", Buttons:=vbOKOnly
Exit Sub
End If
DoStuff:
ControlPanelForm.Show vbModeless
End Sub
Use a static string var within the CommandButton1_Click sub procedure. Once entered correctly, it will be 'remembered' for the duration of the session.
Option Explicit
Private Sub CommandButton1_Click()
Static pwd As String
try_again:
If pwd <> "thePassword" Then
'password challenge
pwd = InputBox(Prompt:="Please enter the password to unlock the updater." & vbLf & "(Case Sensitive)", _
Title:="Control Panel")
'check if the password challenge was cancelled
If pwd = vbNullString Then Exit Sub
'compare again
GoTo try_again
End If
'all the good code once the password challenge has been passed
Debug.Print "pass"
End Sub

Excel VB Code with Input Box to select a range, when nothing is selected it generates and error

Let me start with the fact that I am NOT a programmer. I am self taught some VB with Excel and MS Access. I know just enough to be dangerous.
I have the following code to prompt the user to select a range. The Input box has an OK and Cancel button. If you do not select any cells and hit the OK or select Cancel it generates an errors.
Private Sub Copy_St5_50_Ramp_Click()
Dim sCell As Range
Set sCell = Application.InputBox("Select the Column of data below that is valid Ramp Data STARTING With 24 Minutes!!!", "Station 5", Type:=8)
If sCell Is Nothing Then Exit Sub
If sCell.Cells.Count < 2 Then Application.InputBox ("You Did not Select Enough Cells"), ("ERROR"), vbOK
sCell.Copy
Worksheets("50 Ramp Data").Range("CJ13").PasteSpecial Paste:=xlPasteValues
'Clear Clipboard (removes "marching ants" around your original data set)
Application.CutCopyMode = False
Worksheets("50 Ramp Data").Range("L4").Select
End Sub
I need it to not error but just close the input box and maybe prompt with a message box as to what went wrong
I've added 2 events to trap the possible errors:
If the user hits cancel >> On Error Resume Next , and later check If Err.Number <> 0 Then.
If the user didn't select any cell, use another parameter in the Application.InputBox of Default:=Selection.Address. So you compare if the Selection.Address after the InputBox is the same as the Selection.Address before the InputBox. If it is, then no new selection was made >> abort the operation.
Code
Option Explicit
Private Sub Copy_St5_50_Ramp_Click()
Dim sCell As Range
Dim CurrentSelectionRng As String
CurrentSelectionRng = Selection.Address
On Error Resume Next
Set sCell = Application.InputBox(prompt:="Select the Column of data below that is valid Ramp Data STARTING With 24 Minutes!!!", Title:="Station 5", Default:=Selection.Address, Type:=8)
' trap a case when the user selectes "Cancel"
If Err.Number <> 0 Then
MsgBox "You chose cancel !", vbCritical
Exit Sub
End If
' if the user didn't select anything (but the cell curser stayed on previous selection)
If sCell.Address = CurrentSelectionRng Then
MsgBox "No cell was selected !", vbCritical
Exit Sub
End If
If sCell Is Nothing Then Exit Sub
If sCell.Cells.Count < 2 Then Application.InputBox ("You Did not Select Enough Cells"), ("ERROR"), vbOK
sCell.Copy
Worksheets("50 Ramp Data").Range("CJ13").PasteSpecial xlPasteValues
'Clear Clipboard (removes "marching ants" around your original data set)
Application.CutCopyMode = False
Worksheets("50 Ramp Data").Range("L4").Select
End Sub

VBA: Workbook.Close loop

I have the following portion of the code for a given active worksheet:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim sh As Worksheet
Dim myMessage
If ActiveSheet.Range("I5").Value > 0 Then
MsgBox "Some cells are empty" _
& Chr(13) & Chr(13) & "Please, fill in the empty cells to proceed", _
vbExclamation + vbOKOnly, "ERROR!"
Cancel = True
Else
ThisWorkbook.Unprotect ("123")
Worksheets("Instructions").Visible = True
Worksheets("Instructions").Activate
For Each sh In Worksheets
If sh.Name <> "Instructions" Then
sh.Visible = xlVeryHidden
End If
Next sh
ThisWorkbook.Protect ("123")
myMessage = MsgBox("Do you want to save and close this file?", vbQuestion + vbYesNo, "Workbook 1")
If myMessage = vbYes Then
Application.DisplayFormulaBar = True
ThisWorkbook.Close True
ElseIf myMessage = vbNo Then
Cancel = True
Else
'nothing
End If
End If
End Sub
In general, upon pressing the close button on the workbook itself, the idea is to check a given cell of a given active worksheet for a non-zero value. If it is non-zero, the user has to fill in certain empty cells first and the workbook is not closed. Alternatively, the "Instruction" worksheet is activated and the user receives a message box of what to do next (by doing this, instead of simply no msgbox and sticking with the usual system "SAVE/NO" prompt, is that I want to eliminate the possibility of a user pressing the "No" button, which will lead to no save being made). The only problem I have is the one-time loop I get when a user selects "Yes" answer: the same message box re-appears (apparently, because the procedure goes through the code line again!).
I would appreciate if you could suggest me the way I could avoid this loop.
If you are not going to allow the user not to save then why not force a save. You can replace the entire message box prompt section:
myMessage = MsgBox("Do you want to save and close this file?", vbQuestion + vbYesNo, "Workbook 1")
If myMessage = vbYes Then
Application.DisplayFormulaBar = True
ThisWorkbook.Close True
ElseIf myMessage = vbNo Then
Cancel = True
Else
'nothing
End If
with
ThisWorkbook.Save
This will force the save and close the workbook.

How to detect if user select cancel InputBox VBA Excel

I have an input box asking user to enter a date. How do I let the program know to stop if the user click cancel or close the input dialog instead of press okay.
Something like
if str=vbCancel then exit sub
Currently, user can hit OK or Cancel but the program still runs
str = InputBox(Prompt:="Enter Date MM/DD/YYY", _
Title:="Date Confirmation", Default:=Date)
If the user clicks Cancel, a zero-length string is returned. You can't differentiate this from entering an empty string. You can however make your own custom InputBox class...
EDIT to properly differentiate between empty string and cancel, according to this answer.
Your example
Private Sub test()
Dim result As String
result = InputBox("Enter Date MM/DD/YYY", "Date Confirmation", Now)
If StrPtr(result) = 0 Then
MsgBox ("User canceled!")
ElseIf result = vbNullString Then
MsgBox ("User didn't enter anything!")
Else
MsgBox ("User entered " & result)
End If
End Sub
Would tell the user they canceled when they delete the default string, or they click cancel.
See http://msdn.microsoft.com/en-us/library/6z0ak68w(v=vs.90).aspx
Following example uses InputBox method to validate user entry to unhide sheets:
Important thing here is to use wrap InputBox variable inside StrPtr so it could be compared to '0' when user chose to click 'x' icon on the InputBox.
Sub unhidesheet()
Dim ws As Worksheet
Dim pw As String
pw = InputBox("Enter Password to Unhide Sheets:", "Unhide Data Sheets")
If StrPtr(pw) = 0 Then
Exit Sub
ElseIf pw = NullString Then
Exit Sub
ElseIf pw = 123456 Then
For Each ws In ThisWorkbook.Worksheets
ws.Visible = xlSheetVisible
Next
End If
End Sub
The solution above does not work in all InputBox-Cancel cases. Most notably, it does not work if you have to InputBox a Range.
For example, try the following InputBox for defining a custom range ('sRange', type:=8, requires Set + Application.InputBox) and you will get an error upon pressing Cancel:
Sub Cancel_Handler_WRONG()
Set sRange = Application.InputBox("Input custom range", _
"Cancel-press test", Selection.Address, Type:=8)
If StrPtr(sRange) = 0 Then 'I also tried with sRange.address and vbNullString
MsgBox ("Cancel pressed!")
Exit Sub
End If
MsgBox ("Your custom range is " & sRange.Address)
End Sub
The only thing that works, in this case, is an "On Error GoTo ErrorHandler" statement before the InputBox + ErrorHandler at the end:
Sub Cancel_Handler_OK()
On Error GoTo ErrorHandler
Set sRange = Application.InputBox("Input custom range", _
"Cancel-press test", Selection.Address, Type:=8)
MsgBox ("Your custom range is " & sRange.Address)
Exit Sub
ErrorHandler:
MsgBox ("Cancel pressed")
End Sub
So, the question is how to detect either an error or StrPtr()=0 with an If statement?
If your input box is an array, it does not work. I have solved it by adding a check for if it is an array first.
Dim MyArrayCheck As String
Dim MyPlateMapArray as variant
MyPlateMapArray = Application.InputBox("Select ....", Type:=8)
MyArrayCheck = IsArray(MyPlateMapArray)
If MyArrayCheck = "False" Then
Exit Sub
End If
I have solved it with a False like below
MyLLOQ = Application.InputBox("Type the LLOQ number...", Title:="LLOQ to be inserted in colored cells.", Type:=1)
If MyLLOQ = False Then Exit Sub
If user click cancel the sub will exit.
Another suggestion.
Create a message box when inputbox return null value. Example:
Dim PrC as string = MsgBox( _
"No data provided, do you want to cancel?", vbYesNo+vbQuestion, "Cancel?")
Sub TestInputBox()
Dim text As String
text = InputBox("Type some text")
If text = "" Then
MsgBox "button cancel pressed or nothing typed"
Else
MsgBox text
End If
End Sub
Inputbox send a boolean False value when Cancel is pressed.
contenidoy = Application.InputBox("Cantidad = ", titulox, contenidox, , , , , Type:=1)
'ESC or CANCEL
If contenidoy = False Then
MsgBox "Cancelado"
Else
MsgBox "EdiciĆ³n aceptada"
'End If

Resources