Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Emacs org-mode dynamic block similar to clocktable, but grouped by tag See: http://stackoverflow.com/q/17353591/1225607
(defun clocktable-by-tag/shift-cell (n)
(let ((str ""))
(dotimes (i n)
(setq str (concat str "| ")))
str))
(defun clocktable-by-tag/insert-tag (params)
(let ((tag (plist-get params :tags)))
(insert "|--\n")
(insert (format "| %s | *Tag time* |\n" tag))
(let ((total 0))
(mapcar
(lambda (file)
(let ((clock-data (with-current-buffer (find-file-noselect file)
(org-clock-get-table-data (buffer-name) params))))
(when (> (nth 1 clock-data) 0)
(setq total (+ total (nth 1 clock-data)))
(insert (format "| | File *%s* | %.2f |\n"
(file-name-nondirectory file)
(/ (nth 1 clock-data) 60.0)))
(dolist (entry (nth 2 clock-data))
(insert (format "| | . %s%s | %s %.2f |\n"
(org-clocktable-indent-string (nth 0 entry))
(nth 1 entry)
(clocktable-by-tag/shift-cell (nth 0 entry))
(/ (nth 3 entry) 60.0)))))))
(org-agenda-files))
(save-excursion
(re-search-backward "*Tag time*")
(org-table-next-field)
(org-table-blank-field)
(insert (format "*%.2f*" (/ total 60.0)))))
(org-table-align)))
(defun org-dblock-write:clocktable-by-tag (params)
(insert "| Tag | Headline | Time (h) |\n")
(insert "| | | <r> |\n")
(let ((tags (plist-get params :tags)))
(mapcar (lambda (tag)
(setq params (plist-put params :tags tag))
(clocktable-by-tag/insert-tag params))
tags)))
Copy link

ghost commented Dec 28, 2014

This is what I've been looking for! :) Although I can't get it to work. It gives me
byte-code: Symbol's function definition is void: org-dblock-write:clocktable-by-tag

I am running emacs 23.4.1 on Debian which is probably too old for this?

@willtm
Copy link

willtm commented Aug 12, 2016

Hello, like the earlier poster, this is precisely what I needed. Thank you for sharing your work! I have noticed that :tcolumns, one of the dynamic block clocktable arguments that's used to limit the number of time columns does not work (at least I wasn't able to make it work). Do you have any suggestions on how to accomplish this?

@ironchicken
Copy link

ironchicken commented Jan 24, 2020

This used to work for me on org-mode 9.1. But it dosn't now and hasn't since 9.2.

I've found one small fix: on line 26 it should be (/ (nth 4 entry) 60.0). This fixes the wrong-type-argument error.

But even with this fix, the output is now wrong too. Instead of actually filtering by tag, I just get all the tasks. I get one block by tag, but the rows in the block are not filtered. But it must be org-clock-get-table-data that's actually responsible for the filtering by the :tags property in its params argument. So is this a regression in org-mode itself?

@ironchicken
Copy link

ironchicken commented Jan 24, 2020

The problem is that org-clock-get-table-data's parameters have changed. The :tags parameter is now just a flag which, when non-nil, means include the headline's tags. However, you can still filter by tags using the :match parameter.

@philohistoria
Copy link

philohistoria commented Aug 29, 2021

Anyway to sort the table by the time on tag? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment