Skip to content

Instantly share code, notes, and snippets.

@ffevotte
Created July 1, 2013 07:53
Show Gist options
  • Save ffevotte/5899058 to your computer and use it in GitHub Desktop.
Save ffevotte/5899058 to your computer and use it in GitHub Desktop.
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

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

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

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

@cashpw
Copy link

cashpw commented Nov 15, 2023

@ffevotte I've extended this solution and packaged it as clocktable-by-tag. Are you okay if I add it into MELPA (which requires setting a GPL-compatible license)?

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