Export org-mode headlines to separate files

I was recently managing a set of interviews and I had my notes on all of the candidates in a single org file, with each candidate under their own top-level headline:

* J Kepler
 - Nice work on orbits

* I Newton
 - Versatile
 - Hard to work with

* C Sagan
 - Good communication skills

However, I wanted to generate a separate pdf file for each candidate that I could circulate to interviewers (since each interviewer was only interviewing a subset of applicants).

I came across this stackexchange answer that demonstrated how to build a function to export top level headlines to separate files. There are a few variations on that page, and I put together the slightly tweaked version below. All of the credit goes to stackexchange user itsjeyd for a very detailed answer. In my version I hard code it to export to pdf, save the file first, and apply the export options from the parent file to each of the new files that are created. The new files have a name taken from the headline, with spaces replaced by underscores, unless the :EXPORT_FILE_NAME: property is set for a headline.

;; export headlines to separate files
;; http://emacs.stackexchange.com/questions/2259/how-to-export-top-level-headings-of-org-mode-buffer-to-separate-files
(defun org-export-headlines-to-pdf ()
  "Export all subtrees that are *not* tagged with :noexport: to
separate files.

Subtrees that do not have the :EXPORT_FILE_NAME: property set
are exported to a filename derived from the headline text."
  (let ((modifiedp (buffer-modified-p)))
      (goto-char (point-min))
      (goto-char (re-search-forward "^*"))
      (set-mark (line-beginning-position))
      (goto-char (point-max))
       (lambda ()
         (let ((export-file (org-entry-get (point) "EXPORT_FILE_NAME")))
           (unless export-file
              (replace-regexp-in-string " " "_" (nth 4 (org-heading-components)))))
           (org-latex-export-to-pdf nil t)
           (unless export-file (org-delete-property "EXPORT_FILE_NAME"))
           (set-buffer-modified-p modifiedp)))
       "-noexport" 'region-start-level))))
  • VanLaser

    I wonder if it wouldn’t be even simpler by starting from:

    (org-element-parse-buffer 'headline)

  • Jay Dresser

    Here’s an answer I posted, using properties, for someone who wanted something similar but exported each time the file was saved:

    (defun save-headings-external ()
    “Save all headings containing special property to an external file”
    (when (string= major-mode “org-mode”)
    (goto-char (point-min))
    (let (-extfname -start -end)
    (while (re-search-forward “:PROPERTIES:” nil t)
    (when (setq -extfname (org-entry-get (point) “SAVE-TO-FILE”))
    (setq -start (point))
    (org-forward-heading-same-level 1 t)
    (write-region -start (point) -extfname)
    (message “Wrote ‘%s'” -extfname)))))))

    (add-hook ‘write-file-hooks ‘save-headings-external)