Building a self-sorting list
I haven’t posted in a good while. I’ve done over half the Euler problems, but haven’t had the time to research the high-numbered ones considering I might even understand them. Now that I’ve retired from my second career, and my third is only part-time, maybe I’ll get back to it. Today is something perhaps more useful…to have a list of names, specifications, part numbers, etc and have them self-sort, de-duplicate, and collapse without ever having to go to the Sort Menu. Add a member to the bottom, and it flows through. Replace or paste over the data, and Excel turns the crank. Unique values appear, and no VBA is involved. This was a monthly chore in Job #2 for sometimes as many as 8000 email addresses.
Assume in Column A are 1000 (fantasy) names, in random order. These names were generated by using this website four times. Rice University and Dr. Chris Brown have provided name generation tools for many spoken languages. Your Column A might look something like this:
| A | B | |
|---|---|---|
| 1 | Alfred Sundagger | =IF(LEN(A1)>0,COUNTIF(A:A,”<”&A1)+COUNTIF($A$1:$A1,”=”&A1),”") |
| 2 | Aki Stonesaber | =IF(LEN(A2)>0,COUNTIF(A:A,”<”&A2)+COUNTIF($A$1:$A2,”=”&A2),”") |
| 3 | Yrre the Carver | |
| 4 | Alfred Birchleaf | |
| 5 | Olaf the Dagger | |
| 6 | Isen Grimboldson | |
| 7 | Eagle Arianson | |
| 8 | Besyrwan Odonson | |
| 9 | Onund Boarherder | |
| 10 | Berdoi of the Radiant Face | |
| 11 | Azhar Fahim | |
| 12 | Osric the Hostler | |
| 13 | Yasha the Hare | |
| 14 | Warian Pikethrower | |
| 15 | Konrad Firelash | |
| 16 | Faran Stillstoke |
The formula in B1 tests if there in anything of length in A1. I’ve found that the LEN() function always returns a value that agrees with my ol’ Mark 1 Mod 0 eyeballs, and empty text doesn’t mislead me. If there is something of length in A1, then COUNTIF() everything in A:A that is less than A1. This uses Excel’s lexicographic algorithms, and that opinion may differ from what you want, but I’ve never had a problem with it. Add to that count using mixed references the COUNTIF() of everything between $A$1 and $A1 inclusive that equals $A1. When we fill down this will become COUNTIF($A$1:$A2,”=”&A2) in A2. Otherwise, if there is nothing of length, place empty text (””-double double quotes). Fill down well below the extent of values in A:A.
Column B now looks something like this:
| A | B | C | |
|---|---|---|---|
| 1 | Alfred Sundagger | 43 | =IF(ROW()<=COUNT(B:B),SMALL(B:B,ROW()),”") |
| 2 | Aki Stonesaber | 25 | |
| 3 | Yrre the Carver | 971 | |
| 4 | Alfred Birchleaf | 39 | |
| 5 | Olaf the Dagger | 660 | |
| 6 | Isen Grimboldson | 470 | |
| 7 | Eagle Arianson | 240 | |
| 8 | Besyrwan Odonson | 144 | |
| 9 | Onund Boarherder | 683 | |
| 10 | Berdoi of the Radiant Face | 136 | |
| 11 | Azhar Fahim | 110 | |
| 12 | Osric the Hostler | 693 | |
| 13 | Yasha the Hare | 960 | |
| 14 | Warian Pikethrower | 944 | |
| 15 | Konrad Firelash | 541 | |
| 16 | Faran Stillstoke | 303 |
The formula in C1 tests if the row number is less than or equal to the count of the numbers in Column B. If it is, put the the smallest number there from Column B:B in ROW() order, otherwise put empty text. After filling down as far as in Column B, Column C is just 1 through the extent of your data in Column A. The use of SMALL() is what accommodates blank cells in A:A.
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Alfred Sundagger | 43 | 1 | =IF(ROW()<=COUNT(B:B),INDEX(A:A,MATCH(C1,B:B,0),1),”") |
| 2 | Aki Stonesaber | 25 | 2 | |
| 3 | Yrre the Carver | 971 | 3 | |
| 4 | Alfred Birchleaf | 39 | 4 | |
| 5 | Olaf the Dagger | 660 | 5 | |
| 6 | Isen Grimboldson | 470 | 6 | |
| 7 | Eagle Arianson | 240 | 7 | |
| 8 | Besyrwan Odonson | 144 | 8 | |
| 9 | Onund Boarherder | 683 | 9 | |
| 10 | Berdoi of the Radiant Face | 136 | 10 | |
| 11 | Azhar Fahim | 110 | 11 | |
| 12 | Osric the Hostler | 693 | 12 | |
| 13 | Yasha the Hare | 960 | 13 | |
| 14 | Warian Pikethrower | 944 | 14 | |
| 15 | Konrad Firelash | 541 | 15 | |
| 16 | Faran Stillstoke | 303 | 16 |
The formula in D1 tests the ROW() against the COUNT() again, and if ROW() is less than or equal to the COUNT(), specify zero as the third argument and find the exact MATCH() of the number in Column C:C within Column B:B, and then INDEX down Column A:A that far and return that result. Otherwise, put empty text. Fill down as far as in Columns B and C. After filling down, the list is sorted, and might look something like this:
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Alfred Sundagger | 43 | 1 | Aart Moonhammer |
| 2 | Aki Stonesaber | 25 | 2 | Aart Moonhammer |
| 3 | Yrre the Carver | 971 | 3 | Aart the Millwright |
| 4 | Alfred Birchleaf | 39 | 4 | Aart Whiteson |
| 5 | Olaf the Dagger | 660 | 5 | Aberri of the White Heart |
| 6 | Isen Grimboldson | 470 | 6 | Aberri the Thieving Wizard |
| 7 | Eagle Arianson | 240 | 7 | Acennan Badgerrunner |
| 8 | Besyrwan Odonson | 144 | 8 | Acennan Kenricsson |
| 9 | Onund Boarherder | 683 | 9 | Adei of the Red Ruins |
| 10 | Berdoi of the Radiant Face | 136 | 10 | Adolphus Blackbird |
| 11 | Azhar Fahim | 110 | 11 | Adolphus Blackbird |
| 12 | Osric the Hostler | 693 | 12 | Adolphus Stillearth |
| 13 | Yasha the Hare | 960 | 13 | Adrik Yakovovich |
| 14 | Warian Pikethrower | 944 | 14 | Aethelred Awierganson |
| 15 | Konrad Firelash | 541 | 15 | Aethelred Darkseed |
| 16 | Faran Stillstoke | 303 | 16 | Ageio the Fastidious Sorceror |
Next post we’ll de-dupe the list and then collapse it to unique entries.
…mrt



