Forum Discussion
Excel - sorting rows by balance due
Generally speaking, the answer to such questions depends on what your use case is - do you just need to see the open balances or do you need to be able to interact with the rows that have the open balances? If you just need to see them, you can write a dynamic array formula that uses sortby, filter, etc. and set up your data view however makes sense. If you need to edit the data, that is more complicated since there is not, so far as I know, a way to have data in a table automatically sort as you add/change data.
The solution for viewing/editing the data in place (outside of a VBA type solution or other more "outside" excel tools as NikolinoDE suggested) is to manually update your sort. This can be accomplished in a couple of ways, but a relatively simple way (I believe PeterBartholomew1 uses this one) is to concatenate the columns you wish to sort by into a single helper column and then sort by that column. I believe he uses a character like "-" or some such to split the text strings and takes advantage of textjoin, but I could be wrong. Despite the helper column, I tend to think that this method is probably the most conceptually efficient as involves a single, straightforward join formula combined with sorting as needed on the helper column. Keep in mind that Peter offered this solution before sortby was generally available.
What I would likely do, depending on the particular need, is write a formula to assign an integer to a helper column representing the sort order of that row and then sort by the helper column. So, for instance, I might take the table range which includes the columns I wish to sort by and includes an additional "primary id" or "control number" type column, i.e. a column with relatively simple data to search and find unique values, preferably sortable. So if you don't have a primary column already, just add one, number it from 1 to whatever, but make sure the values are fixed (meaning you copy and paste the integer values if you number the columns using a formula). Then do something like use sortby for the columns of interest, and then add a similar control number to the sorted array. You then xlookup the control number for the original array in the sorted array and return the sorted array's control number. After that setup, from then on you can simply sort by the column with the sorted array's control number and get your current sorted state. Only thing you have to be sure to do is to continue adding control numbers to each new row of an array.
Note that the general difference between my approach and Peters (besides my taking advantage of the new sortby forumula) is that he sorts by the data directly whereas I create an "id" that sort of hides the data behind something that looks prettier. In both cases, the impact is the same - you are adding a new column to your data array that you have to manually sort by every time you want the most up-to-date ordering of your data.
So say you have an array named "sample_array" with these headers and values:
orig_unsorted_id | color | amount | balance | |
1 | 0 | |||
2 | 5 | |||
3 | 0 | |||
4 | 25 | |||
5 | 0 |
you add a column called "sorted_id" and insert the following formula (I used a match to get the column index for a header in case you aren't using excel's table feature - if you are, you could just use, e.g., sample_array[orig_unsorted_id]):
=LET(
target_orig_id, [@[orig_unsorted_id]],
source_array, sample_array[#All],
primary_id_col_name, "orig_unsorted_id",
sort_by_col_name, "balance",
source_array_data, DROP(source_array, 1),
source_array_headers, TAKE(source_array, 1),
balance_col, CHOOSECOLS(source_array_data, MATCH(sort_by_col_name, source_array_headers, 0)),
orig_id_col, CHOOSECOLS(source_array_data, MATCH(primary_id_col_name, source_array_headers, 0)),
sorted_orig_id_col, SORTBY(orig_id_col, balance_col, -1),
return_array, SEQUENCE(ROWS(source_array_data)),
XLOOKUP(target_orig_id, sorted_orig_id_col, return_array, "check_values")
)
you should end up with:
orig_unsorted_id | color | amount | balance | sort_order |
1 | 0 | 3 | ||
2 | 5 | 2 | ||
3 | 0 | 4 | ||
4 | 25 | 1 | ||
5 | 0 | 5 |
you then sort by the "sorted_id" column. Every time you update a value or add a new row, you just have to re-sort by the sorted_id column.
You should get the following after the first sort:
orig_unsorted_id | color | amount | balance | sort_order |
4 | 25 | 1 | ||
2 | 5 | 2 | ||
1 | 0 | 3 | ||
3 | 0 | 4 | ||
5 | 0 | 5 |
You can enhance this sort method as necessary, including filtering the original array before sorting, filtering it after and resorting, etc.