Sort by any number of columns, with the comparison stated: numbers by value, dates by day, text by a collation you choose
Initializing in your browser…
Keep and reorder chosen columns, with the list built from the widest row so a field beyond the header is not dropped
Classify every column against a decider rather than a regex: calendar-checked dates, RFC 4291 addresses, and leading zeros kept out of integer columns
Rename columns under a stated convention, with two that would end up with the same name numbered rather than left to collide
A price list has to go Category ascending, then Price high to low. The price column holds a grouped thousand, an N/A and a blank, which is what makes the ordering a decision rather than a formality.
Two rules: Category ascending as Text, Price descending as Number
Keyboard,Accessories,129.99 Mouse,Accessories,N/A Laptop,Electronics,999 Monitor,Electronics,"1,299" Webcam,Accessories,89 Cable,Accessories,
Sorted
Keyboard,Accessories,129.99 Webcam,Accessories,89 Mouse,Accessories,N/A Cable,Accessories, Monitor,Electronics,"1,299" Laptop,Electronics,999 The rule reads: 4 values sort by number, 1 could not be read as number, 1 blank, and those go last.
Inside Accessories the two prices run high to low, then the value that is not a number, then the blank, and they stay at the end even though the direction is descending. 1,299 is read as one thousand two hundred and ninety nine rather than as 1, which is what parseFloat returns for it. Text compares by Unicode code point, so the same file sorts the same way for every reader rather than following whoever opened it.
Sort a CSV by any number of columns, with the comparison written out on the page rather than guessed. Numbers sort by value, dates by the day they name, text by an order that is the same for every reader, and anything that cannot be read as the column’s type is told to you rather than quietly given a place.
A sorter is only correct with respect to a comparison, so this one states its comparison and checks its own output against it. Every cell gets a sort key once, before anything is compared, and the comparison is a lexicographic walk over those keys. That is what makes the order transitive: there is no branch that can compare one pair of rows one way and the next pair another. It also means a column is read once rather than once per comparison, so 100,000 rows sort in about a fifth of a second.
Each rule picks a column, a direction and an ordering. Automatic looks at the column and says what it chose and why: all numbers, all dates, digits mixed with text, or none of those. Number reads a decimal literal with the decorations a spreadsheet adds (grouped thousands, a currency symbol, a percent sign, accounting parentheses) and nothing else, so 12abc is not the number 12 and 0x1F is not zero. Date reads calendar dates, so 29 February in a common year is not a date, and the day/month order is settled by the whole column with the cell that proved it named on the page. Natural makes item2 come before item10. Length counts characters as Unicode code points.
Text compares by Unicode code point by default, which is deliberate: a locale collation puts the same file in a different order for a Swedish reader, where the ring-A sorts after Z, than for a German one, where it sorts with A. If you want a language’s own alphabetical order you choose the language and the page says which one is in force. Case is a value rather than a tie, so apple, Apple and APPLE get three places instead of one, unless you ask for a case-insensitive collation.
Blank cells, and values that cannot be read as the column’s ordering, are counted separately and go to one end whichever direction the values are sorted in, which is the convention SQL calls NULLS LAST; you can put them first instead. Rows that tie on every rule keep the order they had in the file. After every sort the page re-checks that the result really is in order under the comparison it just described, and says so.
Sort by revenue or score, with the rows that have no number in them collected at the end rather than scattered through the ranking.
Sort a date column by the day it names, including day-first dates that the JavaScript Date constructor refuses outright.
Code point order does not depend on the reader’s browser locale, so two people sorting the same file get the same file.
Rule 1 is Category ascending as Text and rule 2 is Price descending as Number. Rows group by category and then run high to low inside each one, so the cheapest item in a category is the last of that group.
A column of item2, item10, item1 sorted as Natural gives item1, item2, item10. Automatic picks Natural on its own when every value mixes digits with other characters.
A price column holding 999, 1,299, N/A and a blank sorts the two numbers by value, then N/A, then the blank, and the rule says "2 values sort by number, 1 could not be read as number, 1 blank, and those go last".
Yes, and it says what counts as a number. A cell is read as a number only if it is a decimal literal, possibly with grouped thousands, a currency symbol, a percent sign or accounting parentheses. 12abc and 0x1F are not numbers here, where parseFloat reads them as 12 and 0.
The whole column decides. Any cell whose first field is above 12 proves the column is day first, and the page names that cell. The JavaScript Date constructor refuses 15/01/2024 outright, which is why a date sort of a European column used to come out half sorted.
That is Unicode code point order, which is the default because it is the same for every reader. Turn on Ordering options and choose a language to get that language’s alphabetical order instead, where case usually does not separate values.
Last by default, in both directions, along with any value that could not be read as the column’s ordering. Both are counted and shown. You can put them first instead.
Yes. Rows equal under every rule keep the order they had in the file, ascending or descending.
Rows and columns are parsed and transformed in memory in your browser. No record ever reaches a server.