Sorting Data Based On the Last column - vba

So I have 6 columns (Columns A:F). Column A consist of dates while in between that B-E containing data based off of the dates. Column F contains the categories where it's either (L, RI, or R). I've already sorted all of the L's, RI's and R's together so I only want to sort within their own category.
My problem is that the dates are scattered within each category and I need to sort them by the oldest-newest date. So say for instance, the L's go down from F2:F18. So I need to sort the date from A1:F18 and only that part or else it'll mix in with the other data in category's RI, R. And the RI's go from F19:F24 so I would need to sort the data from A19:F24
I need a VBA code that sorts the dates from oldest-newest within their own categories. The data changes so sometimes there can be more or less categories.
I tried recording a macro to get a headstart but I literally don't know what to change because I'm new to VBA. It would definitely make it easier if I don't have to manually select it. Sorry if i'm not descriptive enough, I feel as though that I am pretty bad at explaining things but tried my best Here is the code below:
Range("A1:F23").Select
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Add Key:=Range("A2:A23") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet4").Sort
.SetRange Range("A1:F23")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("A24:F33").Select
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Add Key:=Range("A25:A33") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet4").Sort
.SetRange Range("A24:F33")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

Consider changing your order of operations. I would recommend sorting all of your data by date first (column A) then sort by your other criteria (Column F). Doing so should order your data by date within each L, RI, R.
Should not require a VBA code to accomplish what I am describing when using the filter tool under the "Data" ribbon.
In case you just really want to automate this:
Rows("1:1").Select 'Column Headers Row
Selection.AutoFilter
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Add Key:=Range _
("A1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Add Key:=Range _
("F1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

Related

Sorting, then re-sorting

I am trying to sort the Buy column from Largest to smallest then copy and paste into another column, then I will sort the Sell column from largest to smallest and again copy and paste into another column. The code will not sort, copy/paste, re-sort, then copy/paste; in other words it keeps the original sorting of only the buys. Is there a way to sort the buys, paste them elsewhere, then sort the sells and copy likewise? I was thinking about trying a do loop but Im not sure why I cant do this in a more simple way. Any insight would help. Thank you!
' buys
rows("3:3").Select
Selection.AutoFilter
ActiveSheet.AutoFilter.Sort.SortFields.Add Key:=Range("D3" _
), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortTextAsNumbers
With ActiveSheet.AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'copy top ten buys
Range("A5:I14").Select
Selection.Copy
Range("k3").Select
ActiveSheet.PasteSpecial
Application.CutCopyMode = False
' sells
ActiveSheet.AutoFilter.Sort.SortFields.Clear
ActiveSheet.AutoFilter.Sort.SortFields.Add Key:=Range("E3" _
), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortTextAsNumbers
With ActiveSheet.AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("A5:I14").Select
Selection.Copy
Range("k14").Select
ActiveSheet.paste
Application.CutCopyMode = False
Since you only add a new sort key your second sort will be on the Buy and the Sell column. Do Sortfields.clear before the second search.

Why isn't my VBA sorting my column data correctly?

I am trying to delete the first row of the Excel sheet and sort a specific column using its name "CUST_RELPO". I am using the column header name since the name may change.
Sorting and copying the column from the second row since I do need to copy the column header.
Sub ClearFirstRow()
'
' ClearFirstRow Macro
'
'
Rows("1:1").Select
Selection.Delete Shift:=xlUp
Cells.Select
Dim rngcustrelpo As Range
xindex = Application.ActiveCell.Column
Set rngcustrelpo = ActiveSheet.UsedRange.Find("CUST_RELPO")
If rngcustrelpo Is Nothing Then
MsgBox "CUST_RELPO column was not found."
Exit Sub
End If
'Cells.Select
Range(rngcustrelpo, rngcustrelpo.End(xlDown)).Select
ActiveWorkbook.Worksheets("BACKORDER").Sort.SortFields.Add Key:=ActiveSheet.UsedRange, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("BACKORDER").Sort
.SetRange ActiveSheet.UsedRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Set rngcustrelpo1 = rngcustrelpo.Offset(1, 0)
Range(rngcustrelpo1, rngcustrelpo1.End(xlDown)).Select
Selection.Copy
End Sub
However, it is not sorting the data like I am expecting. I am not sure what I am missing here.
Key:=ActiveSheet.UsedRange is a complete misunderstanding of the sort method. (Usedrange covers the whole used area on the sheet - often "empty" cells, too.) The same applies to .SetRange ActiveSheet.UsedRange. It is not bad just needless. SetRange is needed when you want to limit the area to be sorted. If you want to sort on only one key (column), then change this
ActiveWorkbook.Worksheets("BACKORDER").Sort.SortFields.Add Key:=ActiveSheet.UsedRange, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("BACKORDER").Sort
.SetRange ActiveSheet.UsedRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
to this:
With ActiveWorkbook.Worksheets("BACKORDER").Sort
.Key rngcustrelpo
.Header = xlYes
.MatchCase = False
.Order:=xlAscending
.Orientation = xlTopToBottom
.SortOn:=xlSortOnValues
.DataOption:= xlSortTextAsNumbers
.SortMethod = xlPinYin
.Apply
End With
And you can find more info here: Excel SortFields add then sort and here: Most efficient way to sort and sort syntax VBA

Sort By Column A Not Working Excel VBA

I'm trying to sort by column A from range A2-A30000 and I want to make the drop down on Column A Row 1 but it is neither sorting or enabling the dropdown on Column A Row 1. Even without VBA when I just select the A1 and press filter it automatically ends up putting the dropdown on A2. Another problem that occurs is that it only sorts column A but just moves column A around but leaves the other columns alone making the entire worksheet wrong.
ActiveWorkbook.Worksheets("Sheet3").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet3").Sort.SortFields.Add Key:=Range("A2"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("A2:A30000")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Any idea what might be wrong?
ActiveWorkbook.Worksheets("Sheet3").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet3").Sort.SortFields.Add Key:=Range("A2"), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet3").Sort
.SetRange Range("A2:BZ30000")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Thanks for the comment
You are only referencing column A; use the .CurrentRegion property to isolate the data 'island' radiating out to the first completely blank row and completely blank column. I suspect you have a text column label in A1.
With ActiveWorkbook.Worksheets("Sheet3")
With .Cells(1, "A").CurrentRegion
.Cells.Sort Key1:=.Columns(1), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
End With
End With
The recorded code works fine in some instances but sorting can be handled by VBA functionality more efficiently.
You really should know whether you have a header or not; never use xlGuess.

How to order a varying column in vba?

I want to order a column which will be at varying positions each time the macro is run. Here is my current code for completing the action:
Range(ActiveCell, ActiveCell.Offset(1000, 1)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range(ActiveCell), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range(ActiveCell, ActiveCell(1000, 1))
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
The reason for offsetting by 1000 is that I do not know how many entries there will be in the column, but I know it will be less than 1000... the offset by 1 it to order the numerical values (which are in that 1 column offset) and their company name identifiers, in the other column. Not sure how to fix the code, but in debugging, I get an error specifically after trying to run:
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range(ActiveCell), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
Any ideas?
Range(ActiveCell) does not work because ActiveCell is a range itself. So just use ActiveCell instead of Range(ActiveCell). Better yet, avoid Active... and .Select as Kyle suggested

Sorting multiple sheets - code clean up

Looking for some guidance on sorting columns across multiple sheets.
I have 2 data sets (tab1: ABC and tab2: XYZ).
I'm trying to sort both sheets (range column A to column J) by column A in descending order.
This is what I have so far... it is recorded. I would very much like to clean up my code and also look for better ways to approach sorting by columns. Any help/tips would be appreciated.
Sub sortingcolumns()
Application.Goto Reference:="ABC!A1"
ActiveWorkbook.Worksheets("ABC").sort.SortFields.Clear
ActiveWorkbook.Worksheets("ABC").sort.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("ABC").sort
.SetRange Range("A2:K187")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.Goto Reference:="XYZ!RC"
ActiveWorkbook.Worksheets("XYZ").sort.SortFields.Clear
ActiveWorkbook.Worksheets("XYZ").sort.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("XYZ").sort
.SetRange Range("A2:J179")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Since you are using "with" you can combine those into one bigger with statement:
With ActiveWorkbook.Worksheets("ABC").sort
.SortFields.Clear
.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:= _
xlSortTextAsNumbers
.SetRange Range("A2:K187")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Also, you can remove the .header, .matchcase, .orientation, .sortmethod if you don't need to sort by those.
call sortingcolumns ActiveWorkbook.worksheets("ABC"), 2, 187
call sortingcolumns ActiveWorkbook.worksheets("XYZ"), 2, 179
Sub sortingcolumns(sht as Worksheet, First as Integer, Last as Integer)
With sht.sort
.sortfields.clear
.sortfields.add Key:=Range("A1"), SortOn:=xlSortOnValues, Order:=xlDescending, _
DataOption:=xlSortTextAsNumbers
.setrange = sht.range("A" & First & ":K" & Last)
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
You could modify it to provide the first and last columns, as well, then you have a nice utility function that can sort any range for you just by passing the appropriate parameters.
I like to fully qualify all objects e.g. ActiveWorkbook becomes Excel.ActiveWorkbook. This is a personal choice.
Also I like to avoid Active... objects so if this code only needs to act on the workbook where the code is stored then switch to ThisWorkbook
With Excel.ThisWorkbook.Worksheets("ABC").sort
.SortFields.Clear
.SortFields.Add _
Key:=Range("A1"), _
SortOn:=Excel.xlSortOnValues, _
Order:=Excel.xlDescending, _
DataOption:= Excel.xlSortTextAsNumbers
.SetRange Range("A2:K187")
.Header = Excel.xlNo
.MatchCase = False
.Orientation = Excel.xlTopToBottom
.SortMethod = Excel.xlPinYin
.Apply
End With
If it needs to act on a separate workbook then use an object variable. For example if the target columns are in a book called foo.xlsx (that we assume is open)
Dim myFooBk As Excel.workbook
Set myFooBk = Excel.workbooks("foo.xlsx")
With myFooBk.Worksheets("ABC").sort
.SortFields.Clear
.SortFields.Add _
Key:=Range("A1"), _
SortOn:=Excel.xlSortOnValues, _
Order:=Excel.xlDescending, _
DataOption:= Excel.xlSortTextAsNumbers
.SetRange Range("A2:K187")
.Header = Excel.xlNo
.MatchCase = False
.Orientation = Excel.xlTopToBottom
.SortMethod = Excel.xlPinYin
.Apply
End With
Also the with could be altered slightly by moving the .Sort inside the clause:
Dim myFooBk As Excel.workbook
Set myFooBk = Excel.workbooks("foo.xlsx")
With myFooBk.Worksheets("ABC")
.sort.SortFields.Clear
.sort.SortFields.Add _
Key:= .Range("A1"), _ '<<more specific now as `.` infront of Range
SortOn:=Excel.xlSortOnValues, _
Order:=Excel.xlDescending, _
DataOption:= Excel.xlSortTextAsNumbers
.sort.SetRange .Range("A2:K187") '<<more specific now as `.` infront of Range
.sort.Header = Excel.xlNo
.sort.MatchCase = False
.sort.Orientation = Excel.xlTopToBottom
.sort.SortMethod = Excel.xlPinYin
.sort.Apply
End With
Yes, you can shorten it substantially:
Sub sortingcolumns()
Worksheets("ABC").Range("A2:K187").sort key1:=Range("A1"), Order1:=xlDescending
Worksheets("XYZ").Range("A2:J179").sort key1:=Range("A1"), Order1:=xlDescending
End sub
I made the following changes:
I used the (old) range.sort construct instead of the (newer) worksheet.sort. With the old construct, you simply identify the range to sort and then apply the .sort method with the appropriate arguments. The newer one is also more flexible but also more complicated to use.
The only arguments you need are key1 and Order1. If you wanted to sort ascending, you could also eliminate the order1 argument; then you'd have just one argument.
If you don't specify an argument, Excel will use the default. All of the arguments in your snippet are the default arguments for the sort method. Therefore you don't need to specify them.