0

I have a file ~/documents/foo.org which looks like

#+TBLNAME: data
|                  |                  |        | p01a | p01b | p02 | p03 |
|------------------+------------------+--------+------+------+-----+-----|
| e-mail           | name             |  total |    5 |    5 |  10 |  25 |
|------------------+------------------+--------+------+------+-----+-----|
| gh01@beatles.edu | Harrison, George | 80.00% |    5 |    4 |   7 |  20 |
| jl01@beatles.edu | Lennon, John     | 75.56% |    5 |    3 |   5 |  21 |
| pm01@beatles.edu | McCartney, Paul  | 86.67% |    5 |    5 |   6 |  23 |
| rs01@beatles.edu | Starr, Ringo     | 82.22% |    5 |    4 |   6 |  22 |
#+TBLFM: @3$3..@>$3=100*vsum($4..$>)/vsum(@2$4..@2$>);%.2f%%

I would like to write a program that takes the information in this table and generates new org files organizing each person's data separately. For example, the first new file should be ~/documents/individual-reports/harrison-gh01.org and should look something like

#+Title: George Harrison
#+Email: gh01@beatles.edu
#+Date: <2015-09-12 Sat>

* Exam Results

|               | score | possible |
|---------------+-------+----------|
| problem 1 (a) |     5 |        5 |
| problem 1 (b) |     4 |        5 |
| problem 2     |     7 |       10 |
| problem 3     |    20 |       25 |
|---------------+-------+----------|
| total         |    36 |       45 |
#+TBLFM: @>$2..@>$>=vsum(@2..@>>)

I imagine this is possible using an elisp snippet but I'm not really sure how to get started. Does anyone know how to start something like this?

Note, I'm not necessarily looking for a full solution. I'm mainly looking for commands to get me started.

  • Here was my first attempt about 1.5 years ago at creating org-mode entries programmatically -- I'm not sure whether there is anything there that might be of interest: stackoverflow.com/a/22419713/2112489 – lawlist Sep 13 '15 at 0:41
1

This should do roughly what you want:

#+TBLNAME: students
|                  |                  |        | p01a | p01b | p02 | p03 |
|------------------+------------------+--------+------+------+-----+-----|
| e-mail           | name             |  total |    5 |    5 |  10 |  25 |
|------------------+------------------+--------+------+------+-----+-----|
| gh01@beatles.edu | Harrison, George | 80.00% |    5 |    4 |   7 |  20 |
| jl01@beatles.edu | Lennon, John     | 75.56% |    5 |    3 |   5 |  21 |
| pm01@beatles.edu | McCartney, Paul  | 86.67% |    5 |    5 |   6 |  23 |
| rs01@beatles.edu | Starr, Ringo     | 82.22% |    5 |    4 |   6 |  22 |
#+TBLFM: @3$3..@>$3=100*vsum($4..$>)/vsum(@2$4..@2$>);%.2f%%

#+BEGIN_SRC emacs-lisp :var students=students :results none
    ;; This is a way to prevent Org from prepending commas to the lines
    ;; starting with Org markup
    (defvar my/student-grades-template
      (mapconcat
       'identity
       '("#+Title: %s"
         "#+Email: %s"
         "#+Date: <%s>"
         ""
         "* Exam Results"
         ""
         "|               | score | possible |"
         "|---------------+-------+----------|"
         "| problem 1 (a) |     %s |        5 |"
         "| problem 1 (b) |     %s |        5 |"
         "| problem 2     |     %s |       10 |"
         "| problem 3     |    %s |       25 |"
         "|---------------+-------+----------|"
         "| total         |       |          |"
         "#+TBLFM: @>$2..@>$>=vsum(@2..@>>)")
       "\n"))

    (defun my/gen-student-report (student-row dest)
      (let ((today (format-time-string "%Y-%m-%d %a")))
        (cl-destructuring-bind (e-mail name _ p01a p01b p02 p03) student-row
          (with-temp-file (format "%s/%s.org" dest (car (split-string name "\\W+")))
            (erase-buffer)
            (insert (format my/student-grades-template name e-mail today p01a p01b p02 p03))
            (org-table-TBLFM-begin)
            (orgtbl-ctrl-c-ctrl-c '(4))))))

    (defun my/gen-reports (students)
      (let ((dest "./reports/") 
            (students (cddr students)))
        (unless (file-exists-p dest)
          (make-directory dest))
        (cl-mapcar 'my/gen-student-report
                   students (make-list (length students) dest))))

    (my/gen-reports students)
#+END_SRC

But it may be also possible to make it more generic by replacing the template by a procedure using a special Org file as a template.

  • This gives me a great place to start. I'm going to leave the question open for a day or two just to encourage more activity but will likely end up accepting. Thanks for looking at this! – Brian Fitzpatrick Sep 13 '15 at 17:57

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.