How to sort rows by a column containing numbers in ascending or descending order?
I know how to sort using Filters and Using Sort function in VBA. But it sorts in alphabetical order only not by numbers.
This is so far I have done.But still the sorting is coming alphabetically.
Sub sortdata()
Dim LastRow As Integer
NoOfRows = Sheets("RawData").Range("A" & Rows.Count).End(xlUp).Row
Sheets("RawData").Rows("2:" & NoOfRows).NumberFormat = "0"
Sheets("RawData").Sort.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Sheets("RawData").Sort
.SetRange Range("A1:B" & NoOfRows)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
I prefer the Range.Sort method:
[EDIT 2]:
I have added the .TextToColumns line to programmatically address the numbers stored as text issue
Sub sortdata()
Dim ws As Worksheet
Set ws = Sheets("RawData")
With ws.Range("A1:B" & ws.Cells(Rows.Count, "A").End(xlUp).Row)
Intersect(.Cells, ws.Columns("A")).TextToColumns
.Sort Intersect(.Cells, ws.Columns("A")), xlAscending, Header:=xlGuess
End With
End Sub
[EDIT]:
After reading asker's comment:
I will provide an example . If the column A contains this
values:1,2,55,12,14,5343,22222,9 Then after sorting using filter or
inbuilt sort method. The values are sorted as
follows:1,12,14,2,22222,5343,9. But I need the result as follows:
1,2,9,12,14,5334,22222. Is there any in-built function for this?
The problem is that your numbers are stored as text. You'll need to convert them to numbers.
Select column A -> Data -> Text to Columns -> Finish
Now the numbers should sort correctly.
Related
I've been working on a code to sort a block of data using Range.Sort using a custom sort order. I've tried to record macros and look online but came up more confused about this problem.
For the key1:= argument; is it a single cell (e.g. Range("A1")) or a whole column?
How exactly can I use a custom sort order in OrderCustom:=?
In the case I'm going about this all wrong; the Range in Range.Sort can be anywhere as long as its in one continuous block, correct?
Here is the code I'm working with:
Sub Test()
Dim quantity As Variant
quantity = 2 + WorkshetFunction.Count(Range("A" & 3, "K" & 900))
With Range("A" & 3, "K" & quantity)
.Sort key1:=Range("A" & 3)
Order:=xlAscending
Header:=xlNo
OrderCustom:="VALID, GOOD, DUE, OVERDUE, WAY OVERDUE, MISSING"
'> This is the order in which I want the items on this list sorted by.
End With
End Sub
The Range("A" & 3, "K" & quantity) refers to a block of data containing on "A" the "status" of some items determined by their calibration expiration dates, amongst other data which is irrelevant for this purpose, and I'm not in the liberty to share. All I'm asking is help understanding the inner workings of the .Sort method. Thanks!
Give'r
Sub SortItOut()
Dim rng As Range, sh As Worksheet
Set sh = Sheets("Sheet1")
With sh
Set rng = .Range("A3:K" & .Cells(.Rows.Count, "K").End(xlUp).Row)
With rng
sh.Sort.SortFields.Clear
sh.Sort.SortFields.Add Key:=Range("A3") _
, SortOn:=xlSortOnValues, Order:=xlAscending, CustomOrder:= _
"VALID,GOOD,DUE,OVERDUE,WAY OVERDUE,MISSING", DataOption:=xlSortNormal
End With
With .Sort
.SetRange rng
.Orientation = xlTopToBottom
.Apply
End With
End With
End Sub
The following code below execute fine but the output of the sort function is a mess.
Intention of code is to sort range of values from B2 to last row of L
According to DD/MM/YYYY HH:MM:SS value
Code is used to sort a series of files in a folder, so a simple macro recording won't suffice
Dim Slrow As Long
'Updated last row count to Column B from comment made
Slrow = Cells(Rows.Count, 2).End(xlUp).Row
Range("B2:L" & Slrow).Sort Key1:=Range("B2:L" & Slrow), Order1:=xlAscending, Header:=xlNo
SortWb.Close SaveChanges:=True
Output of Code
File Download link available below ->
Download
Sorting with Custom Sort
The problem is the Key and the range where you apply it, and also the options (looks like your data got headers in row 1). Try something like this:
Range("B1:L" & Slrow).Sort Range("B2:B" & Slrow), xlAscending, , , , , , xlYes, , False, xlSortColumns, xlPinYin, xlSortNormal
Change the Key1 to the column you want to sort at eg Key1:=Range("B1").
use SortOn:=xlSortOnValues to make sure it sorts on the values not text (I think this does the trick here).
make it recognize headers automatically by using Header:=xlYes (easier).
This should work:
Dim ws As Worksheet
Set ws = ActiveSheet 'better specify Worksheets("SheetName")
With ws.Sort
.SortFields.Clear
.SortFields.Add2 Key:=ws.Range("B1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange ws.Range("B1:L" & Slrow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
If it doesn't work your dates are no date values but text and you need to convert them into date values.
Also it might be a good idea always to use the ISO date format YYYY-MM-DD hh:mm:ss which is the only one that can not be misunderstood by humans and can easily be sorted even as text (eg in file names etc).
Example how it looks sorted with the code above:
I want to sort my rows based on the values in column G. There are 3 possible values: Green, Red and Yellow. I want the rows sorted with Green on top, then Yellow, then Red.
Everything I try results in the sort order being alphabetical: Green, Red then Yellow. There is a secondary sort on column R, but that is working fine.
My latest code is below. rr is the number of the last row. I have tried it with and without Order1:=xlAscending.
sCustomList = "Green" "Yellow" "Red"
Application.AddCustomList ListArray:=sCustomList
Range("A3:T" & rr).Sort Key1:=Range("G3:G" & rr), Order1:=xlAscending, _
OrderCustom:=Application.CustomListCount + 1, MatchCase:=False, _
DataOption1:=xlSortNormal, Key2:=Range("R3:R" & rr), Order2:=xlAscending
Looking at your code, the sCustomList looks like a string type variable and not a variant array. My success with custom sort lists has been to create a new one every time and use the highest index number to reference it.
Sub custom_sort()
Dim vCustom_Sort As Variant, rr As Long
vCustom_Sort = Array("green", "yellow", "red", Chr(42))
Application.AddCustomList ListArray:=vCustom_Sort
With Worksheets("Sheet2") '<~~ set this properly!
.Sort.SortFields.Clear
rr = .Cells(Rows.Count, "G").End(xlUp).Row
With .Range("A3:T" & rr)
'use this to presort one or more secondary fields before the primary custom sort
'.Cells.Sort Key1:=.Columns(18), Order1:=xlAscending, _
Key2:=.Columns(1), Order2:=xlDescending, _
Orientation:=xlTopToBottom, Header:=xlYes
.Cells.Sort Key1:=.Columns(7), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes, MatchCase:=False, _
OrderCustom:=Application.CustomListCount + 1
End With
.Sort.SortFields.Clear
End With
End Sub
There is a twist between .Cells.Sort.SortFields.Add and .Cells.Sort that usually generates some confusion. The .SortFields.Add method uses a CustomOrder:= parameter and the Range.Sort method uses a OrderCustom:= parameter. The two are most definitely NOT the same but often get used interchangeably with disastrous results.
If you use the SortFields object, you don't have to refer to custom lists:
It should be obvious below where to change the various range references. I also added an alphabetical sort on one of the columns other than G
Option Explicit
Sub TrafficLightSort()
Dim WS As Worksheet
Dim rSortRange As Range, rSortKey As Range
Const sSortOrder As String = "Green,Yellow,Red"
Set WS = Worksheets("sheet1")
With WS
Set rSortRange = Range("E1", .Cells(.Rows.Count, "E").End(xlUp)).Resize(columnsize:=3)
Set rSortKey = rSortRange.Columns(3)
With .Sort.SortFields
.Clear
.Add Key:=rSortKey, _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
CustomOrder:=sSortOrder
.Add Key:=rSortRange.Columns(1), _
SortOn:=xlSortOnValues, _
Order:=xlAscending
End With
With .Sort
.SetRange rSortRange
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.Apply
End With
End With
End Sub
I would recommend adding a table with an explicit sorting order to your worksheet (green = 1, yellow = 2, etc). Then add a column to your sorting range that uses a lookup function to return the sorting value and use VBA to run a standard sort based on that column. This will leave you with VBA code that is easier for developers to read, allows Excel users who don't read VBA to see your sort order, and avoids burying hardcoded values deep in you macro.
I am new to VBA, and excel macros, but not basic programming. I have a few dozen excel files, that I am taking data from, cleaning it, and populating it into one file. After the data is populated, I'd like to sort it according to Column A. After an 2 hours of playing with it, I just recorded a macro and cut and pasted it into my ButtonCall sub. But I'd like to know why its working and why the solutions I found here, and online would not work for me...
Why does this simple code NOT work:
Set q = ThisWorkbook.Worksheets(2)
LastRow = q.UsedRange.rows.Count 'q.UsedRange.Row ' - 1 + q.UsedRange.rows.Count
LastCol = q.UsedRange.Columns.Count
q.Range("A6:AAA" & LastRow).Sort Key:=q.Columns("A"), Order:=xlDescending
While this modified recorded Macro does?
Set q = ThisWorkbook.Worksheets(2)
LastRow = q.UsedRange.rows.Count 'q.UsedRange.Row ' - 1 + q.UsedRange.rows.Count
LastCol = q.UsedRange.Columns.Count
q.Sort.SortFields.Clear
q.Sort.SortFields.Add Key:=Range("A6:A" & LastRow), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With q.Sort
.SetRange Range("A6:AAA" & LastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Any thoughts? Thanks.
Your code is using the range.sort method, while the original code is employing the sort object - two different things.
This code will sort "A6" to end of data by column A, using the Range.Sort method.
Sub MySort()
Dim q As Worksheet
Dim r As Range
Set q = ThisWorkbook.Worksheets(2)
' specify data range from "A6" to end of data
Set r = q.Range("A6", q.Cells.SpecialCells(xlCellTypeLastCell))
' Header:=xlNo assumes A6 row is included in data to be sorted
r.Sort key1:=r(1, 1), Order1:=xlDescending, Header:=xlNo
End Sub
I have tried to sort a table using the following VBA code. The code does select the correct column, and the column filter does get a small arrow in it, indicating that it is sorted. But the rows do not sort. They stay unsorted.
What is wrong?
Sub SortTableTest()
Dim tbl As ListObject
Dim columnToSortBy As Range
Set tbl = Sheets("PB").ListObjects("AI")
Set columnToSortBy = tbl.ListColumns(9).Range
'Sort table
With tbl.Sort
.SortFields.Clear
.SortFields.Add columnToSortBy, xlDescending
.Header = xlYes
.MatchCase = False
.Apply
End With
End Sub
First, you missed one parameter in .SortFields.Add method. What you need is:
.SortFields.Add columnToSortBy, xlSortOnValues, xlDescending
Second, question from you comment. Try with this kind of References:
Set columnToSortBy = Range(tbl.Name & "[[#All],[column name here]]")