I have an .xlsm file which i want to run the macro automatically when i open it. The current file is saving the file as .xls in a different location with a different name before saving and before closing. However before closing is giving me error and so is the autorun of macro. Here is my code.
Private Sub Workbook_Open()
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.ScreenUpdating = False
Application.DisplayAlerts = False ' so you can overwrite without warning
ActiveWorkbook.SaveCopyAs "C:\Users\name\Desktop\testing.xls"
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ScreenUpdating = False
Application.DisplayAlerts = False ' so you can overwrite without warning
ActiveWorkbook.SaveCopyAs "C:\Users\name\Desktop\testing.xls"
Application.DisplayAlerts = True
Application.ScreenUpdating = True
ActiveWorkbook.save
End Sub
End Sub
For starters, you can't have events inside another event like that. You have a Workbook_BeforeSave and Workbook_BeforeClose inside your Workbook_Open... That won't work, and in any case I'm not sure what it would even mean!
Private Sub Workbook_Open()
' This won't work:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'...
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'...
End Sub
End Sub
You need to set up your events separately, like this:
Private Sub Workbook_Open()
'Stuff to do when file opens...
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Stuff to do before user saves the file...
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'Stuff to do before the user closes the file...
End Sub
Also, instead of ActiveWorkbook, consider using Me (or ThisWorkbook) to avoid any ambiguity.
Related
This clearly shows that value of cancel is true, and still my workbook closes after this! Why?
I want to cancel closing of the excel file if user input is incorrect.
I debug the code and found out that the value of Cancel was initially False, and it becomes True. But once the Sub ends, file is still closed.
(variable error is defined at workbook declaration space, so accessible within module.)
Private Sub Workbook_BeforeClose(Cancel As Boolean)
error = 0
check_for_error
If error = 1 Then
Cancel = True
Exit Sub
End If
Application.EnableEvents = False
Sheet1.Cells.ClearContents
Sheet2.Cells.Clear
Application.EnableEvents = True
End Sub
I want to cancel closing of file if error = 1.
Update:: Thanks everyone for the responses, but nothing seems to work for me! Following is how my current code looks.
Option Explicit
Dim errYes As Byte
Private Sub Workbook_BeforeClose(Cancel As Boolean)
check_freeze_panel
If errYes = 1 Then
Cancel = True
Exit Sub
End If
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
End Sub
errYes is returning 1, Cancel = True is being executed, and still my workbook closes.
I even tried commenting all the code, and just putting Cancel = True as suggested and guess what, it still closes!
Change the name of error this is a reserved word for an already existing function (see Error function) and must not be used as a variable name. And activate Option Explicit and declare all your variables.
Here is an example how you would do it correctly:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim ErrorsFound As Boolean
ErrorsFound = check_for_error
If ErrorsFound Then
Cancel = True
Exit Sub
End If
Application.EnableEvents = False
Sheet1.Cells.ClearContents
Sheet2.Cells.Clear
Application.EnableEvents = True
End Sub
Function check_for_error() As Boolean
'check and return
check_for_error = True 'errors found
End Function
Or even shorter:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Cancel = check_for_error
If Not Cancel Then
Application.EnableEvents = False
Sheet1.Cells.ClearContents
Sheet2.Cells.Clear
Application.EnableEvents = True
End If
End Sub
Function check_for_error() As Boolean
'check and return
check_for_error = True 'errors found
End Function
Try this. Set Error equal to your function call and make sure it returns the right data type.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
error = check_for_error
If error = 1 Then
Cancel = True
Exit Sub
End If
Application.EnableEvents = False
Sheet1.Cells.ClearContents
Sheet2.Cells.Clear
Application.EnableEvents = True
End Sub
Initially Cancel is equal False, means File Close will succeed.
For me the below code works fine. When I set error = 1 then closing is cancelled whether you use "Exit Sub" or not. When I set error <> 1 then cls
When I test your Code:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim error As Integer
error = 1
If error = 1 Then
Cancel = True
'Exit Sub
End If
End Sub
Just test this:
Write False and workbook should Close, and True should "stop" the closing.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Cancel = False
End Sub
I've hijacked saving in an excel file for the purposes of preventing unintended overwrites of a file in an odd environment.
The Workbook_BeforeSave and the Workbook_BeforeClose events work perfectly on their own. Unfortunately, the way the code is currently structured, I would need to call the BeforeSave event from within the BeforeClose event.
In the most basic form, the following code will not do as I'd like. In the following example, wksHiddenWorksheet.Visible = True will not make wksHiddenWorksheet visible if the save is called from within the BeforeClose event.
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
wksHiddenWorksheet.Visible = True
End Sub
Is there any way around this? Is it poor practise (or even fundamentally incorrect) to call an event from inside another event in the way that I'm attempting?
Update:
I have played around with Application.EnableEvents in the workbook, but I've made sure it always reverts back to True in error handling.
I've opened a brand new workbook and entered the following code
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Debug.Print Application.EnableEvents 'Prints TRUE
ThisWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'The workbook consists of two sheets. Sheet1 and Sheet2
Sheet1.Visible = xlSheetHidden
Debug.Print Sheet1.Visible 'Prints -1 (xlSheetVisible)
End Sub
The Visible sheet does not become hidden, though the line is triggered if I go line by line through the code. If I enter code such as a MsgBox in the same space, the MsgBox will open as normal.
Update 2:
To answer everyone's questions and display exactly what happens, please see the below code:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'The workbook consists of two sheets. Sheet1 and Sheet2
Debug.Print Application.EnableEvents 'Prints TRUE
Debug.Print Sheet1.Visible 'Prints -1 (xlSheetVisible)
Sheet1.Visible = xlSheetHidden
Sheet1.Visible = False 'Same thing
Debug.Print Sheet1.Visible 'Prints 0 (xlSheetHidden)
Sheet1.Visible = xlSheetVisible
Sheet1.Visible = True 'Same thing
Debug.Print Sheet1.Visible 'Prints -1 (xlSheetVisible)
ThisWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Debug.Print Sheet1.Visible 'Prints -1 (xlSheetVisible)
Sheet1.Visible = xlSheetHidden
Sheet1.Visible = False 'Same thing
'Sheet1 should now be hidden, but it's not
Debug.Print Sheet1.Visible 'Prints -1 (xlSheetVisible)
End Sub
Hiding and unhiding sheets works perfectly in the first event, but as soon as the second event is triggered, the sheet visibility does not change.
Update 3:
Another point. If I enter the Workbook_BeforeSave() event directly (by saving), rather than entering it from the Workbook_BeforeClose() event, then everything works as expected.
MUCH LATER UPDATE:
Although I marked this question as solved a while ago, I've come across an article that helps to explain the behaviour. An explanation can be found at:
http://www.cpearson.com/excel/events.aspx
edited after all clarifications
the following code worked for me
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Workbook_BeforeSave False, True
ThisWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Cancel Then Sheet1.Visible = xlSheetHidden
End Sub
hard to tell why though...
In this example procedure HideSheet is called from BeforeSave and from BeforeClose event handler. So both handlers hide the sheet. HTH
Private Sub Workbook_BeforeClose(Cancel As Boolean)
HideSheet Sheet1
ThisWorkbook.Save
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
HideSheet Sheet1
End Sub
Private Sub HideSheet(wks As Worksheet)
wks.Visible = xlSheetHidden
End Sub
I have this code that disable the close [x] function of excel. after completed enter ID, I need to enable again the button.
I have this part that disable the [x],
Public FlagToClose As Boolean
Sub Enter_1()
FlagToClose = False
'code
'.....................
FlagToClose = True
End Sub
for the workbook module I have this,
Private Sub Workbook_Open()
FlagToClose = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not FlagToClose Then Cancel = True
End Sub
then how to enable again the close[x] function?
To re-enable closing, run this short macro before closing:
Sub ev_off()
Application.EnableEvents = False
End Sub
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 using Workbook_BeforeSave to update some cells on a locked sheet in excel 2010. The subroutine works as desired when using ctrl-s to save, but will not unlock the sheet when using .Save in vba.
ThisWorkbook(code)
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim MyPassword As String
MyPassword = "password"
ActiveWorkbook.Worksheets("Sheet1").Unprotect (MyPassword)
ActiveWorkbook.Worksheets("Sheet1").Range("A1").Value = Now
ActiveWorkbook.Worksheets("Sheet1").Range("A2").Value = ThisWorkbook.BuiltinDocumentProperties("Author")
ActiveWorkbook.Worksheets("Sheet1").Protect (MyPassword)
End Sub
Module1(Code)
Sub SaveMe()
ActiveWorkbook.Save
End Sub
I have a button that calls SaveMe(). SaveMe() saves the document, activating Workbook_BeforeSave. The Worsheet fails to unprotect, causing an error when writing to A1.
The error states:
Run-time error '1004':
Application-defined or object-defined error
This worked for me, but it is not very elegant. I did not find a separate module for both unprotecting and writing worked.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
UnlockWorksheets
With ThisWorkbook.Worksheets("Sheet1")
.Range("A1").Value = Now
.Range("A2").Value = ThisWorkbook.BuiltinDocumentProperties("Author")
End With
LockWorksheets
End Sub
Sub SaveMe()
UnlockWorksheets
ThisWorkbook.Save
LockWorksheets
End Sub
Sub UnlockWorksheets()
ThisWorkbook.Worksheets("Sheet1").Unprotect Password:="password"
End Sub
Sub LockWorksheets()
ThisWorkbook.Worksheets("Sheet1").Protect Password:="password"
End Sub
why not put the 'before save' module into a new sub routine and have the before close call that
EG.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call SomeSub
End Sub
sub someSub()
'Code here
end sub
sub Button()
call SomeCub
activeworkbook.save
end sub