Excel Sorting not working due to Range object - excel

This macro is based off one I recorded, but have tweaked to cope with possible absence of 3 of the 4 sorting criteria. I can't figure out why my Macro works when the range criteria is specific, but not when I'm referencing a single cell and extrapolating.
With this line the sorting works
.SetRange Range("A1:W162")
With this line it doesn't sort.
.SetRange Range("A1").End(xlDown).End(xlToRight)
I've stepped through and can confirm it's selecting the correct range
I don't want use the line with specific cells because future exports will be different sized.
This is the full subroutine (the relevant bit is near the bottom).
Thanks!
Sub SortByScoreAndCost()
Dim Score As Range
Dim Cost As Range
Dim YN As Range
Dim OriginalScore As Range
Set Score = Cells.Find("Score")
Set Cost = Cells.Find("Cost")
Set YN = Cells.Find("Y/N")
Set OriginalScore = Cells.Find("Original Score")
Range("A1").CurrentRegion.Select
ActiveSheet.Sort.SortFields.Clear
ActiveSheet.Sort.SortFields.Add Key:=Range( _
Score.Offset(1, 0), Score.End(xlDown)), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortNormal
If Cells.Find("Cost") Is Nothing _
Then
Else: ActiveSheet.Sort.SortFields.Add Key:=Range _
(Cost.Offset(1, 0), Cost.End(xlDown)), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption _
:=xlSortNormal
End If
If Cells.Find("Y/N") Is Nothing _
Then
Else: ActiveSheet.Sort.SortFields.Add Key:=Range _
(YN.Offset(1, 0), YN.End(xlDown)), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption _
:=xlSortNormal
End If
If Cells.Find("Original Score") Is Nothing _
Then
Else: ActiveSheet.Sort.SortFields.Add Key:=Range _
(OriginalScore.Offset(1, 0), Original.End(xlDown)), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption _
:=xlSortNormal
End If
With ActiveSheet.Sort
.SetRange Range("A1:W162") 'works with this line
.SetRange Range("A1").End(xlDown).End(xlToRight) 'doesn't work if replaced with this line
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

Range("A1").End(xlDown).End(xlToRight) refers to a single cell range, not similar to A1:W162. Assuming A1:W162 is the range where all the data on your sheet is. The line refers to W162 only. The Range.End property is explained here and it shows that it does not retain the starting point.
Try Range("A1:"& Range("A1").End(xlDown).End(xlToRight).Address) instead as this should create a range similar to A1:W162. The first part is the string "A1:" and Range("A1).End(xlDown).end(xlToRight).Address returns the string "$W$162" Together they form "A1:$W$162"
With the comment I made on your question in mind I would suggest the code below.
Dim wsData as Worksheet 'Add worksheet variable
Set wsData = ThisworkBook.Worksheets("Name of your data sheet")
With wsData.Sort 'Instead of using ActiveSheet
.SetRange wsData.Range(wsData.Cells(1, 1), wsData.Cells(1, 1).End(xlDown).End(xlToRight))

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

Why do blank lines appear after multi-level sorting?

I have a macro that sorts by color, then by date, then again by date.
If I delete a date, instead of just re-sorting, it re sorts and then leaves blank rows where the row from which a date was deleted used to be. I tried adding another sort layer where I sort by color RGB(0,0,0).
Why are the blank rows sitting there?
How do I remove them or make them not appear at all?
If Not Intersect(Target, Range("A:C")) Is Nothing Then
MsgBox ("sorting")
ActiveSheet.Sort.SortFields.Clear
ActiveSheet.Sort.SortFields.Add(Range("C:C"), _
xlSortOnCellColor, _
xlDescending, _
, _
xlSortNormal).SortOnValue.Color = RGB(146, 208, 80)
ActiveSheet.Sort.SortFields.Add2 Key:=Range("C:C"), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
ActiveSheet.Sort.SortFields.Add2 Key:=Range("B:B"), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
ActiveSheet.Sort.SortFields.Add2(Range("C:C"), _
xlSortOnCellColor, _
xlDescending, _
, _
xlSortNormal).SortOnValue.Color = RGB(255, 255, 255)
With ActiveSheet.Sort
.SetRange Range("A:C")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End If
I believe I might have an answers to your questions, atleast for the second one I am sure...
Why are the blank rows sitting there?
I can be only guessing since I do not have your source file to check for any irregularities nor your whole macro. If I had to guess, I would say it is either some function in your macro what is causing this or it might also be an issue of how you define sort ranges. You only specify columns and not actual starting cells and also no ending cells. The way I am used to sort data is to dynamically define the exact range.
How do I remove them or make them not appear at all?
Please try the code which I have adjusted based on your data and code you provided:
If Not Intersect(Target, Range("A:C")) Is Nothing Then
MsgBox ("sorting")
With ActiveWorkbook.ActiveSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row '<-- get last row of data in column "A"
.Sort.SortFields.Clear
.Sort.SortFields.Add(Range("C1:C" & lastRow), _
xlSortOnCellColor, xlDescending, , xlSortNormal).SortOnValue.Color = RGB(146, 208, 80)
.Sort.SortFields.Add Key:=.Range("B1:B" & lastRow), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range("C1:C" & lastRow), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.Sort.SortFields.Add(Range("C1:C" & lastRow), _
SortOn:=xlSortOnCellColor, Order:=xlDescending, DataOption:=xlSortNormal).SortOnValue.Color = RGB(255, 255, 255)
With .Sort
.SetRange Range("A1:C" & lastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End If
The main adjustment is declaration of lastRow which adjusts the bottom of the data range (in your situation it should not matter but you might sometimes encounter data where you want to sort until certain row and this will be very helpful. Also lastRow as defined here is very helpful for a whole lot of other macros and helps to set ranges dynamically).
And I have also added the start the data as you can see in Range("C1:C" & lastRow)
I have tested this on a sample data you have provided and it worked as expected. I hope it will work for you exactly as you wanted to.

Automatic Multi-level Sorting in VBA

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?

Sort by variable Range

I want code to figure how large a table of data is, then sort it. I assumed that I would declare a variable range once I knew how large the table is and tell Excel to sort first by the variable range "Account" and then "Symbol" and then "Quantity."
The problem occurs with the ActiveWorkbook.Worksheets("Mutual Funds").Sort.SortFields.Add Key:=Range("Account")...
Method Range of Object' Global Failed is my error message. It appears that this is not the correct way to give it a variable range.
Anyone know how to fix this?
Sub Macro1()
'
ActiveWorkbook.Sheets("Mutual Funds").Activate
Range("A12").Select
Do Until IsEmpty(ActiveCell)
ActiveCell.Offset(1).Select
Loop
ActiveCell.Offset(-1).Select
Dim Account As Range
Dim Symbol As Range
Dim Quantity As Range
Dim EntireRange As Range
Set Account = Range(ActiveCell, "A11")
Set Symbol = Range(ActiveCell.Offset(, 9), "J11")
Set Quantity = Range(ActiveCell.Offset(, 7), "H11")
Set EntireRange = Range(ActiveCell, "AS11")
ActiveWorkbook.Worksheets("Mutual Funds").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Mutual Funds").Sort.SortFields.Add Key:=Range("Account"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortTextAsNumbers
ActiveWorkbook.Worksheets("Mutual Funds").Sort.SortFields.Add Key:=Range("Symbol"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Mutual Funds").Sort.SortFields.Add Key:=Range("Quantity"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Mutual Funds").Sort
.SetRange Range("EntireRange")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Using Range("Account") to reference a Range variable is wrong.
Just use Account
Other issues:
The Key's need to exclude the header,
Your method of getting the used ranges is highly inefficient.
Here's your code refactored :
Sub Macro1()
Dim wb As Workbook
Dim ws As Worksheet
Dim Account As Range
Dim Symbol As Range
Dim Quantity As Range
Dim EntireRange As Range
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Mutual Funds")
With ws
Set Account = .Range(.Cells(12, 1), .Cells(12, 1).End(xlDown))
End With
Set Symbol = Account.Offset(, 8)
Set Quantity = Account.Offset(, 6)
Set EntireRange = Account.Offset(-1, 0).Resize(Account.Rows.Count + 1, 45)
With ws.Sort ' EntireRange
.SortFields.Clear
.SortFields.Add Key:=Account, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortTextAsNumbers
.SortFields.Add Key:=Symbol, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SortFields.Add Key:=Quantity, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.SetRange EntireRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

excel vba sort error 1004

i'm using this code for sorting (checked for Excel 2010/2013):
Worksheets("Tabelle4(1)").Activate
ActiveSheet.Sort.SortFields.Add Key:=Range( _
"W2:W51"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortNormal
I loop over a sheet 70 times with different values and sort and export them as a pdf.
Everything works fine, but after approximately 30 times I get an error 1004.
If I start the loop at this point 30 again it works fine.
The problem doesn't seem to do with the values.
Is there a buffer inside of excel, which I've to clear from time to time?
You should clear your Sort fields from time to time indeed, because they just accumulate and it'll be harder for you to prioritize them.
And just don't use Activate , nor Select which is even worse, so just combine Sheets().Activate and ActiveSheet.Sort to Sheets().Sort , your code will be much more efficient.
This should help you :
With Worksheets("Tabelle4(1)")
.Sort.SortFields.Add _
Key:=Range("W2:W51"), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
.Sort.Orientation = xlTopToBottom
.Sort.Apply
'here is your export
.Sort.SortFields.Clear
End With
Set ws = Worksheets("Sheet1")
Set rng = ws.Range(Cells(startRow, 1), Cells(endRow, 3))
'startRow=2, endRow=18
'Sort Table Date Decending Order
ws.Sort.SortFields.Clear
With ws
.Sort.SortFields.Add Key:=rng, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.Sort.Orientation = xlTopToBottom
.Sort.SortMethod = xlPinYin
.Sort.Apply
End With
'This works but does not sort the data descending.

Resources