1

I'd like to do some formatting on org-tables than I'm using. For example, make this table :

|----------------+----------+---------+---------+---------|
| Russia         | 12000000 | 1700000 | 4950000 | 2500000 |
| British Empire |  8904467 |  908371 | 2090212 |  191652 |
| France         |  8410000 | 1357800 | 4266000 |  537000 |
|----------------+----------+---------+---------+---------|

Look like this :

|----------------+------------+----------+----------+-----------|
| Russia         | 12 000 000 | 1700 000 | 4950 000 | 2 500 000 |
| British Empire |  8 904 467 |  908 371 | 2090 212 |   191 652 |
| France         |  8 410 000 | 1357 800 | 4266 000 |   537 000 |
|----------------+------------+----------+----------+-----------|

But I'm unable to find documentation on how cell formatting works...

1
  • 1
    There are minor tweaks that you can do to cells that hold results of calculations but there is no way to say: "I want all the cells in this range to look like this". And if you succeed in doing the above, you will probably not be able to use formulas (or, worse, they are going to give you nonsense back); plus the formatting will be destroyed when you press TAB. Org tables can be used as spreadsheets, but they have a lot of limitations when compared with a "real" spreadsheet application.
    – NickD
    Jul 26 at 22:12

1 Answer 1

3

You can duplicate the table and apply an elisp function to format the copy however you want. I don't know if the formatting function exists or not, so I made one up myself.

#+begin_src emacs-lisp
  (defun space-fmt(n)
 "Return a string representing the number N with a space inserted every 3 digits."
  (interactive)
  (let((s(reverse(mapcar #'identity  (number-to-string n))))
       (i 1)
       fmt )
  (push(pop s)fmt)
    (while s
      (if(zerop (% i 3))(push ?  fmt))
      (push (pop s)fmt)
      (setq
       i (1+ i)))
    (apply #'string fmt)))
#+end_src

#+RESULTS:
: space-fmt

#+NAME: src-tbl
|----------------+----------+---------+---------+---------|
| Russia         | 12000000 | 1700000 | 4950000 | 2500000 |
| British Empire |  8904467 |  908371 | 2090212 |  191652 |
| France         |  8410000 | 1357800 | 4266000 |  537000 |
|----------------+----------+---------+---------+---------|


#+NAME: fmt-tbl
|----------------+------------+-----------+-----------+-----------|
| Russia         | 12 000 000 | 1 700 000 | 4 950 000 | 2 500 000 |
| British Empire | 8 904 467  | 908 371   | 2 090 212 | 191 652   |
| France         | 8 410 000  | 1 357 800 | 4 266 000 | 537 000   |
|----------------+------------+-----------+-----------+-----------|
#+TBLFM: @<$<<..@>$>='(space-fmt remote(src-tbl,@@#$$#));N

Unfortunately, I failed to right-justify the columns, with the table-justify command giving weird results. I'm counting on someone smarter than me to do it.

Second version, right justification

I changed the formatting code which now needs a second parameter to represent the length of the strings in each column. I added a row to the source table to calculate the formatted length of the strings in each column. I replaced the SPACE character (#x20) by the SPACE FIGURE character (#x2007) to avoid untimely formatting imposed by the Org mode. If you can't use this character, you can change it to NO-BREAK-SPACE (#xA0), but that might not look as nice.

#+begin_src emacs-lisp
    (defun space-fmt(n w)
      "Returns a string representing the number N with a SPACE FIGURE character #x2007 ' '
           inserted every 3 digits. and padded on the left to have a length of W characters"
    (interactive)
    (let((s(reverse(mapcar #'identity  (number-to-string n))))
         (i 1)
         fmt )
      (push(pop s)fmt)
      (while s
        (if(zerop (% i 3))(push #x2007 fmt)) ;; FIGURE SPACE 
        (push (pop s)fmt)
        (setq
         i (1+ i)))
      (while (<(length fmt)w)(push #x2007 fmt))
       (apply #'string fmt)))
  ;;;-----------------------------
 #+end_src

#+RESULTS:
: space-fmt

#+NAME: src-tbl
|----------------+----------+---------+---------+---------|
| Russia         | 12000000 | 1700000 | 4950000 | 2500000 |
| British Empire |  8904467 |  908371 | 2090212 |  191652 |
| France         |  8410000 | 1357800 | 4266000 |  537000 |
|----------------+----------+---------+---------+---------|
| Column width   |       10 |       9 |       9 |       9 |
#+TBLFM: @>$<<..@>$>='(let ((l(apply #'max (mapcar #'length (list @<..@>)))))(+ l (/ l 3)))



#+NAME: fmt-tbl 
|----------------+------------+-----------+-----------+-----------|
| Russia         | 12 000 000 | 1 700 000 | 4 950 000 | 2 500 000 |
| British Empire |  8 904 467 |   908 371 | 2 090 212 |   191 652 |
| France         |  8 410 000 | 1 357 800 | 4 266 000 |   537 000 |
|----------------+------------+-----------+-----------+-----------|
#+TBLFM: @<$<<..@>$>='(space-fmt remote(src-tbl, @@#$$#) remote(src-tbl,@>$$#));N::@<$<..@>$<=remote(src-tbl,@@#$$#)
1
  • That is a pretty good answer: if you can do the justification, it would answer the OP's question very well. And my fears about formulas giving wrong results can be alleviated by applying them to the original table, leaving the modified copy to be used for display only.
    – NickD
    Jul 28 at 3:24

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.