I found this code and it works perfectly. But when I hit close button, dialog is shown "Do you weant to save changes", and if I choose Yes, an error comes up that I don't have a value in a cell A. And then my file is automatically closed.
How to prevent this, and to stay in the document?
My code is:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If ActiveSheet.Range("A1").Value = "" Then
Cancel = True
Response = MsgBox("Please enter a value in A1", vbCritical, "Error!")
End If
End Sub
Have you tried using BeforeClose instead of BeforeSave?
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If ActiveSheet.Range("A1").Value = "" Then
Cancel = True
Response = MsgBox("Please enter a value in A1", vbCritical, "Error!")
End If
End Sub
Regards
Related
I have an odd thing (I think) but probably doing something incorrectly here. I am trying to force the user to enter in certain information in excel. The msgbox comes up with the OK/Cancel buttons but when either is selected the workbook saves and exits. If they cancel then I want it to sit on the cell where the issue is. Any help would be appreciated
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'---------------------------
'-- Missing Employee Name --
'---------------------------
If Cells(5, 2).Value = Empty Then
If Not MsgBox("Employee Name missing! Pressing OK will exit without saving.", vbOKCancel, "The Mill") = vbOK Then
With Sheets("sheet1")
.Activate
.Cells(5, 2).Activate
End With
Cancel = True
Exit Sub
End If
End If
End Sub
I think the problem is that you aren't handling Workbook_BeforeClose, which triggers as you try to close the workbook.
So while the save is canceled, the close is not.
Moving everything to Workbook_BeforeClose and handling it there kind of works, until the user saves manually. So you will still have to handle that in the before save event.
This is an example:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Cells(5, 2).Value = Empty Then
If MsgBox("Employee Name missing! Pressing OK will exit without saving.", vbOKCancel, "The Mill") = vbOK Then
Application.DisplayAlerts = False
Application.Quit
Else
Sheets("Sheet1").Cells(5, 2).Activate
Cancel = True
End If
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Cells(5, 2).Value = Empty Then
Cancel = True
MsgBox "Employee Name missing!"
Sheets("Sheet1").Cells(5, 2).Activate
End If
End Sub
The only caveat I have seen, is that Application.DisplayAlerts = False will affect other open workbooks.
I want to keep a variable from Form to Workbook Events, it works from Form to Module, but doesn't work from Form to Workbook Event, the Variable "Salvar" stay as "Empty" rather than "True"...
'WorkBook Event
Public Salvar As Boolean
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
UserForm_Salvar.Show 'Calls "Private Sub Botao_Salvar_Click()"
If SaveAsUI = True Then
If Salvar = True Then
Cancel = False
Salvar = False
Else
Cancel = True
End If
End If
End Sub
'UserForm
Private Sub Botao_Salvar_Click()
Dim PassWord As Variant
PassWord = Senha_TextBox
If PassWord = 123 Then
Unload UserForm_Salvar
Salvar = True
End If
End Sub 'Go back to "Workbook_BeforeSave"
You don't really need a global variable if you declare the form as an object, which is the better practice anyway, and then handle it correctly. Use any of the form's properties or the form's controls' properties to convey the message. I recommend to use the Tag property. Here is the code in the worksheet's module. Observe that I named the form FrmSalvar.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
' 091
Dim Form As FrmSalvar
If SaveAsUI = True Then
Set Form = New FrmSalvar ' create a new instance of the form
With Form
.Show ' the Form takes control
' code resumes here with Form hidden but still in memory
Cancel = (Val(.Tag) <> True) ' True = -1
End With
Unload Form ' only now the form is destroyed
Set Form = Nothing
End If
End Sub
and the code in the Form's code sheet.
Private Sub Botao_Salver_Click()
' 091
Dim PassWord As String ' Textboxes handle text = strings
PassWord = Senha_TextBox.Value ' this is a string, even if numeric
If PassWord = "123" Then
Me.Tag = -1 ' write something to the Tag property
Else
MsgBox "The password is incorrect", vbInformation, "Access denied"
End If
Me.Hide ' hide the form
End Sub
The line Cancel = (Val(.Tag) <> True) in the BeforeSave procedure will crash if the user closed the form using the X button. This is because that button effectively unloads the form before your code can do it. In your system, that action should be paramount to "no password". Therefore this code will remedy the situation.
On Error Resume Next
Cancel = (Val(.Tag) <> True)
If Err.Number Then Cancel = True
That's a more dignified exit than gathering your skirts and fleeing the scene in panic. However, there is also a method by which you can simply not allow the form to be closed that way. I use the two event procedures below in most of my forms.
Private Sub CmdCancel_Click()
' 091
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' 091
Cancel = (CloseMode <> vbFormCode)
If Cancel Then CmdCancel_Click
End Sub
Read up about the QueryClose event here. In its above incarnation it just cancels what the user pressed and suggests alternative code which could be simply Me.Hide. I have Me.Hide in the procedure that responds to the Cancel button on my form and I rather invoke that procedure than allowing a second cancel exit from the form in my code. In this way there are just two exits from my form, with OK or with Cancel. Pressing the X is handled in the same way as when Cancel was pressed. Either way, the Me.Tag is preserved until the bitter end.
Change the value of Salvar before Unloading the UserForm.
If PassWord = 123 Then
Salvar = True
Unload UserForm_Salvar
End If
I have this code, that refuses and cancels to save a workbook if a cell contains a specific text. the code is working fine, but if i want it to refuse saving if some cells in a range contains specific text then it is not working. my code below that is working:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Sheets("Sheet1").Range("A1").Value = "Fill in a comment" Then
Cancel = True
Response = MsgBox("Fill in a comment", vbCritical, "Error!")
End If
End Sub
the code that i tried to make it work but its not
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean
For Each c In Sheet1.Range("A1:A5000")
If c.Value = "Fill in a comment" Then
Cancel = True
Response = MsgBox("Fill in a comment", vbCritical, "Error!")
End If
Next
End Sub
do you guys have any ideas?
Try this instead rather than looping:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Cancel = Not Sheet1.Range("A1:A5000").Find("Fill in a comment") Is Nothing
If Cancel Then MsgBox "Fill in a comment", vbCritical, "Error!"
End Sub
It uses the .Find() method to look for "Fill in a comment" and if it isn't Nothing then Cancel is set to True
Then, we test the value of Cancel to see if we need to display the message box.
Doing it this way also makes sure that you don't get 500 message boxes if you have "Fill in a comment" written in 500 different cells in that range...
This question already has answers here:
Making fields mandatory of a specific sheet on workbook save
(3 answers)
Closed 8 years ago.
I want to call this Sub in the Workbook_BeforeSave event:
Sub test()
If ActiveSheet.Range("A4") = "" Then
MsgBox ("Please fill in cell A4!")
Exit Sub
Else
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
test
End Sub
When I click save the file is saved even if the cell A4 is blank.
You should set Cancel as the proper way to terminate the save event.
It would be better to have test as a function, so you can check the return value, and set cancel appropriately.
Function test() as Boolean
If ActiveSheet.Range("A4") = "" Then
Test = False
Else
Test = True
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If test = False then Cancel=True
End Sub
Also, ActiveSheet is not appropriate, unless you have only one worksheet, and you have protected the workbook from having extra sheets added.
My suggested solution would be to check Sheets("MySheet").Range("A4").
Of course, the laziest way to do the test would be:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
cancel = (ActiveSheet.Range("A4") = "")
End Sub
where the test is done within the save procedure, and no sub tests are required.
Try:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call test
End Sub
Sub test()
If ActiveSheet.Range("A4") = "" Then
MsgBox ("Please fill in cell A4!")
End
End If
End Sub
Exit Sub merely terminates sub test(), while End completely stops code execution, thus preventing Workbook_BeforeSave() from running further.
if cancel is true, the saving will be blocked :
Sub Test(byref cancel as boolean)
If ActiveSheet.Range("A4") = "" Then
MsgBox ("Please fill in cell A4!")
cancel = true
Exit Sub
'Else
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Test Cancel
End Sub
I am running a macro while in Private Sub Workbook_BeforeClose(Cancel As Boolean)
but whenever user clicks on Cancel button macro should not run.
I kept following lines of code
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Cancel = True Then
MsgBox "You clicked on Cancel"
ElseIf Cancel = False Then
Call SDA
End If
End SubBut whenever i press Cancel button it is not showing me any MessageBox.Any help would be appreciated greatly.
Try this please:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim Msg As String
Dim ireply As Integer
If Not Me.Saved Then
Msg = "Do you want to Save this book? "
ireply = MsgBox(Msg, vbQuestion + vbYesNoCancel)
Select Case ireply
Case vbYes
Me.Save
Call SDA
Case vbNo
Me.Saved = True
Case vbCancel
Cancel = True
MsgBox "Cancelling...workbook close event!"
Exit Sub
End Select
End If
End Sub
Output dialogs:
The usual structure of a messagebox cancel event wrap is as follows:
'--Display MessageBox
Dim intMsg as integer
intMsg = MsgBox(strPrompt, vbYesNo, strTitle)
'--Check pressed button
If iRet = vbNo Then
MsgBox "NO!"
Else
MsgBox "Yes!"
End If