0

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 |
1
  • 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. Aug 2 at 21:00
1

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.

4
  • 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.
    – Nicryc
    Aug 1 at 15:39
  • Maybe org-aggregate can do the sorting? Otherwise, I'd look into a source code block.
    – NickD
    Aug 2 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.
    – Nicryc
    Aug 4 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.
    – Nicryc
    Aug 13 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.