Turning an Org Mode outline into an HTML table with a column for more notes

| emacs, org

The 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:

Two-column table

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!

You can view 10 comments or e-mail me at sacha@sachachua.com.

10 comments

Shreyas Ragavan

2019-06-10T13:21:56Z

Thank you! this is totally awesome.

jueqingsizhe66

2019-06-16T15:58:54Z

org-export-resolve-link is void

Oh, 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.

Very 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!

Sacha, with the complete git version of Org, the output is as expected. Thanks for the ideas!

Woohoo! 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...

https://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:18Z

Can u do something like this in Vim?

Maybe you can figure out how! :) I like Emacs, so that's what I use.

Hi 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 :


* Activity ideas :noexport:
** Gross motor
*** Balance on one leg
*** Coast on the balance bike
Long Paragraph
** Fine motor
*** Cut along a curve or shape

Thank you very much for your help.