I need to be able to sort a protected worksheet that has locked column headers in excel (VBA) - vba

I am working on an excel document at the moment and everything is turning out quite nicely. However, I am coming down to the very last issue that I am having a problem resolving: being able to sort my columns in ascending/descending order while the worksheet is protected and the column headers are locked. I will state some facts about my worksheet first, the goal that I am trying to accomplish, then possible solutions that I have researched and why those solutions do not seem to apply to my situation.
First, I am NOT using an excel table object (just plain
rows/columns).
The top row has AutoFilter applied (to work as column headers).
All of the cells in the worksheet are unlocked, EXCEPT for the
entire first row which is locked (aka, the column headers).
The worksheet will be protected.
I do NOT want users to be able to edit data in the first row (this
is important, these must not be editable no matter what).
For my protected sheet settings, I have "Select locked
cells","Select unlocked cells","Insert rows","Delete rows","Sort",
and "AutoFilter" checked.
I am using VBA for my worksheet.
I am using Excel 2013
Now, assuming the worksheet is protected, users are currently able to use the AutoFilter at the top to actually "filter" the data as intended. The issue is whenever they try to "sort" the data in ascending/descending order that I get an error saying that you must unprotect the sheet first.
After researching I have seen that this is due to the fact that when you sort, the AutoFilter automatically counts the column header as part of the range being sorted... but because this column header (row 1) is locked, it is causing this error. However, this row HAS to be locked, my VBA code specifically reads the values in these column headers and under no circumstances can they be changed.
So filtering works just fine, it is just the sorting I am trying to figure out now. My "ideal" solution would be to somehow capture an event when a user clicks on the AutoFilter arrow and selects "Sort" where I can then, in VBA, unprotect the sheet, sort according to their selection, then protect the sheet again. However, again upon research, it seems that there really isn't an option when it comes to an event for this AutoFilter button (I could be wrong, sometimes it can be confusing reading other's suggestions).
I am hoping someone out there can help me out with this situation, I would also LIKE to avoid using an excel table object, however if it is the only solution that works that meets all my above criteria then so-be-it.
Thanks in advance for your help.

If you already use VBA, you can plug this code into the Sheet module. This assumes the headers are in row 1. Change to suit.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("1:1")) Is Nothing Then
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
End If
End Sub
The sheet now does not need to be protected.

Borrowing a bit from #Teylyn's and adapted it to disallow selection of the header row, when it is selected, it selects the cell below it directly and displays an error message. The code sits in the sheet module, if it needs to be applied to more sheets, it may be better to use Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range), in that case, replace all instances of Me with Sh in the code below.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Me.Range("1:1")) Is Nothing Then
Target.Offset(1, 0).Select
MsgBox "You cannot select or edit the headerrow, please use the autofilter button to sort and filter.", vbCritical, "Invalid Selection"
End If
End Sub
Note
Unlocking the cells which is required for the sorting and then allowing unlocked cells to be selected when protecting the worksheet, which is needed to be able to edit the data, makes the worksheet protection effectively useless.
Also wit the code above, there is still a loophole through which cells can be edited. If you select an allowed cell, drag it to the header row, and choose to replace the data in the cell then the header cell to which the allowed cell was moved is selected and editable.
End of note
Select the data range which needs to be sorted and unlock the cells.
When protecting the worksheet, be sure to allow
sort
autofilter
To prevent users from changing the cell contents, disallow the selection of unlocked cells.

Related

VBA: Mirror a cell to another sheet, then keep the data after deleting the original

Apologies if this has been answered, but I couldn't find any details of this being asked before. I know it's a vague question without code, but just looking for ideas of how to approach this. Writing VBA code on Excel.
I have a sheet, which contains 20+ columns and 8,000+ rows of data. The sheet is password protected / read only as I do not want users editing the data (the sheet is linked to several other macros). Called 'Master Data Sheet'.
I have created a macro that will filter the Master Data table and then paste the filtered results on another sheet (called 'Filtered Results') and combines data with another separate sheet. The user can view and edit this sheet.
However there are two columns that I want the user to put data in that needs to be duplicated/mirrored in the Master Data Sheet (in those specific columns) automatically. Issue I'm having is that the 'Filtered Results' sheet gets deleted after a period of time, but I still need the user input data for those specific columns to be in the Master Data Sheet.
I'm unsure how to get around the issue of the sheet being deleted but data being retained.
An alternative workaround I had would be a copy/paste button the user could click to copy the unformatted data from the Filtered Sheet to Master Data Sheet. However, I was hoping to find a solution that would just automatically update as the user types (in case they forget to click the button etc.)
Thanks for all the help!
EDIT: Code I'm working with right now. Still stuck on linking filtered cells though.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents=False
If Not Intersect (Target, Range("D1:D1000")) Is Nothing Then
Target.Copy Destination:=Worksheets("Master Data
File").Range(Target.Address)
End If
Application.EnableEvents=True
End Sub
You can use the Worksheet_Change event to check if a specific range changed and then copy/update the other sheet. This way you have the copy/paste automatically when the original data changed.
Example:
If you want to copy range A1:A5 into another sheet whenever its values changed:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1:A5")) Is Nothing Then 'range A1:A5 was changed
Target.Copy Destination:=Worksheets("OtherSheet").Range(Target.Address)
End If
End Sub

VBA Excel - How to know if a specific cell is affected by any macro?

I have an excel file with hundreds of macros, where which macro has extensive code.
I need to change the layout of the cells and that includes moving some cells to another location.
My only problem is that after doing that i need to change the macros that interacts with that cell. Interacts as his value/formula was changed or his value is used in another operation
I can't search in the code for range("C2") for example because the cell can be affected in diferent forms like:
Range("C2")
Cells(2, 3)
Range("B1:E5")
Range(Cells(1, 1), Cells(10, 10))
Offset
Is there any whey that i can discover which macros are changing a specific cell?
Are you looking for a way to track a specific cell, or for a way to track all cells affected by VBA code? Also, "affected" as in "value was changed" or "formula was changed", or "cell was merged with another", "range was unmerged", or "borders were changed", or "backcolor was changed"? Is adding conditional formatting "affecting" a cell? Data validation?
And then, there are more ways a cell can be "affected", too. Without tracking the code as it's running, it could be hard to tell whether this myRange variable is affecting the cell you're looking for.. especially if methods like Range.Offset and Range.Resize are used.
Then ranges can be named, so Range("Foo") might be referring to a cell you're interested in, but you can't know that without verifying whether Names("Foo").RefersToRange includes that cell.
Short of carefully reviewing the code, I'm afraid you can't.
If no macro is highlighting any cell in bright yellow, you could always make a copy of the file and then handle Workbook_SheetChange in ThisWorkbook:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Target.Interior.Color = vbYellow
End Sub
You can easily add conditional logic here to only recolor modified cells from a specific sheet, or from a specific column or row.
Now remove or comment-out any Application.EnableEvents toggling everywhere in the code, and run your macros - the cells it affected (assuming a change in value is what we're after) should all be bright yellow.
If you need to know what code caused this, you can place a breakpoint there, and inspect the call stack:

Resetting Filters using VBA

I have a short piece of code to reset the filters applied to the columns on my worksheet.
Sub ResetFilters()
If ActiveSheet.FilterMode Then
Cells.AutoFilter
End If
End Sub
When I click the command button to run the macro, it works but the 'Reset Filters' command button disappears and the rest that I have on the sheet all stack up in the top left hand corner of the worksheet. They all have 'Don't move or size with cells' set as their property but they still move...
Command Buttons - Before resetting filters
Command Buttons - After resetting
When I enter Design Mode, the 'Reset Filters' button reappears in the correct place... I am very confused - does anyone have any advice they can offer?
EDIT (14/06 16:41) - I have discovered that if I sort the data into ascending or descending order, the buttons stay where they are when I reset the filters. They only move if I have filtered out some of the data.
EDIT (14/06 17:58) - I have included a screenshot of what I am working with so that my filtering needs are clearer! I work in a school and teachers will analyse their data with this tool. They can filter any of the columns to analyse results and progress of specific children based on their characteristics or assessment results. As they can filter or sort many columns, it can be hard to reset the data without missing a column. I would like to add a 'Reset' button to make this job easier. (I will now likely add these to the ribbon as I have just created a bespoke school tab for this tool so that will remove the issue of the moving buttons. However, if there is a better method of resetting the filters, I would love to learn it.)
Screenshot of the data analysis tool
Many thanks.
Don't use ActiveSheet. It is prone to multiple errors.
Use Dim ws As Worksheet: Set ws = Sheets("Sheet1") instead (change Sheet1 to the actual Sheet name that you are using)
If you are willing to remove literally all filters (and not only over a specific range), this will do
Private Sub clearfilters()
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
ws.Cells.AutoFilter
End Sub

Enable Clear Filter on Protected Sheet's Excel Ribbon

Even though Microsoft says that it's not possible: Can't clear auto filter in protected sheet, I am still thinking that somehow this should be possible. At least I hope.
I know that I can clear filters from columns one by one, but I want users to be able to click that Clear feature on the Ribbon/Sort&Filter section. (Currently it's disabled / greyed out)
There are many questions on the internet but none of them is useful honestly. Is there any possibility?
I tried defining Worksheet_Change event to Unprotect Sheet but that is not sensible at all because it slows down my worksheet and I wasn't able to find correct condition to define into Worksheet_Change. In this example it was running whenever $:$ rows are selected . So I need another smart suggestion.
You do not need to unprotect the sheet to clear the filter. Simply paste this macro in a module
Sub ClearFilter()
Dim ws As Worksheet
Set ws = ActiveSheet
ws.AutoFilter.ShowAllData
End Sub
And then assign a shortcut key to it.
Now when you press CTRL+SHIFT+C, you will see Autofilter data is reset.

VBA for clear value in specific range of cell and protected cell from being wash away formula

I have data from like A1:Z50 but I want to delete only A5:X50 using VBA
(I think it will be a lot faster than dragging the whole cell or using clickA5+shift+clickX50+delete).
How can I do this ?
And then, how to lock the cell to prevent it from getting fixed or cleared ?
You could define a macro containing the following code:
Sub DeleteA5X50()
Range("A5:X50").Select
Selection.ClearContents
end sub
Running the macro would select the range A5:x50 on the active worksheet and clear all the contents of the cells within that range.
To leave your formulas intact use the following instead:
Sub DeleteA5X50()
Range("A5:X50").Select
Selection.SpecialCells(xlCellTypeConstants, 23).Select
Selection.ClearContents
end sub
This will first select the overall range of cells you are interested in clearing the contents from and will then further limit the selection to only include cells which contain what excel considers to be 'Constants.'
You can do this manually in excel by selecting the range of cells, hitting 'f5' to bring up the 'Go To' dialog box and then clicking on the 'Special' button and choosing the 'Constants' option and clicking 'Ok'.
Try this
Sheets("your sheetname").range("A5:X50").Value = ""
You can also use
ActiveSheet.range
Not sure its faster with VBA - the fastest way to do it in the normal Excel programm would be:
Ctrl-G
A1:X50 Enter
Delete
Unless you have to do this very often, entering and then triggering the VBAcode is more effort.
And in case you only want to delete formulas or values, you can insert Ctrl-G, Alt-S to select Goto Special and here select Formulas or Values.