0

I have an org-mode file as such:

* Header level 1
:header-args: :var filename="somefile.csv"

** Header level 2
:header-args: :var foo="bar"
#+begin_src emacs-lisp
foo
#+end_src

#+RESULTS:
: bar
| / |                         |       |       |      |
|   | Datetime                | Price | Attr  | Note |
|---+-------------------------+-------+-------+------|
|   | 2021-01-13 13:45:46 UTC |  12.4 |       |      |
|---+-------------------------+-------+-------+------|
#+TBLFM: @3$3=12.4
#+TBLFM: @3$4='(message "%S" foo)

I would like to be able to C-c C-c on the second formula and have "bar" written on the Attr cell for that entry.

Is this possible using header-args?

Thank you very much.

1
  • Do you mean to have header-args properties? AFAICT, the way you specify :header-args: does not work at all.
    – NickD
    Jan 14, 2021 at 14:38

1 Answer 1

1

Assuming you meant to define header-args in properties, as I suggested in a comment, you could

  • name the code block with #+name: my-name e.g.
  • then in order to use the value of the code block, you can execute the code block using (org-sbe "my-name").

Something like this:

* Header level 1
  :PROPERTIES:
  :header-args:  :var foo="somefile.csv"
  :END:

** Header level 2
   :PROPERTIES:
   :header-args: :var foo="foobar"
   :END:
   
#+name: my-name
#+begin_src emacs-lisp 
foo
#+end_src

#+RESULTS: my-name
: foobar

| / |                         |       |        |      |
|   | Datetime                | Price | Attr   | Note |
|---+-------------------------+-------+--------+------|
|   | 2021-01-13 13:45:46 UTC |  12.4 | foobar |      |
|---+-------------------------+-------+--------+------|
#+TBLFM: @3$3=12.4
#+TBLFM: @3$4='(org-sbe "my-name")

Read the doc string of org-sbe with C-h f org-sbe. Note that it is the name of the code block that matters: the name of the variable foo does not (it's a local variable of the code block, so it's not visible from the outside).

EDIT: Here's a slight modification to deal with multiple variables. The assumption is that the code block returns a list of the values of the variables which are defined in the header. Then the table formula puts those values in successive rows in the third column:

* Header level 1                                                                                                
  :PROPERTIES:
  :header-args:  :var foo="somefile.csv"
  :END:

** Header level 2
   :PROPERTIES:
   :header-args: :var foo="foobar" :var bar="barfoo"
   :END:
   
#+name: my-name
#+begin_src emacs-lisp :results drawer
(list foo bar)
#+end_src

#+RESULTS: my-name
:results:
(foobar barfoo)
:end:

| / |                         |       |        |      |
|   | Datetime                | Price | Attr   | Note |
|---+-------------------------+-------+--------+------|
|   | 2021-01-13 13:45:46 UTC |  12.4 | foobar |      |
|   | 2022-01-13 13:45:46 UTC |  13.4 | barfoo |      |
|---+-------------------------+-------+--------+------|
#+TBLFM: @3$3=12.4 :: @4$3=13.4
#+TBLFM: @3$4..@>$4='(my-func (- @# 3))


** code                                                :noexport:
   #+begin_src emacs-lisp
     (defun my-func (n)
       (let ((x (read (org-sbe "my-name"))))
          (nth n x)))
   #+end_src

The my-func function basically does the "array" indexing: org-sbe returns the list as a string (unfortunately: that's a quirk of org-babel), so we invoke the lisp reader (read) to turn it back into a Lisp list and then we extract the n^th element of the list.

The function is called with the row number of the cell minus 3 to make it 0-based.

3
  • Thank you very much @NickD. This example was rather minimalistic but in real life I have like 10 variables or so, defining a block for each variable is a bit cumbersome. I wonder if there is a way to define just one block with all the vars, and access each value? Something similar like an array if you will Jan 14, 2021 at 21:41
  • 1
    Added an example with two variables: generalization is straightforward.
    – NickD
    Jan 14, 2021 at 23:20
  • Thank you very much Nick! Jan 20, 2021 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.