Excel VBA Sort, error 1004 on .Apply - vba

I'm having issues using sort in VBA. I saw this thread for which the answers don't work for me: Sort in VBA
I believe there is a maximum nr of records on which you can sort. Is that correct? I want to sort on 4 criteria in a sheet/table with 188,000 records.
I always get an error on the .Apply statement: "run-time error '1004': application-defined or object-defined error"
Below my code:
Sub Sort_Table()
Dim sht As Worksheet
Set sht = ActiveWorkbook.Worksheets("Sheet1")
sht.Activate
With sht.ListObjects("Table1").Sort
.SortFields.Clear
.SortFields.Add Key:=Range("Table1[Date]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Country Code]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Rating]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Segment]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub

Potential problem
Actually maybe you shouldn't the Apply inside the With since your object is really updated after the end of the With block.
For instance here your parameters (.SortFields etc ...) are not yet set when you use Apply. I'm not 100% sure because I doesn't have EXCEL to test right now, and it seem not everyone have this problem with this code as you pointed out, but that may be a reason.
(potential) Solution
Try doing:
With sht.ListObjects("Table1").Sort
.SortFields.Clear
.SortFields.Add Key:=Range("Table1[Date]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Country Code]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Rating]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.SortFields.Add Key:=Range("Table1[Segment]"), SortOn:=xlSortOnValues, Order:=xlAscending ', DataOption:=xlSortNormal
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
End With
sht.ListObjects("Table1").Sort.Apply
Tell me if this doesn't solve the issue
Other potential problems/solutions
The sheet you work on (Sorting) is protected
Check out this question: Excel VBA Sort
Hope it helped anyway ...

Related

Custom sort dynamic range using VBA

I receive an Excel file every morning which I like to sort into a more logical manner. All of the column headings are always the same, but the number of rows may change.
I'm trying to put together a macro that highlights the entire region (starting in B2). It needs to sort column C (ascending), G (descending), H (ascending) and I (descending).
I started off by using the macro recorder and am now trying to clean up the code it spat out.
So far I've managed to put together code that selects the region from B2 to the right and then down. Then when defining the sorting criteria for each column, I've tried to make sure that the range selected goes from the top of the list in row 3 (row 2 has headers, row 3 is first item in the list) and then dynamically selects down for each relevant column. However, after the With statement I'm struggling to get the range to be dynamic (it's just the macro-recorded static range still).
I'm also getting an 'Run-time error '1004': Application-defined or object-defined error' after .Apply.
Sub Macro1()
Range("B2").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("G3",
Range("G3").End(xlToRight)) _
, SortOn:=xlSortOnValues, Order:=xlDescending,
DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("C3",
Range("C3").End(xlToRight)) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("H3",
Range("H3").End(xlToRight)) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("I3",
Range("I3").End(xlToRight)) _
, SortOn:=xlSortOnValues, Order:=xlDescending,
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("B2:Q31") ' NOT SURE HOW TO MAKE DYNAMIC HERE
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply ' GETTING ERROR HERE
End With
End Sub
Just had to change the Range to Selection as you already have dynamically selected the Range in work:
Sub Macro1()
Range("B2").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("G3", Range("G3").End(xlDown)), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("C3", _
Range("C3").End(xlDown)), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("H3", _
Range("H3").End(xlDown)), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("I3", _
Range("I3").End(xlDown)), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
'
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range(Selection.Address)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
See if it works now.

Unable to get the Sort property of the Range class

I'm getting the above error when performing a sort. I've fully qualified all objects and checked that my variables hold the correct values. The error occurs on the first line:
With ws.Columns("A:E").Sort
.SortFields.Clear
.SortFields.Add Key:=ws.Range("A2:A" & oldLastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange ws.Range("A1:E" & oldLastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
It doesn't seem to matter how I refer to the range, each of these gives the same error:
With ws.Range("A:E").Sort
With ws.Range("A1:E" & oldLastRow).Sort
There is data in each cell of the range and the columns have headers. What could be causing this problem?
ws.Columns("A:E").Sort is calling the Sort function of a Range which is different from the Sort class of the worksheet:
(hit F2 in the VBA editor to get to that screen)
So your code will likely work if you just remove the .Columns("A:E") of your snippet e.g.:
With ws.Sort
.SortFields.Clear
.SortFields.Add Key:=ws.Range("A2:A" & oldLastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange ws.Range("A1:E" & oldLastRow)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
You are already saying what you want to sort with .SetRange ws.Range("A1:E" & oldLastRow) so you can see it is a bit redundant to also have it in the With statement (as well as generating the error).
PS I get
Run-time error '438': Object doesn't support this property or method

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 a varying size table in excel

What I'm trying to do is select a table in a spreadsheet, and then sort according to 2 different columns
I generated this code with the record macro option. The table changes in size which is why I have used the xlDown, unfortunately the code later references the exact cells "B4:B52". Any idea how I might solve this issue?
Range("B4:J4").Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range( _
"B4:B52"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range( _
"G4:G52"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("B4:J52")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Since you are sorting a Table (ListObject in VBA), you'll want to refer to it. This will dynamically adjust to encompass entire table columns. In this example the column headers/names to be sorted are "Data1" and "Data3":
Sub SortTable()
Dim lo As Excel.ListObject
'change this assignment to suit your table location and name
Set lo = ActiveWorkbook.Worksheets("Sheet1").ListObjects("Table1")
With lo
.Sort.SortFields.Clear
.Sort.SortFields.Add _
Key:=Range("Table1[data1]"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
.Sort.SortFields.Add _
Key:=Range("Table1[data3]"), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With .Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End Sub
I would sort the column in the table in the following way:
Sub SortingTable()
Dim ws As Worksheet
set ws = ActiveSheet
Dim target_table As ListObject
Set target_table = ws.ListObjects(wsName)
Dim sort_column_index As Long
sort_column_index = target_table.ListColumns("ColumnToBeSortedName").Index
Dim sort_column As Range
Set sort_column = target_table.ListColumns(sort_column_index).Range
' Applying the sorting to the table
With target_table.Sort
.SortFields.Clear
.SortFields.Add Key:=sort_column _
, SortOn:=xlSortOnValues, Order:=xlAscending _
, DataOption:=xlSortNormal
.Apply
End With
End Sub
In fact, the only difference is that you declare a Range and assign it to the specific table column that should be sorted. Doing it this way, you're able to apply the macro to tables on different sheets assuming that the tables contain the column with name "ColumnToBeSortedName".

Excel 2007 returns `Application-defined or object-defined error`

I have Excel 2007 and Windows XP
When this code runs:
Columns("A:G").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("B2:B20000") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("A2:A20000") _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("F2:F20000") _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("A1:G20000")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.Calculation = xlCalculationAutomatic
It throws an error at .Apply:
Application-defined or object-defined error
One thing to note is that Application.Calculation = xlCalculationManual
Also, I cannot do anything in the UI except for switching tabs and opening the office menu, and I have to go to the Task Manager and click end task to exit, whereupon it asks if I want to save. Pressing cancel does not fix it. If I hit "no", it just closes. If I hit yes, it calculates and then asks if I want to have it recover my work.
I moved Application.Calculation = xlCalculationAutomatic to right before it and that fixed it.
Application.Calculation = xlCalculationAutomatic
Columns("A:G").Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("B2:B20000") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("A2:A20000") _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("F2:F20000") _
, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("A1:G20000")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Edit: Oops, it doesn't after all.
Well, it turned out that it doesn't happen unless the computer is loaded with running programs. I did a pretty good rewrite of it and it is much faster now. The problem seems to be taken care of.