Excel VBA CustomSort from Range - excel

Sub RRC()
Dim noOfLists As String
With Sheets("All_list")
Application.CutCopyMode = False
Application.AddCustomList ListArray:=Range("AU2:AU4")
noOfLists = Application.CustomListCount
noOfLists = noOfLists + 1
End With
ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort.SortFields.Add2 _
Key:=Range("All[RRC]"), SortOn:=xlSortOnValues, Order:=xlAscending, _
CustomOrder:=CVar(noOfLists), DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.DeleteCustomList (noOfLists - 1)
End Sub
Could anyone Help to figure out why this does not work, it runs, but does not sort.
Range AU2:AU4 will be dynamic, meaning that sorting there will always be different, therefore the key moment here is to use the latest sort in that range when applying VBA
Thank you

This is what I would have used. Let me know if there's a reason you're using the CustomOrder in the actual sort
Sub RRC()
Dim currWorksheet As Worksheet
Set currWorksheet = ActiveWorkbook.Worksheets("All_list")
Dim newRangeSort As Range
Dim newRangeKey As Range
' Fields to be sorted
Set newRangeSort = currWorksheet.Range("AU2:AU4")
' "Header" column of which to sort from
Set newRangeKey = currWorksheet.Range("AU1")
'Your sort
Dim customSort As String
customSort = ("test")
'Actual sort
currWorksheet.Sort.SortFields.Clear
newRangeSort.Sort Key1:=newRangeKey, Order1:=xlAscending, Header:=xlGuess, _
OrderCustom:=Application.CustomListCount + 1, MatchCase:=False, _
Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
' clean up
Set currWorksheet = Nothing
End Sub
There should be no reason to use a With here. This is a much better way of pulling a custom sort, as using vba - Application.AddCustomList is just an awful way to do things - very unfriendly

Here is what i did, after some intzernet research:
Sub Segment()
Dim x() As Variant
With Sheets("All_list")
.Range("AP2:AP10").Clear
.Range("AO2:AO10" & .Cells(.Rows.Count, "AO").End(xlUp).Row).Copy
.Range("AP2").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
x = Application.Transpose(Sheets("All_list").Range("AP2:AP10").Value)
ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort.SortFields.Add2 _
Key:=Range("All[Segment]"), SortOn:=xlSortOnValues, Order:=xlAscending, _
CustomOrder:=Join(x, ","), DataOption:=xlSortNormal
End With
With ActiveWorkbook.Worksheets("All_list").ListObjects("All").Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
First ranges just copy paste code cells into text, otherwise macro doe not run, join allowed to skip creation of custom list in excel

Related

How to refer to dynamic sheet in Excel VBA instead of Sheet Name - Instead of "Sheet16", i want to refer to the ActiveSheet

How to refer to dynamic sheet in Excel VBA instead of Sheet Name - Instead of "Sheet16", i want to refer to the ActiveSheet, please see below
Sub Macro1()
Cells.Select
Selection.Copy
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.AutoFilter
ActiveWorkbook.Worksheets("Sheet16").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet16").AutoFilter.Sort.SortFields.Add2 Key:= _
Range("M1:M12"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption _
:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet16").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Just need to change it to (ActiveSheet.Name)
The usage of ActiveSheet (as well of that of ActiveCell, Selection and the like of) should be avoided in favor of that of variables of proper class (e.g.: Worksheet, Range) as follows:
Sub Macro1()
ActiveSheet.UsedRange.Copy ' handle only relevant cells
Sheets.Add After:=ActiveSheet
Dim newSh As Worksheet
Set newSh = ActiveSheet ' set the currently active sheet to the 'newSh' variable of 'Worksheet' class
With newSh ' reference 'newSh' variable
.Paste
Application.CutCopyMode = False
.UsedRange.AutoFilter
Dim keyRng As Range
Set keyRng = .Range("M1:M12") ' set M1:M12 cells range of the referenced sheet as the one for sort keys
With .AutoFilter.Sort ' reference 'Sort' property of 'Autofilter' object of referenced sheet
With .SortFields ' reference 'SortFields' object of referenced 'Sort' property
.Clear
.Add2 Key:=keyRng, _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
End With
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End Sub
This worked perfectly fine for me :)
Sub Sortieren()
lr = Cells.Find("*", Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
Cells.Select
Selection.AutoFilter
Worksheets(ActiveSheet.Name).Sort.SortFields.Clear
Worksheets(ActiveSheet.Name).AutoFilter.Sort.SortFields.Add2 Key:= _
Range("N1:N" & lr), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption _
:=xlSortNormal
With ActiveWorkbook.Worksheets(ActiveSheet.Name).AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

How to sort date data type?

I've been trying to sort dates on A1 but it sorts based on text not the value
Private Sub sortData()
Worksheets(Me.Combobox1.Value).Range("A1:F1", Range("A1:F1").End(xlDown)).Sort
Key1:=Range("A1"), Order1:=xlAscending, Header:=xlYes
End Sub
As #Marcelo Scofano Diniz started to say, when you run into a problem forget about the shortcxuts and go by the book. Here is the book.
Private Sub SortByDate()
Dim Ws As Worksheet
Dim SortRange As Range
Set Ws = Worksheets(Me.ComboBox1.Value)
With Ws
Set SortRange = .Range(.Cells(1, 1), .Cells(.Rows.Count, "A").End(xlUp)) _
.Resize(, 6)
With .Sort.SortFields
.Clear
.Add2 Key:=SortRange.Cells(1), _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
DataOption:=xlSortNormal
End With
With .Sort
.SetRange SortRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End Sub
The above code will carry out the sort you say your code won't do. If the dates are true dates they will be sorted by date. If they are fake dates they will be sorted as text. And if you have doubt about any part of the code you can see what is being done and step through it line by line.
Change The Range to Table of Name Tbl
then Create :
Sub Table_Sort(byval FieldNo as Integer)
Tbl.Sort.SortFields.Clear
FieldRange(FieldNo).Select
Tbl.Sort.SortFields.Add _
Key:=FieldRange(FieldNo), SortOn:=xlSortOnValues, Order:= _
xlAscending, DataOption:=xlSortNormal
With Tbl.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

VBA Excel sort the data from A to Z in one column with all data table changes

It might be such a duplicate question with:
VBA Sort A-Z on One Column
However I want to have the stuff clarified.
I tried to use this code for my purpose:
Sub SortAsc2()
Dim LastRow As Long
LastRow = Cells(Rows.Count, "M").End(xlUp).Row
'Columns("D:D").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("D"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("D2:D" & LastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
where I got an error:
1004 Method 'Range' of object_Global failed
I tried another code then
Sub SortDataWithoutHeader()
Range("D1:D12").Sort Key1:=Range("D1"), Order1:=xlAscending, Header:=xlNo
End Sub
But the sort happens only within the column, whereas the other data is unaffected.
I want to have values from other cells corresponding to the data sort.
Is anyone able to help?
Give this a try.
Read code's comments and adjust it to fit your needs
Code:
Public Sub SortAsc2()
Dim targetSheet As Worksheet
Dim targetRange As Range
Dim lastRow As Long
' Set a reference to the sheet
Set targetSheet = ThisWorkbook.Worksheets("Sheet1")
' Find the last non empty row (based on column A)
lastRow = targetSheet.Cells(targetSheet.Rows.Count, "A").End(xlUp).Row
' Set the range to be sorted (A2= begins in row 2 and ends in column K?)
Set targetRange = targetSheet.Range("A2:K" & lastRow)
' Clear current sorting fields
targetSheet.Sort.SortFields.Clear
' You are missing a 1 after "D" in Range in your code
targetSheet.Sort.SortFields.Add Key:=Range("D1"), _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
DataOption:=xlSortNormal
With targetSheet.Sort
.SetRange targetRange
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Let me know if it works

how do I know if my sort worked in excel vba?

I recorded the following macro when sorting data:
Sub sort_sheet_test()
ActiveWindow.ScrollRow = 1
ActiveWindow.ScrollColumn = 1
Range("A1:AB40905").Select
ActiveWorkbook.Worksheets("flurry_an_output.csv").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("flurry_an_output.csv").Sort.SortFields.Add Key:= _
Range("AB2:AB40905"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("flurry_an_output.csv").Sort
.SetRange Range("A1:AB40905")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
I then wrote my own function to use generically in other sheets...etc:
Function sort_sheet_last_column(sheet_name As String)
Dim rows1 As Long
rows1 = Get_Rows_Generic(sheet_name, 1) ' get the number of rows in the sheet
Dim columns1 As Integer
columns1 = Range(find_last_column(sheet_name)).column ' get the number of columns in the sheet
Dim sort_range As Range
Dim key_range As Range
With Worksheets(sheet_name)
Set sort_range = .Range(.Cells(1, 1), .Cells(rows1, columns1)) ' set up range: the whole used portion of the sheet
Set key_range = .Range(.Cells(1, columns1), .Cells(rows1, columns1))
End With
With Worksheets(sheet_name).Sort
.SortFields.Clear
.SortFields.Add Key:=key_range, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange sort_range
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Function
It seems to reorder the rows based on the right key, but how do I know if my version is 1) working at all (it's hard to know if over 40,000 rows are ordered properly, and 2) how do I know if the rest of the data are in their proper order?
I always use Sheet.Range.Sort not Sheet.Sort
lLastRow = LastUsedRow(shMain)
shMain.Range("A1:W" & lLastRow).SORT Key1:=.Range("B2"), _
Order1:=xlAscending, _
Header:=xlYes, _
OrderCustom:=1, _
MatchCase:=False, _
Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
Never had a problem with this sorting the range and you can add Key2,Order2 and DataOption2 to sort by multiple columns

Issue with SortFields function and ranges

My problem with the code below is that because of the select of the range that I have defined I can't run this code successfully while on another Sheet. I know that it's bad practice to use .select and now I know why, it causes so many problems. I'm not sure how to fix this code so that it'll work properly.
Sub Sorting(sorted As Range, keys As Range)
'Range("A1:A4").Select
sorted.Select
Sheets("IDBHour1").Sort.SortFields.Clear
Sheets("IDBHour1").Sort.SortFields.Add Key:=keys, SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortTextAsNumbers
With Sheets("IDBHour1").Sort
.SetRange sorted
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
You don't need to select in order to sort. How are you passing the ranges in the calling procedure?
My personal preference would be to pass the ranges as strings and then make them into ranges inside the sub. That code runs from anywhere. The IDBHour1 sheet needs neither selection nor activation.
Sub Sorting(sortSheet As String, sorted As String, keys As String)
Dim ws As Worksheet
Dim sortRange As Range
Dim sortKeys As Range
Set ws = ThisWorkbook.Sheets(sortSheet)
Set sortRange = ws.Range(sorted)
Set sortKeys = ws.Range(keys)
ws.Sort.SortFields.Clear
ws.Sort.SortFields.Add Key:=sortKeys, SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortTextAsNumbers
With ws.Sort
.SetRange sortRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Sub testSort()
Call Sorting("IDBHour1", "A1:A10", "A1")
End Sub

Resources