Excel VBA - Sorting With Protected Row and Column - vba

I'm an average/intermediate VBA developer, mostly able to modify existing code and re-use code for expanding Excel projects.
We ran into a situation where someone recorded some Macro's in Excel 2013 but they won't work in Excel 2003. They HAVE to work in Excel 2003 due to the legacy nature of the machine this sheet will be primary on.
So, I did some research and re-wrote the code for the Macros so it would on 2003. However, of the 4 worksheets in this workbook, it only worked on the first page. It drove me crazy trying to figure out why. Finally noticed that on the other 3 worksheets, the first column and row are PROTECTED. If I unprotect them, the re-written Macros work.
So need a little advice on how to make these re-written macros work with the first row and column protected.
This is a sample of the Macro (there are multiple ones like this with just range differences):
Sub KA24()
' Had to Convert Macro to work with the older version of Excel 2003 in the
shop - BW - 8/31/2017
Dim Ws As Worksheet
Set Ws = Worksheets("24 GA KY")
Application.ScreenUpdating = False
Ws.Range("D2:J9").Sort Key1:=Ws.Range("G2"), Order1:=xlAscending,
Header:=xlNo, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom,
DataOption1:=xlSortNormal
Application.ScreenUpdating = True
End Sub

You can unprotect the Worksheet for use in your VBA code using the UserInterFaceOnly method. This assumes your sheet is password protected with the password "Something", if not just leave out the password part.
Dim Ws As Worksheet
Set Ws = Worksheets("24 GA KY")
Ws.Protect Password:="Something", UserInterFaceOnly:=True
...

Related

Excel macro modification ( or maybe VBA ) to update the last included worksheet

Situation
Trying to copy a range of cells that include formulas from worksheet called "Sheet1" to the rest of other worksheets I found that I could do it performing "Fill Across Worksheets". It worked fine, so my next step was to record a Macro for it to be more efficient and worked just fine too.
The Problem
The problem is that when I include a new worksheet and run the Macro, the Macro does not consider the new worksheet so this last worksheet doesn't get updated.
I am including below the code created by the macro. In it I can see that it's including only the worksheets I have now in the workbook, so this is where I need help.
( My excel is in Spanish so when you read Ctrl+Mayus+Q, Mayus means Shiftkey )
Help
What I need is a way to modify this Macro so when it runs it will check and update all worksheets. Or, maybe it's because a Macro can't do this I may need a VBA code ? If this VBA is the way to resolve it, can you help me here with this ?
I appreciate all help
Thank you
Javier
Sub Macro2()
'
' Macro2 Macro
'
' Acceso directo: Ctrl+Mayús+Q
'
Range("A5:D12").Select
Sheets(Array("Sheet1", "Sheet2", "Sheet3", "Sheet4")).Select
Sheets("Sheet1").Activate
ActiveWindow.SelectedSheets.FillAcrossSheets Range:=Selection,
Type:=xlAll
Sheets("Sheet1").Select
End Sub
This is a work around, concerning that you want all the worksheets to have the value of the first worksheet in range A5:D12:
Sub TestMe()
Dim ws As Worksheet
Dim selAddress As String
selAddress = "A5:D12"
For Each ws In Worksheets
'ws.Range(selAddress).Value2 = Worksheets(1).Range(selAddress).Value2
ws.Range(selAddress).Formula = Worksheets(1).Range(selAddress).Formula
Next ws
End Sub
See How to avoid using Select in Excel VBA.

Unable to paste into a protected worksheet using VBA, but can do it manually

I have written a macro that should copy a range of data from one workbook into another. The sheet in the other workbook is password protected, but if I copy and past manually, it allows me to do so. However, when I try and write this into my macro, it won't allow the paste.
Code is currently as follows:
Sub COPYT()
'
' COPYT Macro
Range("B2:U109").Select
Selection.Copy
Workbooks.Open Filename:= _
"_FileName_.xls"
Windows("_FileName_.xls").Activate
Range("H10").Paste
End Sub
When I run the macro as is, I get a
Run-time error '438': "Object doesn't support this property or method"
and the debugger shows that the issue is with the last line Range("H10").Paste
I can't unprotect the sheet (compliance), and I can obviously get round this by just running the macro and then CTRL+V but (as this allows me to paste....), but I would rather that this was automated. Do I need a different syntax for the paste command due to the sheet being protected?
Thanks
Paste is a method of the worksheet, not range. Try this. I have assumed sheet references but you may need to adjust.
Sub COPYT()
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:="_FileName_.xls")
wb.Sheets("compliance").unprotect
ThisWorkbook.Sheets(1).Range("B2:U109").Copy wb.Sheets("compliance").Range("H10")
wb.Sheets("compliance").protect
End Sub

VBA - Does Worksheet.Select not longer have (replace) argument?

I've tried using the following code to select all Worksheets in the Workbook:
Public Sub selectAllWS()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
ws.Select False
Next
End Sub
However, this doesn't seem to work -- it doesn't select multiple Worksheets.
(Sidenote: I know I can use Sheets(Array("Sheet1", "Sheet2", "Sheet3")).Select. I don't want to do this -- I'm experimenting if I can select Sheets across multiple Workbooks.
I'm running the latest version of Excel 2016.
This is a way you could accomplish this, and this does use the Worksheets(Array:
Workbooks("Book.xlsx").Activate
Workbooks("Book.xlsx").Worksheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
Workbooks("Book1.xlsx").Activate
Workbooks("Book1.xlsx").Worksheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
side note:
As asked in the comments I am unsure why you would do this, especially since using .Select is not the proper coding way in VBA.

Row level security in Excel - what approach should I use:

Morning folks,
Over the last couple of days I have been trying to find a way of implementing "pseudo" row level security in Excel using VBA macros.
What I require is to filter all of my Excel table based on the Windows user credentials. The problem is that I am not sure how to tackle this issue and this is the only idea I have so far:
1.Derive the NT account and store it in namedrange
2. Use autofilter based on NamedRange for each table in my spreadsheet
3. Delete / Hide the unnecessary rows ?
Example:
Perhaps, there are other ways which are more suitable for my scenario, however I havent been able to find them.
If you could point me into the right direction, I would appreciate it.
Thanks
This can be achieved by pasting the following into the ThisWorkBook Module in your specific WorkBook VBA project. Just remember to save the WorkBook as a .dotm
As mentioned by J.Chomel bypassing WorkBook passwords is not the hardest thing to do and you could find a macro to do that on the net.
Obviously you will need to password protect your VBA project as well to prevent users from accessing the WorkBook password from there.
Private Sub Workbook_Open()
Dim CurrentUserName As String
CurrentUserName = Environ("Username")
Dim WorkBookPassword As String
'Replace password with your desired password
WorkBookPassword = "password"
Dim DataWS1 As Worksheet
'Replace Sheet1 with your specific sheet name
Set DataWS1 = ThisWorkbook.Sheets("Sheet1")
With DataWS1
.Unprotect WorkBookPassword
If .AutoFilterMode Then .AutoFilterMode = False
.UsedRange.AutoFilter Field:=3, Criteria1:=CurrentUserName
.Protect Contents:=True, _
AllowFiltering:=False, _
UserInterfaceOnly:=True, _
Password:=WorkBookPassword
End With
End Sub
To implement row level security in Excel, you should avoid retrieving the data in Excel in the first place. Because if you use vba to filter, it will easily be bypassed by some users. So it could not be called security.

Paste after unprotecting worksheet not working

I have two sheets "Request" and "Changes" both protected by same password. Password has been stored as a constant in another module. I have tested this code when "Changes" sheet in unprotected and it works, however for some reason, if I have to unprotect the sheet before pasting it won't paste.
I am simplifying trying to keep a record of what was deleted in the workbook by placing the info in a protected sheet "Changes" that is hidden.
Sub PODelete()
Dim rng As Range, ws As Worksheet, ws1 As Worksheet, lr As Integer
Set ws = Sheets("Request")
Set ws1 = Sheets("Changes")
lr = ws1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row 'Last non-blank row for column A
On Error Resume Next
Set rng = Application.InputBox("Select a range", Type:=8)
If Not rng Is Nothing Then
' Checks to see if column A is selected
If rng.Cells.Column = 1 Then
' Checks to see that only 1 cell is selected
If rng.Cells.Count > 1 Then
MsgBox "Select only one P.O. Number to remove"
Else
' Select entire row
rng.EntireRow.Copy
' Activate sheet and pastes values
Sheets("Changes").Activate
ws1.Unprotect Password:=worksheetpassword
Cells(lr, 1).EntireRow.Select
Selection.PasteSpecial Paste:=xlPasteValues
ws1.Protect Password:=worksheetpassword, DrawingObjects:=True, Contents:=True, Scenarios:=True
' Deletes range
ws.Activate
ws.Unprotect Password:=worksheetpassword
rng.EntireRow.Delete
ws.Protect Password:=worksheetpassword, DrawingObjects:=True, Contents:=True, Scenarios:=True
End If
Else
MsgBox "Select P.O. Number to remove"
End If
Else
Exit Sub
End If
End Sub
Once again, if I run this macro with the "Changes" sheet unlocked it will work.
The real answer to this is actually not to unprotect the Worksheet at all. Protect it with a different password that isn't stored in the file anywhere, but set the parameter UserInterfaceOnly:=True. This will allow the macro to make changes to the worksheet, and even if the user find the hidden sheet they won't be able to find the password.
Speaking of hiding it, you should really hide it. As far as I know this is only possible through VBA, but you can set the Worksheet to xlSheetVeryHidden, either through the VBE...
...or in code:
Worksheets("Changes").Visible = xlSheetVeryHidden
Then password protect the VBA project with the same password as the Worksheet, and nobody is going to find it but you unless they know the name of the sheet and manually type it into a cell formula:
=Changes!A1
If you want to avoid that possibility, just name the Worksheet something non-obvious or even total gibberish. The likelihood of an unsuspecting user typing this into a cell...
=kusidkeshlkiehas!A1
...is virtually zero.
I have found that occasionally doing an Unprotect on the active sheet will change the active sheet to a different sheet. I haven’t figured out under what circumstances this occurs or why the particular sheet that ends up selected gets selected. Could this be your problem? I solved this problem by having one routine that is called to do all Unprotects. In that routine I save the active sheet name before doing the Unprotect and then re-select the saved sheet. I haven't seen this problem with Protecting a sheet but just to be safeI have done the same thing with a Protect routine.
I tried to copy a range from one work book(selection.copy only once and keeping the workbook open) and through "for loop", to many other work books(ActiveSheet.Unprotect "password", ActiveSheet.Paste).
This works fine during 1st trial but fails during subsequent trials on the same file with a message "Error 1004 Paste Method of Worksheet Failed" suggested by Mr Darrel Dixon and various other solutions of "UserInterfaceOnly:=True" etc but the error is repeating. The sheet appears UNPROTECTED at that stage and copy from source workbook and paste into destination workbook MANUALLY works fine but through VBA macro, it fails.
Finally, I tried repeating "selection.copy" from source workbook after "ActiveSheet.Unprotect" on each destination workbook/each iteration of for loop.
Even though this appears to be inefficient code, this alone solved the problem of PASTE failure after UNPROTECTING a worksheet.