2

I try to give a name to a clocktable :

#+BEGIN: clocktable :scope file :maxlevel 2
#+NAME: d1
#+CAPTION: Clock summary at [2020-04-21 mar. 14:31]
| Headline     |   Time |
|--------------+--------|
| *Total time* | *0:15* |
|--------------+--------|
| t1           |   0:05 |
| t2           |   0:10 |
#+END:


* t1
  CLOCK: [2020-04-21 mar. 14:10]--[2020-04-21 mar. 14:16] =>  0:05

* t2
  CLOCK: [2020-04-21 mar. 14:20]--[2020-04-21 mar. 14:30] =>  0:10

To use it in a perl src block :

* code 
  #+NAME: t1
  #+begin_src perl :var d=d1
  $d;
  #+end_src

  #+RESULTS: t1
  | Headline     |   Time |
  | *Total time* | *0:16* |
  | t1           |   0:06 |
  | t2           |   0:10 |

But When I update the clocktable, the #+NAME: d1 disappear. And If I put it before the #+BEGIN line, the perl block do not find the reference.

How could I make the #+NAME line in the clocktable remain after the update of the clocktable ?

1
  • @Drew, I have updated the request. Thks
    – flav
    Commented Apr 21, 2020 at 15:52

1 Answer 1

4

You are correct that the #+NAME: line has to be attached to the table and therefore has to be inside the clocktable block. The cheapest way is to use a :header argument to the clocktable:

#+BEGIN: clocktable :scope file :maxlevel 2 :header "#+NAME: d1\n"

That will add the name, but it will take away the automatic caption. You can add your own caption as well with

#+BEGIN: clocktable :scope file :maxlevel 2 :header "#+NAME: d1\n#+CAPTION: my caption\n"

but you will have to forego the date insertion that is done by default (although you could perhaps do that using other methods).

The most versatile way would be to use your own :formatter function to format the clocktable:

#+BEGIN: clocktable :scope file :maxlevel 2 :formatter my-org-clocktable-write

instead of using the default org-clocktable-write-default. The only problem now is to write that function, but unfortunately there is not much support in Org mode for that: you'd have to copy the default function, rename it and then add the additional piece of information you want. You'd probably also want to add another argument to the line above to name the table:

#+BEGIN: clocktable :scope file :maxlevel 2 :formatter my-org-clocktable-write :tablename d1

The modification is not difficult to do, but adding the function here would make the answer very long and I don't have time to do it ATM: if I find some time and nobody beats me to it, I might add a diff later on.

EDIT: So here is what you need to do to get the modified formatter function. Copy the function org-clocktable-write-default from the file org-clock.el to the file org-clocktable-write-default.el in some temporary working directory. Save the following patch to some file, say org-clocktable.patch, in the same temp working directory:

--- org-clocktable-write-default.el 2020-04-21 16:59:49.009188899 -0400
+++ my-org-clocktable-write.el  2020-04-21 17:02:14.990787901 -0400
@@ -1,4 +1,4 @@
-(defun org-clocktable-write-default (ipos tables params)
+(defun my-org-clocktable-write (ipos tables params)
   "Write out a clock table at position IPOS in the current buffer.
 TABLES is a list of tables with clocking data as produced by
 `org-clock-get-table-data'.  PARAMS is the parameter property list obtained
@@ -63,17 +63,21 @@
     (insert-before-markers
      (or header
     ;; Format the standard header.
-    (format "#+CAPTION: %s %s%s\n"
-        (org-clock--translate "Clock summary at" lang)
-        (format-time-string (org-time-stamp-format t t))
-        (if block
-            (let ((range-text
-               (nth 2 (org-clock-special-range
-                   block nil t
-                   (plist-get params :wstart)
-                   (plist-get params :mstart)))))
-              (format ", for %s." range-text))
-          ""))))
+         (concat
+          (let ((tname (plist-get params :tablename)))
+            (if tname
+                (format "#+NAME: %s\n" tname)))
+     (format "#+CAPTION: %s %s%s\n"
+         (org-clock--translate "Clock summary at" lang)
+         (format-time-string (org-time-stamp-format t t))
+         (if block
+             (let ((range-text
+                (nth 2 (org-clock-special-range
+                    block nil t
+                    (plist-get params :wstart)
+                    (plist-get params :mstart)))))
+               (format ", for %s." range-text))
+           "")))))

     ;; Insert the narrowing line
     (when (and narrow (integerp narrow) (not narrow-cut-p))

Now run the following command in that temporary working directory:

patch < org-clocktable.patch

This will modify the org-clocktable-write-default.el file. Now insert the contents of this file into your init file, restart emacs (or eval the defun) and regenerate the clocktable by pressing C-c C-c on the #+BEGIN line which should now look like this:

#+BEGIN: clocktable :scope file :maxlevel 2 :formatter my-org-clocktable-write :tablename d1

#+END:

Assuming it all worked, you can delete the temporary directory where you did this work.

As you can see, there are two changes to the function: we change the name (that's the name you have to use for the :formatter argument in the clocktable line) and we change the header line to concatenate the #+NAME: ... line with the #+CAPTION: ... line.

Note a couple of things: if header is non-nil (i.e. you used :header foo in the clocktable line), then that's what's used: there is no #+NAME:... or #+CAPTION:... line produced - that's the same behavior as with the original function; if tablename is nil (i.e. you didn't include a :tablename foo argument in the clocktable line), then nothing changes: you just get the #+CAPTION: ...; but if tablename is non-nil, then you get the #+NAME: ... line and then the #+CAPTION: ... line.

Finally, it may look complicated, but it's easier done than said.

1
  • this is an excellent answer!!! Commented May 20, 2023 at 10:46

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.