I am working on a project that will sort all the cells in another worksheet based on criteria. I need to activate a cell in another worksheet to make it work. I tried finding a solution but no luck.
I recorded a macro from my workbook and tweaked it a bit so it would fit my need. When I run the code, Runtime Error 1004 appears.
I need a code to replace
SetRange ActiveCell.Offset(-1, 0).Range("A1:AF30436")
Any suggestion will be appreciated.
Here's the code:
Sheets("Source").Select
ActiveWorkbook.Worksheets("Source").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Source").Sort.SortFields.Add Key:=ActiveCell.Range _
("A1:A30435"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Source").Sort
.SetRange ActiveCell.Offset(-1, 0).Range("A1:AF30436")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
when you record macro, you click on the cell in the second sheet and start the sort routine. Macro correctly recorded this.
however when you are doing this in VBA, the "active cell" could be anything and in most cases you dont need this as long as you know the datarange that you need to work with
dim ws as WorkSheet
set ws = Sheets("Source")
ws.Sort.SortFields.Clear
ws.Sort.SortFields.Add Key:=ws.Range _
("A1:A30435"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ws.Sort
.SetRange Range("A1:AF30436") ' Change here to itended dataset
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Related
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
I am trying to loop this macro (below) to go through all me data columns but need some help creating a loop or adjusting the current code to work for all columns.
Sub Trial_5()
'
ActiveCell.Offset(0, -7).Columns("A:A").EntireColumn.Select
ActiveWorkbook.Worksheets("Sheet6").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet6").Sort.SortFields.Add Key:=ActiveCell, _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet6").Sort
.SetRange ActiveCell.Range("A1:A16395")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
`enter code here`.SortMethod = xlPinYin
.Apply
End With
End Sub
do I adjust the .columns or the activecell.offset to total range??
adjusted script
Sub eachcolumndesending()
'
' eachcolumndesending Macro
' descending
'
'
Columns("A:A").Select
ActiveWorkbook.Worksheets("Sheet5").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet5").Sort.SortFields.Add Key:=Range("A1"), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet5").Sort
.SetRange Range("A2:A32")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Columns("B:B").Select
ActiveWorkbook.Worksheets("Sheet5").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet5").Sort.SortFields.Add Key:=Range("B1"), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet5").Sort
.SetRange Range("B1:B33")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
I suggest you move away from the recorded code to what VBA actually requires for a single column sort.
Sub sortAllColumns()
Dim c As Long
On Error Resume Next '<~~ may be necessary if a column breaks the sort
With Worksheets("Sheet5")
For c = .UsedRange.Columns.Count To 1 Step -1
With .Columns(c)
.Cells.Sort Key1:=.Columns(1), Order1:=xlDescending, _
Orientation:=xlTopToBottom, Header:=xlGuess
End With
Next c
End With
End Sub
Btw, you probably shouldn't have to xlGuess at the existence of a header. Either one is there (xlYes) or not (xlNo) but you know your data better than I.
I have a macro that selects a range of cells, erases the cells, sorts the data by alphabetical order and saves the file.
I need the macro to copy the selected range of cells to another excel sheet but I am not able to create the code.
The code of my macro is:
Sub SAVE1()
'
' SAVE1 Macro
'
'
Range("B8:K8").Select
Selection.ClearContents
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Add Key:=Range _
("B7:B85"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("B8").Select
ActiveWorkbook.Save
End Sub
Please let me know if you have some ideas.
Many thanks for your help.
Joao
I Have a relatively long sub that adds data to another sheet in a bunch of columns based on where its coming from. this part of the code works perfectly, however I wanted to sort all the rows in the table up to the last row that was added. the sorting code that I added on to the end works if I hard code what cells to include in the range, but my range will grow each time the sub is run so I tried to make the range include the variable I named for the next empty row (1MaxRows).
When I do this I get an error that says "400", in the past when I have gotten this error it is because i referenced the sheet or workbook wrong, but this time I didn't change any sheet references. The section of my code that gives me this error is as follows:
Columns("A:Q").Select
ActiveWorkbook.Worksheets("Raw Data").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Raw Data").Sort.SortFields.Add Key:=range("A2:A & lMaxRows" _
), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Raw Data").Sort.SortFields.Add Key:=range("B2:B & lMaxRows" _
), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Raw Data").Sort
.SetRange range("A1:Q & lMaxRows")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
I have tried changing the range codes in a handful of ways but I always either get an overflow error or a 400 error.
Thank you for the help.
You should qualify your Range calls with the correct worksheet, and you also have quotes in the wrong place in your addresses. For example:
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Raw Data")
With ws.Sort.SortFields
.Clear
.Add Key:=ws.Range("A2:A" & lMaxRows), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
.Add Key:=ws.Range("B2:B" & lMaxRows), SortOn:=xlSortOnValues, _
Order:=xlDescending, DataOption:=xlSortNormal
End With
With ws.Sort
.SetRange ws.Range("A1:Q" & lMaxRows)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
I've assumed you have properly declared and assigned a value to lMaxRows (and note that it is LMAXROWS and not 1MAXROWS with a number at the start.
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.