# Org mode: Using elisp formula to automatically sort tables

I'm trying to use table formulas to automatically sort my tables. I have made this:

``````| Animal   | Nombre |
|----------+--------|
| Bison    |      5 |
| Vache    |      4 |
| Aligator |      7 |
| Chèvre   |      4 |
| Wapiti   |      6 |
| Sanglier |     41 |
| Porc     |      0 |
#+TBLFM: \$1 = '(org-table-sort-lines nil ?a)
``````

However it produces a weird result, it replaces all string in the `\$1` column by the number `2`:

``````| Animal | Nombre |
|--------+--------|
|      2 |      7 |
|      2 |      5 |
|      2 |      4 |
|      2 |      0 |
|      2 |     41 |
|      2 |      4 |
|      2 |      6 |
``````

That's obviously not what I want to do and I have no idea why it is doing this.
I tried using a relative notation to start from the second row:

``````#+TBLFM: @<<\$1 = '(org-table-sort-lines nil ?a)
``````

The result is better but still not perfect:

``````| Animal   | Nombre |
|----------+--------|
| 2        |      7 |
| Bison    |      5 |
| Chèvre   |      4 |
| Porc     |      0 |
| Sanglier |     41 |
| Vache    |      4 |
| Wapiti   |      6 |
``````
• Why do you want to use a Elisp formula to sort your table? This question seems like the XY problem (X being "sort a table", Y being "use a formula to sort a table"). If your overall goal is to sort a table, then you can use `org-sort` `(C-c ^)` while your cursor is on the table. Commented Aug 2, 2021 at 21:00

`org-table-sort-lines` does not return the sorted table as your first formula assumes: instead, it operates by side-effect, modifying the table in place. It just so happens that the last thing it calls is `(move-column 2)` to move the cursor to the second column (of the screen, not the table - I'm oversimplifying here, but the details really don't matter much), and that function returns the column number (in this case 2). That is then the value assigned to the whole of the first column. Turn on formula debugging with `C-c {` to see what it's doing: you'll see that it sorts the table in a first pass and then assigns 2 to the first column when you continue.

Your second formula "mostly works" because it's only affecting directly the top row of the table: again, the table is sorted by side-effect and then the value it returns is assigned to the `@1\$1` cell of the table. What you really want to do is to throw away the result, but I don't know of a way to do that.

As in your other question, however, I suggest you do NOT use formulas for such operations. You can interactively sort the table once and for all: you do not need to do that from a formula.

EDIT: Here is an implementation of my suggestion to use a source code block:

``````#+name: animals
| Animal   | Nombre |
|----------+--------|
| Bison    |      5 |
| Vache    |      4 |
| Aligator |      7 |
| Chèvre   |      4 |
| Wapiti   |      6 |
| Sanglier |     41 |
| Porc     |      0 |

#+begin_src elisp :var tbl=animals :colnames yes
(sort tbl (lambda (x y) (string-lessp (car x) (car y)))))
#+end_src

#+RESULTS:
| Animal   | Nombre |
|----------+--------|
| Aligator |      7 |
| Bison    |      5 |
| Chèvre   |      4 |
| Porc     |      0 |
| Sanglier |     41 |
| Vache    |      4 |
| Wapiti   |      6 |
``````

This depends on the fact that the table is represented in lisp as a list of rows and each row is a list of cells, with non-numeric cells represented as strings , e.g. the above table is represented like this:

``````(("Bison" 5) ("Vache" 4) ("Aligator" 7) ("Chèvre 4) ("Wapiti" 6) ("Sanglier" 41) ("Porc" 0))
``````

The `sort` function sorts a list using a predicate, i.e. a function that takes two arguments and returns non-nil if the first argument should sort before the second. In our case, the elements are two-element lists and we need to take the `car` of each element to get the names, which we compare using `string-lessp`. Do `C-h v sort` to find out more about the `sort` function.

• The thing is that in reality my tables are generated from a bigger root table using the org-aggregate module. So every time a value change in this main table, the resulting tables are completely regenerated, so it isn't a one-time operation anymore. Commented Aug 1, 2021 at 15:39
• Maybe `org-aggregate` can do the sorting? Otherwise, I'd look into a source code block. Commented Aug 2, 2021 at 18:32
• Unfortunately no, `org-aggregate` can't do that. Thank you for your suggestion and your explanation I guess it will do the trick. Commented Aug 4, 2021 at 19:10
• The module `org-aggregate` has just been updated and now support sorting. Thanks for your response I guess it could help for other cases. I mark it as a solution. Commented Aug 13, 2021 at 20:32