Time formatting for org clocktable report - emacs

I use org-clock table to track time. It is more convenient for me to see time in hours, not in days. How could I configure org clocktable to do that?
Here is what I get now:
* A
:LOGBOOK:
CLOCK: [2020-05-08 Fri 10:37]--[2020-05-08 Fri 23:37] => 13:00
CLOCK: [2020-05-07 Thu 13:37]--[2020-05-07 Thu 23:37] => 10:00
:END:
* D
:LOGBOOK:
CLOCK: [2020-05-08 Fri 03:37]--[2020-05-08 Fri 05:37] => 2:00
CLOCK: [2020-05-06 Thu 03:37]--[2020-05-06 Thu 05:37] => 2:00
:END:
#+BEGIN: clocktable :scope file :maxlevel 2
#+CAPTION: Clock summary at [2020-05-08 Fri 19:40]
| Headline | Time |
|--------------+-----------|
| *Total time* | *1d 3:00* |
|--------------+-----------|
| A | 23:00 |
| D | 4:00 |
#+END:
Note "Total time" is "1d 3:00". I want total time to be shown as 27:00.

The time format is controller by the variable org-duration-format which has a very long description (C-h v org-duration-format RET). I quote selectively here:
The value can be set to, respectively, the symbols ‘h:mm:ss’ or
‘h:mm’, which means a duration is expressed as, respectively,
a "H:MM:SS" or "H:MM" string.
So adding this to the file:
#+begin_src emacs-lisp
(setq org-duration-format 'h:mm)
#+end_src
and evaluating it with C-c C-c will allow the clocktable to look like this:
#+BEGIN: clocktable :scope file :maxlevel 2
#+CAPTION: Clock summary at [2020-05-11 Mon 22:10]
| Headline | Time |
|--------------+---------|
| *Total time* | *27:00* |
|--------------+---------|
| A | 23:00 |
| D | 4:00 |
#+END:
You can also of course customize the variable if you want to avoid code.
Also, if you don't like the asterisks, you can customize the variable org-clock-total-time-cell-format whose default value is the string *%s*.

Related

org-mode review clocked time by multiple tags

I would like to review my clocked time by tags, to answer e.g. how much time did I spend this week on my health, on my work, on a client or on social relationships?
I am using tags, because the items I want to review my clocked time, can be spread over multiple files and hidden in different subtrees. Maybe this is the problem and I need to restructure? E.g. "Write an entry in your diary" should be stored under "notes", but summed into "health" and of course under "notes" there would be also other notes like "finance"...
Any other solution, e.g. using a custom agenda view or categories instead of tags would also be very welcome.
So far I have tried to use org mode clocktable grouped by multiple tags. For using clocktables I was using this test data:
* Take out the trash :private:
:LOGBOOK:
CLOCK: [2021-03-12 Fri 11:24]--[2021-03-12 Fri 11:30] => 0:06
:END:
* Update document for client :client1:
:LOGBOOK:
CLOCK: [2021-03-12 Fri 12:45]--[2021-03-12 Fri 13:30] => 0:45
:END:
* Create my awesome note for work :work:
:LOGBOOK:
CLOCK: [2021-03-13 Sat 11:24]--[2021-03-13 Sat 12:53] => 1:29
:END:
* Fill in timesheet :work:
:LOGBOOK:
CLOCK: [2021-03-12 Fri 11:24]--[2021-03-12 Fri 11:40] => 0:16
:END:
I have found the following solutions, neither seems to work with my system.
Here my problem is perfectly described. I've downloaded the code, it will create a table, but won't show the sums. Unfortunately, that code snipped seems too old, and I am not able to fix it. I have found a a fork of that snipped which gives me this result:
#+BEGIN: clocktable-by-tag :tags ("work" "client1")
| Tag | Headline | Time (h) |
| | | <r> |
|---------+------------+----------|
| work | *Tag time* | *0.00* |
|---------+------------+----------|
| client1 | *Tag time* | *0.00* |
#+END:
Here I found another solution. The author uses a function to format the times, which are then used by orgaggregate. Unfortunately already the first step, doesn't seem to work correctly:
#+BEGIN: clocktable :scope file :maxlevel 3 :tags t :match "work|client1" :header "#+TBLNAME: timetable\n"
#+TBLNAME: timetable
| Tags | Headline | Time | T |
|---------+---------------------------------+--------+--------|
| | *Total time* | *2:30* | #ERROR |
|---------+---------------------------------+--------+--------|
| client1 | Update document for client | 0:45 | #ERROR |
| work | Create my awesome note for work | 1:29 | #ERROR |
| work | Fill in timesheet | 0:16 | #ERROR |
#+TBLFM: $4='(convert-org-clocktable-time-to-hhmm $3)::#1$4='(format "%s" "T")
#+END:
It really shouldn't be that hard, what I would like to achieve. At the moment the best solution I have, is to use multiple tables, one for each tag:
#+BEGIN: clocktable :scope file :maxlevel 3 :match "work"
#+CAPTION: Clock summary at [2022-01-03 Mon 16:55]
| Headline | Time |
|---------------------------------+--------|
| *Total time* | *1:45* |
|---------------------------------+--------|
| Create my awesome note for work | 1:29 |
| Fill in timesheet | 0:16 |
#+END:
#+BEGIN: clocktable :scope file :maxlevel 3 :match "client1"
#+CAPTION: Clock summary at [2022-01-03 Mon 16:55]
| Headline | Time |
|----------------------------+--------|
| *Total time* | *0:45* |
|----------------------------+--------|
| Update document for client | 0:45 |
#+END:
The first solution you found was almost there. It had two issues that gave you the wrong result:
It considered only agenda files, not the current file as an input for the table. That's the reason why you were getting empty results.
To convert minutes to a nicely formatted display, the function org-duration-from-minutes can be used.
With these updates, your test file gave this result to me:
#+BEGIN: clocktable-by-tag :tags ("work" "client1")
| Tag | Headline | Time (h) | |
|---------+-----------------------------------+----------+------|
| work | *Tag time* | 1:29 | |
| | File *test.org* | 1:29 | |
| | . Create my awesome note for work | | 1:29 |
|---------+-----------------------------------+----------+------|
| client1 | *Tag time* | 0:45 | |
| | File *test.org* | 0:45 | |
| | . Update document for client | | 0:45 |
#+END:
You can get a better summary by using :summary t (I personally prefer this option):
#+BEGIN: clocktable-by-tag :tags ("work" "client1") :summary t
| Tag | Headline | Time (h) |
|---------+------------+----------|
| work | *Tag time* | 1:29 |
|---------+------------+----------|
| client1 | *Tag time* | 0:45 |
#+END:
The :scope tag also works, except that I didn't implement scopes tighter than the current file (such as subtree).
You can find the code in a gist, or copy and paste from below:
(require 'org-clock)
(defun clocktable-by-tag/shift-cell (n)
(let ((str ""))
(dotimes (i n)
(setq str (concat str "| ")))
str))
(defun clocktable-by-tag/insert-tag (files params)
(let ((tag (plist-get params :tags))
(summary-only (plist-get params :summary))
(total 0))
(insert "|--\n")
(insert (format "| %s | *Tag time* |\n" tag))
(mapcar
(lambda (file)
(let ((clock-data (with-current-buffer (find-buffer-visiting file)
(org-clock-get-table-data (buffer-name) params))))
(when (> (nth 1 clock-data) 0)
(setq total (+ total (nth 1 clock-data)))
(if (not summary-only)
(progn
(insert (format "| | File *%s* | %s |\n"
(file-name-nondirectory file)
(org-duration-from-minutes (nth 1 clock-data))))
(dolist (entry (nth 2 clock-data))
(insert (format "| | . %s%s | %s %s |\n"
(org-clocktable-indent-string (nth 0 entry))
(nth 1 entry)
(clocktable-by-tag/shift-cell (nth 0 entry))
(org-duration-from-minutes (nth 4 entry))))))))))
files)
(save-excursion
(re-search-backward "*Tag time*")
(org-table-next-field)
(org-table-blank-field)
(insert (org-duration-from-minutes total))))
(org-table-align))
(defun org-dblock-write:clocktable-by-tag (params)
(insert "| Tag | Headline | Time (h) |\n")
(let ((params (org-combine-plists org-clocktable-defaults params))
(base-buffer (org-base-buffer (current-buffer)))
(files (pcase (plist-get params :scope)
(`agenda
(org-agenda-files t))
(`agenda-with-archives
(org-add-archive-files (org-agenda-files t)))
(`file-with-archives
(let ((base-file (buffer-file-name base-buffer)))
(and base-file
(org-add-archive-files (list base-file)))))
((or `nil `file)
(list (buffer-file-name)))
(_ (user-error "Unknown scope: %S" scope))))
(tags (plist-get params :tags)))
(mapcar (lambda (tag)
(clocktable-by-tag/insert-tag files (org-combine-plists params `(:match ,tag :tags ,tag))))
tags)))

Why is Emacs org-mode missing one date from clocktable?

I have used Emacs' org-mode for a long time to keep track of my hours, and for whatever reason, the following snippet drawn from my actual org-mode file, consistently misreports both Saturday the 11th, and Sunday the 12th.
Looking into it, I find that the hours for Saturday and Sunday are combined into the Saturday entry, at least in the first clocktable. In the second clocktable, which I specifically limited to the dates shown in the logbook, the hours are properly separated out.
I'd appreciate it if anyone could explain what's wrong, as I've never had this happen before, and I really do depend on it for timesheets!
Things Tried
* Re-compiled Emacs 25.1.1 .. just in case a library change was the issue.
* Used 'Packages' to upgrade everything.
* Locally compiled 'git' 2.x since 'magit' was complaining when I updated Packages.
Thanks!
Emacs Version...: GNU Emacs 25.1.1 - Locally compiled.
Org Version.....: 20170210 - Installed via 'Packages'
Operating System: CentOS 7 - From DVD early this year,
and updated as needed.
* FOO
:LOGBOOK:
CLOCK: [2017-03-13 Mon 10:22]--[2017-03-13 Mon 19:17] => 8:55
CLOCK: [2017-03-12 Sun 18:35]--[2017-03-12 Sun 19:17] => 0:42
CLOCK: [2017-03-12 Sun 15:29]--[2017-03-12 Sun 16:23] => 0:54
CLOCK: [2017-03-12 Sun 10:34]--[2017-03-12 Sun 11:18] => 0:44
CLOCK: [2017-03-11 Sat 20:06]--[2017-03-11 Sat 22:59] => 2:53
CLOCK: [2017-03-11 Sat 15:09]--[2017-03-11 Sat 19:15] => 4:06
CLOCK: [2017-03-11 Sat 11:56]--[2017-03-11 Sat 12:32] => 0:36
CLOCK: [2017-03-11 Sat 11:40]--[2017-03-11 Sat 11:56] => 0:16
CLOCK: [2017-03-10 Fri 12:26]--[2017-03-10 Fri 20:10] => 7:44
:LOGBOOK:
** WHERE DID SUNDAY THE 12TH GO?
#+BEGIN: clocktable :maxlevel 9 :scope file :step day :tstart "<-1w>" :tend "<+1d>"
Daily report: [2017-03-07 Tue]
| Headline | Time |
|--------------+--------|
| *Total time* | *0.00* |
Daily report: [2017-03-08 Wed]
| Headline | Time |
|--------------+--------|
| *Total time* | *0.00* |
Daily report: [2017-03-09 Thu]
| Headline | Time |
|--------------+--------|
| *Total time* | *0.00* |
Daily report: [2017-03-10 Fri]
| Headline | Time |
|--------------+--------|
| *Total time* | *7.73* |
|--------------+--------|
| FOO | 7.73 |
Daily report: [2017-03-11 Sat]
| Headline | Time |
|--------------+---------|
| *Total time* | *10.18* |
|--------------+---------|
| FOO | 10.18 |
Daily report: [2017-03-13 Mon]
| Headline | Time |
|--------------+--------|
| *Total time* | *8.92* |
|--------------+--------|
| FOO | 8.92 |
Daily report: [2017-03-14 Tue]
| Headline | Time |
|--------------+--------|
| *Total time* | *0.00* |
Daily report: [2017-03-15 Wed]
| Headline | Time |
|--------------+--------|
| *Total time* | *0.00* |
#+END:
** OH HERE IT IS? BUT WHY?
#+BEGIN: clocktable :maxlevel 9 :scope file :step day :tstart "<2017-03-10>" :tend "<2017-03-14>"
Daily report: [2017-03-10 Fri]
| Headline | Time |
|--------------+--------|
| *Total time* | *7.73* |
|--------------+--------|
| FOO | 7.73 |
Daily report: [2017-03-11 Sat]
| Headline | Time |
|--------------+--------|
| *Total time* | *7.85* |
|--------------+--------|
| FOO | 7.85 |
Daily report: [2017-03-12 Sun]
| Headline | Time |
|--------------+--------|
| *Total time* | *2.33* |
|--------------+--------|
| FOO | 2.33 |
Daily report: [2017-03-13 Mon]
| Headline | Time |
|--------------+--------|
| *Total time* | *8.92* |
|--------------+--------|
| FOO | 8.92 |
#+END:
I'm experiencing a similar problem (for November 2018) and have reported it to emacs-orgmode#gnu.org

How can you sort an Org clock table?

Here's an example Org clock table in Emacs:
#+BEGIN: clocktable :maxlevel 1 :scope file :tcolumns 1 :formula %
#+CAPTION: Clock summary at [2014-03-30 Sun 22:47]
| Headline | Time | % |
|--------------+--------+-------|
| *Total time* | *4:31* | 100.0 |
|--------------+--------+-------|
| Item A | 1:07 | 24.7 |
| Item B | 1:06 | 24.4 |
| Item C | 2:18 | 50.9 |
#+TBLFM: $3='(org-clock-time% #2$2 $2..$2);%.1f
#+END:
I want to sort the table by the % column. Is this possible?
Here's a more complex example:
#+BEGIN: clocktable :maxlevel 2 :scope file :tcolumns 1 :formula %
#+CAPTION: Clock summary at [2014-03-30 Sun 22:48]
| Headline | Time | % |
|--------------------+--------+-------|
| *Total time* | *4:31* | 100.0 |
|--------------------+--------+-------|
| Item A | 1:07 | 24.7 |
| \__ Item A1 | 0:07 | 2.6 |
| \__ Item A2 | 1:00 | 22.1 |
| Item B | 1:06 | 24.4 |
| \__ Item B1 | 1:06 | 24.4 |
| Item C | 2:18 | 50.9 |
| \__ Item C1 | 2:18 | 50.9 |
#+TBLFM: $3='(org-clock-time% #2$2 $2..$2);%.1f
#+END:
In this instance, the top level items should be sorted by their % values, but within each subtree, the secondary level items should also be sorted by their % values.
The time clocking code for Org-mode org-clock.el doesn't support any sorting facilities. The function org-clocktable-write-default creates tables by very rigid algorithm with limited variants of tuning, all of them are in the variable org-clocktable-defaults. Thus, dynamic block clocktable generates org tables "as is", http://orgmode.org/manual/The-clock-table.html contains exhaustive list of settings.
You can sort first table manually by placing the cursor in the 3 column and executing M-x org-table-sort-lines [n]umeric.
As to sorting second table with "knowledge about structure of levels" - it seems to be impossible without profound changes in the function org-clocktable-write-default.
The built-in formatter org-clocktable-write-default sorts the entries just row by row with no idea of levels. I was looking for the same functionality and ended up with writing my own formatter (not a formatter really) that sorts the entries with respect to levels. It has a limitation though that it can only sort on name or time, since the result of sorting on time is essentially the same as sorting on percentage, this's acceptable in your case.

Summing columns in a row in all rows with Emacs org-mode

I'm using Emacs org-mode to track times worked on various tasks. The last column in the table is the weekly sum for each task:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: #2$7=vsum($2..$6)::#3$7=vsum($2..$6)
Currently, I have to add a formula for each new row. Is there any way to customise the formula so that it calculates the sums regardless of how many rows there are?
Column formula did the trick as suggested by fniessen. Here's what I ended up with:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: $7=vsum($2..$6)
More info in the Column formulas and field formulas section from the docs.
You really should take a closer look at the documentation, and read about "column formulas" (and, even, "row formulas"). A colum formula is $7=...' and is editable viaC-c ='.

How can I compute sleep duration in an emacs table?

I have a table containing as inputs the Date, Waketime, and Bedtime. Based on this data I want to calculate the sleep duration of the night before. Below you can see an example of the table I would like to obtain:
| Date | Waketime | Bedtime | Sleep |
| <2012-09-24 Mon> | 6:00 | 22:00 | |
| <2012-09-25 Tue> | 8:00 | 01:00 | 10:00 |
| <2012-09-26 Wed> | 7:00 | 23:00 | 6:00 |
When I apply the table formula: #+TBLFM: $4=if((24-$3)<12, (24-$3)+#-1$2, $3+#-1$2);t this doesn't give the wanted result, due to the integers (24, 12...) being interpreted as seconds.
Erroneous result:
| Date | Waketime | Bedtime | Sleep |
| <2012-09-24 Mon> | 6:00 | 22:00 | |
| <2012-09-25 Tue> | 8:00 | 01:00 | 5.01 |
| <2012-09-26 Wed> | 7:00 | 23:00 | -14.99 |
#+TBLFM: $4=if((24-$3)<12, (24-$3)+#-1$2, $3+#-1$2);t
How can I adjust this formula so it returns the correct sleep duration?
Notice that for computing sleep duration, I have an if-statement that computes the sleep duration differently, depending on the value of Bedtime. If bedtime is before 12h, Bedtime and Waketime are added. If bedtime is past 12h, 24 is first subtracted by Bedtime and subsequently added to Waketime
It's a hack, because org-mode does not seem to understand calc's HMS notation when creating formulas, but here you are:
#+TBLFM: $4=if($3 - (12 * 3600) < 0, (24 * 3600), 0) + $2 - $3;T