From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ross Patterson Subject: [PATCH] Add a flat clocktable formatter useful for tables whose CSV export can be imported into accounting/invoiving tools such as Zoho Invoicing. Date: Thu, 27 Jun 2013 21:20:20 -0700 Message-ID: <874nci7tob.fsf@rpatterson.net> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:48788) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UsQAn-0008VD-Qv for emacs-orgmode@gnu.org; Fri, 28 Jun 2013 00:20:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UsQAl-0004y7-UO for emacs-orgmode@gnu.org; Fri, 28 Jun 2013 00:20:37 -0400 Received: from plane.gmane.org ([80.91.229.3]:38747) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UsQAl-0004xN-FH for emacs-orgmode@gnu.org; Fri, 28 Jun 2013 00:20:35 -0400 Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UsQAk-0004o3-M7 for emacs-orgmode@gnu.org; Fri, 28 Jun 2013 06:20:34 +0200 Received: from 199-188-193-35.public.monkeybrains.net ([199.188.193.35]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 28 Jun 2013 06:20:34 +0200 Received: from me by 199-188-193-35.public.monkeybrains.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 28 Jun 2013 06:20:34 +0200 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org --- lisp/org-clock.el | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index 8ac215e..bad653e 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -325,6 +325,14 @@ play with them." :group 'org-clocktable :type 'plist) +(defcustom org-clock-clocktable-flat-columns + '("Invoice Date" "Invoice Number" "Customer Name" + "Item Name" "Item Desc" "Quantity" "Item Price") + "Columns for the org-clocktable-write-flat clocktable formatter. +Default value matches the ZOHO CSV import format." + :group 'org-clocktable + :type '(repeat string)) + (defcustom org-clock-idle-time nil "When non-nil, resolve open clocks if the user is idle more than X minutes." :group 'org-clock @@ -2546,6 +2554,75 @@ from the dynamic block definition." (org-table-delete-column)) total-time)) +(defun org-clocktable-write-flat (ipos tables params) + "Write out a flat clock table at position IPOS in the current +buffer. Useful to render a table which can be exported to CSV and +then imported into accounting/invoiving tools such as Zoho Invoicing. +TABLES is a list of tables with clocking data as produced by +`org-clock-get-table-data'. + +PARAMS is the parameter property list obtained from the dynamic block +definition. Several parameters are used beyond those used by the +clocktable dynamic block: + :customer A string to be inserted into the 'Customer Name' column + :price A number to be inserted into the 'Item Price' column as a rate + :number A string to be inserter into the Invoice Number column + :columns A list which overrides the default CSV columns from + `org-clock-clocktable-flat-columns' + +Several other columns are calculated automatically: + Item Name: The path to the parent headline + Item Desc: The headline + Quantity: The clocktime. Useful with the `;t' formatter to get a + decimal billable time. +" + (let ((date (format-time-string "%Y-%m-%d")) + (customer (plist-get params :customer)) + (number (plist-get params :number)) + (price (plist-get params :price)) + (columns (or (plist-get params :columns) + org-clock-clocktable-flat-columns))) + (insert "\n|") + (dolist (column columns) + (insert column "|")) + (insert "\n|-\n") + (dolist (table tables) + (let ((rows (nth 2 table)) + (parents (list ""))) + (dotimes (row-idx (length rows)) + (let ((row (nth row-idx rows))) + (if (listp row) + (progn + (dotimes (parent-idx + (- (nth 0 (nth (- row-idx 1) rows)) (nth 0 row))) + (setcdr (last parents 2) nil)) + (if (and (< row-idx (- (length rows) 1)) + (< (nth 0 row) (nth 0 (nth (+ row-idx 1) rows)))) + (nconc parents (list (cadr row))) + (insert "|") + (dolist (column columns) + (cond + ((equal column "Invoice Date") (insert date)) + ((equal column "Invoice Number") (insert number)) + ((equal column "Customer Name") (insert customer)) + ((equal column "Item Name") + (dotimes (parent-idx (length parents)) + (insert (nth parent-idx parents)) + (if (not (or (= parent-idx 0) + (= parent-idx (- (length parents) 1)))) + (insert "/")))) + ((equal column "Item Desc") (insert (cadr row))) + ((equal column "Quantity") + (insert (org-minutes-to-hh:mm-string (nth 3 row)))) + ((equal column "Item Price") + (insert (format "%s" price)))) + (insert "|")) + (insert "\n")))))))) + (insert "#+TBLFM: " (plist-get params :formula)) + (org-ctrl-c-ctrl-c) + (goto-char ipos) + (skip-chars-forward "^|"))) + (defun org-clocktable-indent-string (level) (if (= level 1) "" -- 1.7.9.5