Add subheadings to all headings in an org-file at some level

| categories: org-mode | tags:

On the org-mode mailing list someone asked how to insert a sub-heading with properties at some level in a tree. The application is they have a tree they use to store grades for a class, and they want to easily add a new level for an assignment for each student. The new level will have a title, and some properties to store the grade in.

This can be done with org-map-entries. This will visit all the headlines and run a function. For this example, students are at level 3, and we want to add a headline at level 4 with the title "Essay 2", and with a property for the grade. The following code does this.

(let ((MATCH t)
      (SCOPE 'file)
      (SKIP nil)
      (spacing nil))
  (org-map-entries
             (lambda ()
               (let ((level (nth 1 (org-heading-components))))
                 (if (= level 3)                     
                     (save-restriction
                       (org-narrow-to-subtree)
                       (goto-char (point-max))
                       
                       (org-insert-heading)
                       (insert "Essay 2\n")
                       (org-entry-put (point) "GRADE" nil)
                       ;; now cut tree and paste at level 4
                       (org-cut-subtree)
                       (org-paste-subtree 4)
                       )))) MATCH SCOPE SKIP))

This code does not check for duplicates, so if you run it again, you get another set of entries for Essay 2. That might actually be hard to prevent without setting a unique ID for each new entry, something like Student-Name-Essay-2.

I found it necessary to cut and paste the new subtree to get to the level I wanted because in Class two, there were not already subtrees at level 4, and the code above went into a recursion loop.

I could not figure out why I had to narrow to the subtree, and go to the end of that subtree. Without doing that there was another recursion loop.

Below here is a slightly modified subtree showing a structure of two courses an instructor might have, with students in headlines at level 3. The code above has already added headlines at level 4 for "Essay 2". You have to check out the actual org-file to see that the properties are there.

For application, the code above could be put in an emacs-lisp file as an interactive command you could call with M-x.

1 Class One

1.1 Student 1

1.1.1 Essay One

Here is my comment to the student on their essay. The grade/mark itself will be stored as a property or priority. <<<<<<<<<<<<<<HERE I'd like to add a node for "Essay Two"

1.1.2 Essay 2

1.2 Student 2

Comment on John's essay. <<<<<<<<<<<<<< I to add the same node skeleton here, automatically

1.2.1 Essay 2

1.3 Student 3

1.3.1 Essay One

Comment on Sally's essay. <<<<<<<<<<<<<< And here.

1.3.2 Essay 2

2 Class Two

2.1 Student 1

2.1.1 Essay 2

2.2 Student 2

2.2.1 Essay 2

Copyright (C) 2013 by John Kitchin. See the License for information about copying.

org-mode source

Discuss on Twitter