Turning an Org Mode outline into an HTML table with a column for more notes
| emacs, orgThe last time A- had a babysitter, I quickly scribbled down some ideas for activities that A- might enjoy. The babysitter found the list very helpful, so I figured I’d make a list that I could easily update as A-‘s interests change. I wanted a two-column table with space for notes, but I didn’t want to fiddle with LibreOffice or manually writing HTML. Org Mode to the rescue! To turn something like this:
* Activity ideas :noexport: ** Gross motor *** Balance on one leg *** Coast on the balance bike ** Fine motor *** Cut along a curve or shape ...
into a table like this:

I wrote this bit of code inside a #+begin_src emacs-lisp :exports results :results value html
… #+end_src
block:
(let* ((elements (org-element-parse-buffer)) (activity-ideas (org-element-contents (org-export-resolve-link "Activity ideas" `(:parse-tree ,elements))))) (format "<table><tr><th width=\"50%%\">Activity ideas</th><th width=\"50%%\">Notes</th></tr>%s</table>" (mapconcat (lambda (section) (format "<tr><td><h2>%s</h2><ul>%s</ul></td><td></td></tr>" (org-element-property :raw-value section) (mapconcat (lambda (idea) (format "<li>%s</li>" (org-element-property :raw-value idea))) (org-element-contents section) ""))) (org-element-contents activity-ideas) "")))
I can then export the buffer to HTML and get my nice neat table by itself, since the data comes from a subtree with the :noexport: tag. The code parses the elements in the buffer, looks at the children under the “Activity ideas” header, turns each child into a table row, and turns the children of those nodes into list items.
The code coincidentally takes advantage of the org-export-resolve-link
I wrote to help someone with an Org feature request. Yay for multipurpose code!
For the next step, I’ll probably put TODO state filtering in so that I can keep a long list of activities and then select a few for each category. It’s nice to have an outline I can easily update!
10 comments
Shreyas Ragavan
2019-06-10T13:21:56ZThank you! this is totally awesome.
jueqingsizhe66
2019-06-16T15:58:54Zorg-export-resolve-link is void
sachac
2019-06-16T21:42:56ZOh, you'll need the git version of Org, at least until it's included in a release. We can substitute anything that returns the element that you're interested in.
Jay Iyer
2019-07-05T18:28:00ZVery useful feature! What would be the workaround if I don't have org-export-resolve-line? Also, how to generalize function for more than 2 columns? Thanks again!
Jay Iyer
2019-07-06T00:52:15ZSacha, with the complete git version of Org, the output is as expected. Thanks for the ideas!
sachac
2019-07-09T03:02:50ZWoohoo! I saw your Org mailing list post. Nifty idea. Right now, TBLFM formulas that return newlines break the table. I wonder if it would be possible to modify table processing so that it can postpone evaluating a function until exporting...
sachac
2022-05-26T21:55:08Zhttps://lists.gnu.org/archi... is the mailing list post mentioned above. Thanks to Andres Ramirez for tracking that link down!
Jan Samborski
2019-06-22T09:21:18ZCan u do something like this in Vim?
sachac
2019-06-23T14:23:37ZMaybe you can figure out how! :) I like Emacs, so that's what I use.
spike
2021-11-03T21:46:51ZHi Sacha,
Thank you very much. I've been trying to do this for a while. Can you help me figure out how to handle the following:
1) images that are inserted in ORG's syntax, i.e.,
[[./img/a.jpg]]
so how to change its syntax to HTML and have it in the table in the same place it was in the ORG list.
2) How to handle the text that is in a new line after some level, for example, assume there's a Long Paragraph (without any stars before it) after "Coast on the balance bike" as below :
Thank you very much for your help.