Automatic Multi-level Sorting in VBA - excel

I currently have the following code that works and every time something is typed in, it is automatically sorted by column I
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Column = 9 Then
Dim lastRow As Long
lastRow = ActiveSheet.Cells.Find(What:="*", LookIn:=xlValues,
SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Range("A2:I" & lastRow).Sort Key1:=Range("I2:I" & lastRow),
Order1:=xlAscending, Header:=xlNo
End If
End Sub
I want it so that it is primarily sorted by item I, but also secondarily sorted by column A. Any help please?

The starting point for any request like this should be "Fire up the macro recorder, perform a sort, and see what code it spits out".
If you fire up the recorder and add a multilevel sort like so:
...then the Macro Recorder spits out this:
Sub Macro11()
'
' Macro11 Macro
'
'
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("I2:I16") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("A2:A16") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("A1:I16")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
This gives you a clue as to the syntax you need to add multiple sort keys. Do you need help amending your original code, or is this enough to get you started?

Related

Sort and ignore leading quotation marks

This VBA code sorts my vinyl collection catalogue by any column by double-clicking the column header.
With my classical vinyl, nearly half of the song titles are in quotes and so when that column is sorted, it alphabetically sorts the titles with quotes first, then the titles without quotes.
Is there a way to add a line of code so that it will ignore the leading quotation marks when sorting so that "ac" comes after ab and so on?
My workaround for now uses a hidden helper column to strip the quotes but I am hoping for a cleaner solution.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim KeyRange As Range
Dim ColumnCount As Integer
'Clear previous sorts
ActiveSheet.Sort.SortFields.Clear
'Clear contents of hidden helper column
Columns("K").ClearContents
'Copy and Paste songname column to helper column
Range("F:F").Copy Range("K:K")
'Strip quotes from helper column
Application.ScreenUpdating = FALSE
ActiveSheet.Columns("K").Replace What:="""", Replacement:="", LookAt:=xlPart, MatchCase:=False
Application.ScreenUpdating = TRUE
'Set range of header columns that will sort on double-click
ColumnCount = Range("A1:J1").Columns.Count
Cancel = FALSE
If Target.Row = 1 And Target.Column <= ColumnCount Then
Cancel = TRUE
'Get cell address of double-clicked header cell
Set SortColumn = Range(Target.Address)
'Set fill color of currently sorted column header
Rows(1).Interior.Color = xlNone
SortColumn.Interior.ColorIndex = 15
With ActiveSheet
'Sort by hidden column if songname column is double-clicked
If SortColumn = Range("F1") Then
Range("K1").Select
Else
SortColumn.Select
End If
'Sort by selected column followed by album, disc, then track
.Sort.SortFields.Add Key:=Selection, _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("E1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("B1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("C1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
End With
With ActiveSheet.Sort
'Set flexible sort range to all data before reaching entirely empty row or column
.SetRange Range("A1").CurrentRegion
.Header = xlYes
.MatchCase = FALSE
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End If
End Sub
Excel has always had this issue when sorting data. This is because it uses ASCII character codes to determine sort order (more details here: https://exceljet.net/excel-functions/excel-char-function). Special characters and punctuation have lower ASCII values than alphabet letters, so they get sorted at the top. This is by design.
There's no real way to "ignore" quotation marks when sorting, but one way to get around this is to remove all the quotes from the cells you are trying to sort. You could try adding this code right after your SET statement:
ActiveSheet.KeyRange.Cells.Replace _
What:="""", _
Replacement:="", _
LookAt:=xlPart, _
MatchCase:=False
WARNING!!! This will actually modify all your song titles (it will remove the double quotes from that column), so please back up your file before you try this.
One way is to Add a dummy Column K with F data, clear ", sort, erase column K...
I fixed the code accordingly
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim KeyRange As Range
Dim ColumnCount As Integer
Dim dstRng as Range ' placeholder 2 add column "K"
ActiveSheet.Sort.SortFields.Clear
ColumnCount = Range("A1:J281").Columns.Count
Cancel = False
If Target.Row = 1 And Target.Column <= ColumnCount Then
Cancel = True
Set KeyRange = Range(Target.Address)
Set dstRng = KeyRange.Resize(, 1).Offset(, KeyRange.Columns.Count - 1) 'Added column K
KeyRange.Resize(,1).Offset(,5).copy ' copy column F
dstRng.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
dstRng.Replace What:="""", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByColumns, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
With ActiveSheet ' columns F,B,C >> K,B,C
.Sort.SortFields.Add Key:=KeyRange, _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("K1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("B1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=Range("C1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
End With
With ActiveSheet.Sort
.SetRange Range("A1:K281")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
dstRng.ClearContents
End If
End Sub
As Always run 1st on a copy, protecting the original Excel file.
NOTES: I have used KeyRange to work on, but there might be a case that some set SrcRng = Range("A1:J281") is needed

How to write code for a sort that will work in any workbook?

Sub test()
ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort.SortFields. _
Clear
ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort.SortFields. _
Add2 Key:=Range("E2:E62"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort.SortFields. _
Add2 Key:=Range("B2:B62"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort.SortFields. _
Add2 Key:=Range("A2:A62"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort
.SetRange Range("A1:I62")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
This is a macro I recorded to sort data for me. Each week to active worksheet changes names. How do I get it to where it will work on any sheet?
Sort is a method that is accessible through worksheet objects. However you choose to reference a worksheet object is up to you.
The method that excel has transcribed for you in the macro recorder uses the worksheet's name as an index.
ActiveWorkbook.Worksheets("timesheet_report_2019-12-08_thr").Sort...
Notice that the name is in quotes and is therefore a string. You could create a string variable. The following code does the same work as above.
Dim worksheetName as String
worksheetName = "timesheet_report_2019-12-08_thr"
ActiveWorkbook.Worksheets(worksheetName).Sort...
But you can also use numeric indexes. This would sort whatever sheet the workbook thinks is first in the collection. (this can be a bit misleading so be careful doing it this way. The first sheet in the collection isn't always the leftmost tab, or even the sheet named "Sheet1").
ActiveWorkbook.Worksheets(1).Sort...
You can also use certain keywords to reference a worksheet. Some commenters have suggested ActiveSheet. That works, because it references a worksheet object.
ActiveWorkbook.ActiveSheet.Sort...
And, you can get references out of an iterator, like in a "for each" loop. The following code (complete with sort) will run the sort you've designed on every sheet in the workbook.
Sub SortAllSheets()
For Each s In ActiveWorkbook.Sheets
With s.Sort
.SortFields.Clear
.SortFields.Add2 Key:=s.Range("E2:E62"), Order:=xlAscending
.SortFields.Add2 Key:=s.Range("B2:B62"), Order:=xlAscending
.SortFields.Add2 Key:=s.Range("A2:A62"), Order:=xlAscending
.SetRange s.Range("A1:I62")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Next s
End Sub
So, there are lots of ways to run your sort "in any workbook". Hope it helps.

Custom order sort

Hi I would like to sort the whole C column based on the values(Critical, high, medium,low). I am running this code on macro enabled worksheet
Here is my code.
Sub run()
Range("C:C").Sort Key1:=Range("C1"), SortOn:=xlSortOnValues, Order:=xlAscending, CustomOrder:="Critical,High,Medium,Low", DataOption:=xlSortNormal
End Sub
It did not work as there is error indicated. No argument. What is the solution to correct this problem? Thank you.
Your custom sort criteria needs to be in an array. Try,
Sub runSortC()
Dim vCustom_Sort As Variant, rr As Long
vCustom_Sort = Array("Critical","High","Medium","Low", Chr(42))
Application.AddCustomList ListArray:=vCustom_Sort
with Range("C:C")
.parent.Sort.SortFields.Clear
'sort on custom order with header
.Cells.Sort Key1:=.Columns(1), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes, MatchCase:=False, _
OrderCustom:=Application.CustomListCount + 1
.parent.Sort.SortFields.Clear
End With
End Sub
If this is in a public module, a qualified parent worksheet reference would help.
Try:
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("A:A") _
, SortOn:=xlSortOnValues, Order:=xlAscending, CustomOrder:= _
"Critical,High,Medium,Low", DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("A:A")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With

Auto Sorting after inputting data using UserForm

I've made a UserForm to input data to specific columns on a worksheet("Endorse"), and it works fine.
After that, I have used a code to automatically sort the sheet based on the the values on Column A, B and C. But the sheet does not sort based on the criteria:
Column A: oldest to recent (date)
Column B: ascending order by: "BSUH (September),Frimley (October),CWH (November),Kingston (December)"
Column C: ascending order by: Allen,Christine,Feri,Hubert,Paula"
here is the code that i have used for the sheet("Endorse"):
Private Sub Worksheet_Change(ByVal Target As Range)
LastRow = Range("L4000").End(xlUp).Row
ActiveWorkbook.Worksheets("Endorsed Candidates").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Endorsed Candidates").Sort.SortFields.Add Key:= _
Range("A2:A" & LastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption _
:=xlSortNormal
ActiveWorkbook.Worksheets("Endorsed Candidates").Sort.SortFields.Add Key:= _
Range("B2:B" & LastRow), SortOn:=xlSortOnValues, Order:=xlAscending, CustomOrder _
:="BSUH (September),Frimley (October),CWH (November),Kingston (December)", _
DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Endorsed Candidates").Sort.SortFields.Add Key:= _
Range("C2:C4000"), SortOn:=xlSortOnValues, Order:=xlAscending, CustomOrder _
:="Allen,Christine,Feri,Hubert,Paula", DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Endorsed Candidates").Sort
.SetRange Range("A2:L" & LastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Here is the sheet after using the UserForm:
[enter image description here][1]
*ps I can't post an image yet in my question, hope you guys understand. And many thanks to those who could help!

Excel Macro: Apply sorting to each sheet

Here is the code that I am using to apply sorting to each page except two. The system is throwing following error.
"select method of range class failed".
Private Sub CommandButton3_Click()
Dim ws1 As Worksheet
For Each ws1 In Worksheets
If ws1.Name <> "Sheet1" And ws1.Name <> "Extra" Then
**ws1.Range("A1:V1000").Select** Something is wrong here I suspect
ActiveWorkbook.Worksheets(ws1).Sort.SortFields.Clear
ActiveWorkbook.Worksheets(ws1).Sort.SortFields.Add Key:=Range("I2:I1000") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets(ws1).Sort.SortFields.Add Key:=Range("T2:T1000") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets(ws1).Sort
.SetRange Range("A1:V1000")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End If
Next ws1
End Sub
Please help.
I would Select the worksheet before Selecting the range. Replace:
ws1.Range("A1:V1000").Select
with:
ws1.Select
Range("A1:V1000").Select
You may not need these Selections if you use .Range() rather than Range() in the code that follows. Also since ws1 is a worksheet object,:
ActiveWorkbook.Worksheets(ws1)
should be replace with:
ActiveWorkbook.Worksheets(ws1.Name)
There may be other problems with code.

Resources