How do I lock cells containing formulas but still allow macros to work? - vba

I have a worksheet that I make my employees fill out, and I have calculated cells that I want to lock so they cannot change them. I have selected the cells and selected properties and ensured that the "lock" checkbox is checked. When I protected the worksheet/workbook the "export to csv" macro button stopped working. In order to enable the macro to be completed I inserted this VB code into the Workbook:
Private Sub Workbook_Open()
Dim wSheet As Worksheet
For Each wSheet In Worksheets
wSheet.Protect Password:="password", _
UserInterFaceOnly:=True
Next wSheet
End Sub
This worked but had the unintended side effect of allowing my locked formulas to be able to be edited even though they were locked. Only cells containing non-formula values remained locked. What is the proper way to allow macros but still lock formula cells?

My solution was to lock the entire workbook and worksheets, then code into the VB button the disabling of the lock then the re-enabling the macro. Like so:
Sub MyMacro()
Sheet1.Unprotect Password:="password"
'insert code here
Sheet1.Protect Password:="password"
End Sub
I then deleted my Workbook_Open code.

Related

Activating a different worksheet using VBA does not change the focus on it permanently

I want to select and modify different worksheets programmatically every time the workbook is saved. At the end however, I want to set the focus on a particular worksheet so that the workbook is saved with that particular worksheet in focus. What I'm noticing is that whenever the code executes it activates the worksheets, modifies them but at the end it goes back to the worksheet that I had selected before running the code.
Here's my code:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Sheets(1).Activate
Debug.Print Sheets(1).Name
End Sub
The code above is executed in an empty, local workbook with 2 empty worksheets
Sheet1 and Sheet2. Whenever I save the workbook with Sheet2 selected, I see that it is indeed activated because the console log prints Sheet1, in the workbook however, the selected worksheet remains Sheet2.I'm using SAP's BusinessObjects Analysis but as noted above, the workbook is a local macro-enabled workbook that is not saved on the SAP NetWeaver platform.
Is it possible for me to permanetly set the focus to a different worksheet so that it's visible in the workbook?
Thanks
EDIT:
Oh no!!! I have the annoying problem of inconsistent behavior with the different save buttons once again and that is yet to be resolved! I just realized that if I save through the workbook save button the sheet permanently changes, however when I save through the code editor it doesn't. The previous problem I had experienced was on workbooks saved on SAP NetWeaver where VBA code is not executed through the workbook save button but is, through the code editor save button. I guess I will have to log an Oss with SAP for this inconsistency.
What you are saying is only possible, if someone has written:
Private Sub Worksheet_Activate()
Sheets(2).Activate
End Sub
At Worksheets(1).
Otherwise, the code you are using:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Sheets(1).Activate
Debug.Print Sheets(1).Name
End Sub
should activate the first Sheet and it should not be changed later.
I have no idea where Sheet2 is compared to Sheet1.
You say
The code (above) is executed in an empty, local workbook with 2 empty
worksheets Sheet1 and Sheet2. Whenever I save the workbook with
Sheet2 selected, I see that it is indeed activated because the console
log prints Sheet1, in the workbook however, the selected worksheet
remains Sheet2
Your code doesn't do anything to a sheet called Sheet2. It only looks at the first sheet in the tab order - the sheet could be called anything.
It activates the first sheet and then puts the name of the first sheet in the immediate window.
This code will select the sheet with the tab name Sheet2, it will then put the name of the activesheet (Sheet2) in cell A1 of the sheet with the tab name Sheet1.
Finally it selects the sheet with the codename Sheet3 (The codename is the name not in brackets in the Project Explorer).
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
With ThisWorkbook
.Worksheets("Sheet2").Select
.Worksheets("Sheet1").Range("A1") = ActiveSheet.Name
End With
Sheet3.Select
End Sub
Just use following code:
Sub activateSheet(sheetname As String)
'activates sheet of specific name you want.
Worksheets(sheetname).Activate
End Sub
then for select another sheet:
Sub activateSheet(sheetname As String)
'selects sheet of specific name you want.
Sheets(sheetname).Select
End Sub
Regards
Xsi

How to make vba code to run auto-close only on active workbook?

Here's the scenario. I have multiple excel workbooks that copy and paste data among each other. So the macro works to open.copy.close from one workbook then open.paste.close to another. I am working on creating a function to auto run macro when file is closed.
Here's the issue, when I click macro button in workbook 1, it is supposed to open.copy.close from workbook 2. However, because of the auto run when file is closed function in workbook 2, an error will occur (2 macros cannot run at the same time)Any solution for this? I am looking for a solution to only auto run macro when file is closed IF IT IS AN ACTIVE WORKBOOK. Here is what I have now:
Workbook 1
Sub workbook_beforeclose(cancel As Boolean)
Application.Run "Sheet1.UpdateYellowTabs_Click"
End Sub
Workbook 2
Sub Workbook_BeforeClose(Cancel As Boolean)
Workbook.BeforeClose
Application.Run "Sheet12.UpdateGreen_Click"
End Sub
How do I code it in the workbook code to only make this run only when it's active/closed by a human user and not when open/close by macro?
Thanks!
Well I am not sure to understand your final goal from this, but I can answer the "technical" question. Technically, if you want to check if a given workbook is active: If Application.ActiveWorkbook Is Me,
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Not Application.ActiveWorkbook Is Me Then Exit Sub ' <-- add this test
''''''''''''''''''''''''''
' Whatever code goes here
''''''''''''''''''''''''''
End Sub
EDIT
But problem is that invoking wb2.close will make the workbook wb2 the "active" one during the execution of the macro. So this method won't work. Another method is to disable events before closing the workbook; so that the event Workbook_BeforeClose will not fire. After that, you can enable events back if needed. The code looks like this:
' ... open wb2 and do the work with it
Application.EnableEvents = False
wb2.Close False
Application.EnableEvents = True
notice, if you had already disabled events at the beginning of the current macro, which is usually recommended, then this additional code wouldn't be needed.

Protected Excel workbook broken after pasting data from a "newer" workbook

Given an excel workbook with an unlocked cell in a protected worksheet.
If I copy a cell from another workbook which was opened after target workbook, and paste it to the unlocked cell, it becomes locked and I can't do anything with it except undo the paste action.
On the other hand, if source workbook was opened before the target, copy-paste works as expected - target cell remains editable.
I've reproduced this on excel 2007 and 2010.
What am I asking is to reproduce the problem and advise how to handle this issue with VBA to avoid locking cells by users.
Following #Jeeped advise, I wrote this script and it works:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Sh.Unprotect Password:="pwd"
Target.Locked = False
Sh.Protect Password:="pwd"
End Sub
But there's a side effect. Undo cache will be cleared each time worksheet changes.

How do you run macros upon opening Excel workbook, then re-protect after finished running?

Is there a way to first, unprotect a workbook at the beginning of opening, run all the workbook_open() macros and then re-protect the workbook so that a common user can not change anything on any worksheets? I'd like to prevent the common user from changing anything but allow the macros to do its auto-update and computations.
Any suggestions? Is this even feasible?
What I think you're looking for is the Worksheet.Protect method.
At the beginning of your Workbook_Open event, place this code:
ThisWorkbook.Sheets("SheetYouWantToUnprotect").Unprotect _ Password:="TheSheetPassword"
Then at the end of your Workbook_Open event code, you want to protect the sheet again, so place this code:
ThisWorkbook.Sheets("SheetYouWantToProtect").Protect _
Password:="SheetPassword"
Of course, you can do this with more than one sheet if multiple sheets need to be unprotected. If each sheet has the same password, place a simple loop at the beginning of your Open event:
Dim sht as Worksheet
For Each sht in Thisworkbook.Sheets
sht.Unprotect Password:="YourPassword"
Next sht
At the end of your code you can use the same loop to protect the sheets, just change .Unprotect to .Protect.
Or, if there are many different passwords (aside from recommending you change them all to one password), you can place as many instances of the first line of code I mentioned as it takes to unprotect the necessary sheets.
Note: There are many more optional arguments to the .Protect method which I did not cover, but you can find an exhaustive list here.
EDIT: Here's more info on the Unprotect method.
Yes, it can be done
Private Sub Workbook_Open()
Dim WS As Worksheet
For Each WS In ThisWorkbook.Sheets
WS.Unprotect Password:="YourPassword"
WS.Protect Password:="YourPassword", UserInterfaceOnly:=True
Next WS
End Sub
The UserInterfaceOnly:=True allows VBA to act on any part of your worksheets while the common user can only interact with "unlocked" cells.

VBA seems to disappear after I protect a range of cells

Hi I can't seem to get my head around this problem:
After I lock a range of cells A1:U1 (and all other cells are unlocked) and I then protect the worksheet - the VBA in the worksheet doesn't appear to work anymore - is there any way around this??
Thanks,
Kieran
If the VBA changes cells that you have locked then you need to update the VBA to unlock the worksheet before running the rest of the code. Then complete the Sub by locking the worksheet.
'Add to beginning of the Sub
Sheets("worksheet_name").Unprotect Password:="password"
'Add to end of the Sub
Sheets("worksheet_name").Protect Password:="password"