Difference between revisions of "Custom Reports Using Eguile"

From GnuCash
Jump to: navigation, search
(Custom for-loop syntax: fix broken <)
 
(22 intermediate revisions by 7 users not shown)
Line 8: Line 8:
  
 
For example,  
 
For example,  
<pre>
+
<SyntaxHighlight lang="HTML">
 
<h3><?scm:d coyname ?></h3>
 
<h3><?scm:d coyname ?></h3>
 
<h2><?scm:d reportname ?> as at <?scm:d (gnc-print-date opt-date-tp) ?></h2>
 
<h2><?scm:d reportname ?> as at <?scm:d (gnc-print-date opt-date-tp) ?></h2>
</pre>
+
</SyntaxHighlight>
 
would become
 
would become
<pre>
+
<SyntaxHighlight lang="Scheme">
 
(display "<h3>")(display "Acme Tools Ltd.")(display "</h3>
 
(display "<h3>")(display "Acme Tools Ltd.")(display "</h3>
 
<h2>)(display "Balance Sheet")(display " as at ")
 
<h2>)(display "Balance Sheet")(display " as at ")
 
(display "05/04/2009")(display "<h2">)
 
(display "05/04/2009")(display "<h2">)
</pre>
+
</SyntaxHighlight>
 
which is then evaluated as guile code to create the text of the report.
 
which is then evaluated as guile code to create the text of the report.
  
Line 25: Line 25:
 
<tt>/usr/share/gnucash/guile-modules/gnucash/report/eguile-gnc.scm</tt>.  In general, it should go into the same folder as files such as fancy-invoice.scm.
 
<tt>/usr/share/gnucash/guile-modules/gnucash/report/eguile-gnc.scm</tt>.  In general, it should go into the same folder as files such as fancy-invoice.scm.
  
'''Note:''' GnuCash 2.3/2.4 already includes eguile-gnc.scm.
+
;Note: GnuCash >=2.3 already includes eguile-gnc.scm.
  
 
Install the report and its associated files in the usual way (see [[Custom Reports#Loading the Report]] for a full explanation).
 
Install the report and its associated files in the usual way (see [[Custom Reports#Loading the Report]] for a full explanation).
  
Your report should start with a define-module statement like<pre>(define-module (gnucash report my-report-name))</pre> and have a unique name (GnuCash 2.2.x and before)/a unique id (GnuCash 2.3.x and later).  
+
Your report should start with a define-module statement like <SyntaxHighlight lang="Scheme" inline>
 +
(define-module (gnucash report my-report-name))
 +
</SyntaxHighlight> and have a unique name (GnuCash 2.2.x and before)/a unique id (GnuCash 2.3.x and later).  
  
The easiest way is to put all the files for a report into your <tt>.gnucash</tt> folder, and then add a line to <tt>.gnucash/config.user</tt> like this:
+
The easiest way is to put all the files for a report into your <tt>.gnucash</tt> folder, and then add a line to <tt>.gnucash/config.user</tt> like this:<SyntaxHighlight lang="Scheme">
(load "/path/to/my/.gnucash/report.scm")   
+
(load "/path/to/my/.gnucash/report.scm")   
 +
</SyntaxHighlight>
 
If <tt>.gnucash/config.user</tt> does not already exist, just create it and add the new line.
 
If <tt>.gnucash/config.user</tt> does not already exist, just create it and add the new line.
  
 
For example, on a Linux system, for a user called 'chris', the Tax Invoice report can be installed by:
 
For example, on a Linux system, for a user called 'chris', the Tax Invoice report can be installed by:
 
# Downloading taxinvoice.scm and taxinvoice.eguile.scm, and putting them into the <tt>/home/chris/.gnucash/</tt> folder.
 
# Downloading taxinvoice.scm and taxinvoice.eguile.scm, and putting them into the <tt>/home/chris/.gnucash/</tt> folder.
# Adding this line to <tt>/home/chris/.gnucash/config.user</tt>:
+
# Adding this line to <tt>/home/chris/.gnucash/config.user</tt>:<SyntaxHighlight lang="Scheme">
(load "/home/chris/.gnucash/taxinvoice.scm")
+
(load "/home/chris/.gnucash/taxinvoice.scm")
 +
</SyntaxHighlight>
  
 
Restart GnuCash, and the report should then show up somewhere in the reports menu, depending on the menu-path option in the report.  The Tax Invoice and Balance Sheet reports (see below) put themselves into the Reports/Business sub-menu.
 
Restart GnuCash, and the report should then show up somewhere in the reports menu, depending on the menu-path option in the report.  The Tax Invoice and Balance Sheet reports (see below) put themselves into the Reports/Business sub-menu.
Line 57: Line 61:
  
 
Note that s-expressions can be spread across more than one '<?scm ... ?>',  
 
Note that s-expressions can be spread across more than one '<?scm ... ?>',  
for example:
+
for example:<SyntaxHighlight lang="HTML">
<?scm (if (> x 3) (begin ?>Bigger<?scm ) (begin ?>Smaller<?scm )) ?>
+
<?scm (if (> x 3) (begin ?>Bigger<?scm ) (begin ?>Smaller<?scm )) ?>
 +
</SyntaxHighlight>
  
 
Each chunk of text outside a '<?scm ... ?>' pair ends up wrapped
 
Each chunk of text outside a '<?scm ... ?>' pair ends up wrapped
Line 67: Line 72:
 
result (as a string which is passed back to the report-displaying part of GnuCash).
 
result (as a string which is passed back to the report-displaying part of GnuCash).
  
For example, if the input file contained these lines:
+
For example, if the input file contained these lines:<SyntaxHighlight lang="HTML">
<pre>
 
 
  <h1 align="center">Invoice <?scm:d invoiceid ?></h1>
 
  <h1 align="center">Invoice <?scm:d invoiceid ?></h1>
 
  <?scm (for entry in entries do ?>
 
  <?scm (for entry in entries do ?>
 
   <p>Date: <?scm:d (entry date) ?>, description: <?scm:d (entry desc) ?>
 
   <p>Date: <?scm:d (entry date) ?>, description: <?scm:d (entry desc) ?>
 
  <?scm ) ?>
 
  <?scm ) ?>
</pre>
+
</SyntaxHighlight>
the resulting script would look like:
+
 
<pre>
+
the resulting script would look like:<SyntaxHighlight lang="Scheme">
 
  (display "<h1 align=\"center\">Invoice ")(display invoiceid)(display "</h1>")
 
  (display "<h1 align=\"center\">Invoice ")(display invoiceid)(display "</h1>")
 
  (for entry in entries do
 
  (for entry in entries do
Line 81: Line 85:
 
   (display ", description: ")(display (entry desc))
 
   (display ", description: ")(display (entry desc))
 
  )
 
  )
</pre>
+
</SyntaxHighlight>
and the final result might be this:
+
and the final result might be this:<SyntaxHighlight lang="Scheme">
<pre>
 
 
  <h1 align="center">Invoice 002345</h1>
 
  <h1 align="center">Invoice 002345</h1>
 
   <p>Date: 04/03/2009, description: Widgets
 
   <p>Date: 04/03/2009, description: Widgets
 
   <p>Date: 05/03/2009, description: Modified widgets
 
   <p>Date: 05/03/2009, description: Modified widgets
</pre>
+
</SyntaxHighlight>
 
...
 
...
  
Line 94: Line 97:
  
 
==== Single list ====
 
==== Single list ====
 +
<SyntaxHighlight lang="Scheme">
 +
(for <var> in <list> do <expr> ...)
 +
</SyntaxHighlight>
  
(for &lt;var> in <list> do <expr> ...)
+
This syntax loops over <tt><list></tt>, assigning each value to <tt>&lt;var&gt;</tt> in turn and evaluating all <expr>'s. In other words, it takes the first element of <list>, assigns it to <var>, evaluates each <expr>, takes the second element of <list>, etc.
 
 
This syntax loops over <tt><list></tt>, assigning each value to <tt>&lt;var></tt> in turn and evaluating all <expr>'s. In other words, it takes the first element of <list>, assigns it to &lt;var>, evaluates each <expr>, takes the second element of <list>, etc.
 
 
 
Consider the following example:
 
  
 +
Consider the following example:<SyntaxHighlight lang="Scheme">
 
  (for entry in (gncInvoiceGetEntries invoice) do
 
  (for entry in (gncInvoiceGetEntries invoice) do
 
   (displayEntry entry))
 
   (displayEntry entry))
 +
</SyntaxHighlight>
  
 
This example would evaluate the "<tt>displayEntry</tt>" function for each entry in a given invoice.
 
This example would evaluate the "<tt>displayEntry</tt>" function for each entry in a given invoice.
  
 
==== Multiple lists ====
 
==== Multiple lists ====
 +
<SyntaxHighlight lang="Scheme">
 +
(for (<var> ...) in (<list> ...) do <expr> ...)
 +
</SyntaxHighlight>
  
(for (&lt;var> ...) in (<list> ...) do <expr> ...)
+
This syntax loops over all <tt><list></tt>'s in parallel, assigning each value to the corresponding <var> and evaluates all <expr>'s. In other words, it takes the first element of the first <list>, assigns it to the first <var>, takes the first element of the second <list>, assigns it to the second <var>, up to the last <list> and <var>. Then it evaluates each <expr> and starts over with the second element of each list, etc.
 
 
This syntax loops over all <tt><list></tt>'s in parallel, assigning each value to the corresponding &lt;var> and evaluates all <expr>'s. In other words, it takes the first element of the first <list>, assigns it to the first &lt;var>, takes the first element of the second <list>, assigns it to the second &lt;var>, up to the last <list> and &lt;var>. Then it evaluates each <expr> and starts over with the second element of each list, etc.
 
 
 
Consider the following example:
 
  
 +
Consider the following example:<SyntaxHighlight lang="Scheme">
 
  (let ((descriptions (list "Company name" "Address" "Website"))
 
  (let ((descriptions (list "Company name" "Address" "Website"))
 
       (values (list "Example Corp" "Example street 1" "http://example.org")))
 
       (values (list "Example Corp" "Example street 1" "http://example.org")))
Line 120: Line 124:
 
     (display ": ")
 
     (display ": ")
 
     (display val)
 
     (display val)
     (display "&lt;br/>\n")))
+
     (display "<br/>\n")))
 
+
</SyntaxHighlight>
This example would output:
 
  
<pre>
+
This example would output:<SyntaxHighlight lang="HTML">
 
Website: http://example.org<br/>
 
Website: http://example.org<br/>
 
Company name: Example Corp<br/>
 
Company name: Example Corp<br/>
 
Address: Example street 1<br/>
 
Address: Example street 1<br/>
</pre>
+
</SyntaxHighlight>
 
 
==== Hashes ====
 
  
 +
==== Hashes (removed in Gnucash 3.7) ====
 +
<SyntaxHighlight lang="Scheme">
 
  (for <key> => <value> in <hash> do <expr> ...)
 
  (for <key> => <value> in <hash> do <expr> ...)
 +
</SyntaxHighlight>
  
 
This syntax loops over all keys and values in a hash, assiging each key to <key> and each value to <value> in turn and evaluating all <expr>'s. Note that as always with hashes, the keys from the hash are looped in arbitrary order.
 
This syntax loops over all keys and values in a hash, assiging each key to <key> and each value to <value> in turn and evaluating all <expr>'s. Note that as always with hashes, the keys from the hash are looped in arbitrary order.
  
Consider the following example:
+
Consider the following example:<SyntaxHighlight lang="Scheme">
 
 
 
  (let ((company (make-hash-table 16)))
 
  (let ((company (make-hash-table 16)))
 
   (hash-set! company "Company name" "Example Corp")
 
   (hash-set! company "Company name" "Example Corp")
Line 146: Line 149:
 
     (display ": ")
 
     (display ": ")
 
     (display val)
 
     (display val)
     (display "&lt;br/>\n")))
+
     (display "<br/>\n")))
 +
</SyntaxHighlight>
  
 
This example would output exactly the same as the previous example.
 
This example would output exactly the same as the previous example.
 +
 +
This syntax was removed in Gnucash 3.7 (in this [https://github.com/Gnucash/gnucash/commit/e506b7c3325f09e84c1e5d9519e551cc49943535#diff-0e5f3da1af5a9af1929e52328ef4cf8c commit]). Instead, you can use the scheme built-in [https://www.gnu.org/software/guile/manual/html_node/Hash-Table-Reference.html hash-for-each], e.g.:<SyntaxHighlight lang="Scheme">
 +
  (hash-for-each (lambda (desc val) (
 +
    (display desc)
 +
    (display ": ")
 +
    (display val)
 +
    (display "<br/>\n")
 +
  )) company)
 +
</SyntaxHighlight>
  
 
=== ...the rest of this page will be here very soon ===
 
=== ...the rest of this page will be here very soon ===
Line 157: Line 170:
  
 
More precise N_ means NOP, no operation. It can be used to mark strings for translation e.g. in array declarations, but doesn't translate them. Then later the translation is called with _. More Details in [[Translation#Tips for Developers]].
 
More precise N_ means NOP, no operation. It can be used to mark strings for translation e.g. in array declarations, but doesn't translate them. Then later the translation is called with _. More Details in [[Translation#Tips for Developers]].
 +
  
 
== Available Reports ==
 
== Available Reports ==
Line 164: Line 178:
 
==== Tax Invoice ====
 
==== Tax Invoice ====
 
{|
 
{|
| Report file: || [http://www.fb-cs.co.uk/files/gnucash/taxinvoice.scm taxinvoice.scm]  
+
| Report file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/taxinvoice.scm taxinvoice.scm]  
 
|-
 
|-
| Template file: || [http://www.fb-cs.co.uk/files/gnucash/taxinvoice.eguile.scm taxinvoice.eguile.scm]  
+
| Template file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/taxinvoice.eguile.scm taxinvoice.eguile.scm]  
 
|-
 
|-
| CSS file: || none
+
| CSS file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/taxinvoice.css taxinvoice.css]
|-
 
| Sample output: || [http://www.fb-cs.co.uk/files/gnucash/taxinvoice.pdf PDF]
 
 
|-
 
|-
 
| Author: || [[User:ChrisDennis|ChrisDennis]]
 
| Author: || [[User:ChrisDennis|ChrisDennis]]
 
|-
 
|-
| Version: || 0.01
+
| Version: || 0.03
 
|-
 
|-
| Last update: || June 2009
+
| Last update: || June 2018
 
|}
 
|}
 
===== Features =====
 
===== Features =====
 +
* Included in the GnuCash source tree
 
* Includes full company and customer details, including a company logo if required.
 
* Includes full company and customer details, including a company logo if required.
 
* Automatically includes only relevant columns.  For example, if none of the items on the invoice have discounts applied, then the discount columns will be omitted.
 
* Automatically includes only relevant columns.  For example, if none of the items on the invoice have discounts applied, then the discount columns will be omitted.
  
 
===== Issues =====  
 
===== Issues =====  
* taxinvoice.scm includes code to display individual taxes on a per-entry basis, i.e. on each line of the invoice. This relies on a fix to the Swig encoding that is currently in the pipeline as bug #573645, but it includes a work-around so that it simply misses out the extra columns if that fix hasn't been applied.  This bug has been fixed in [[Announcement 2.3.0|2.3/2.4]].
+
* No known issues
* Doesn't have a separate CSS file (yet).
 
  
 
==== Balance Sheet ====
 
==== Balance Sheet ====
 
{|
 
{|
| Report file: || [http://www.fb-cs.co.uk/files/gnucash/balsheet-eg.scm balsheet-eg.scm]
+
| Report file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/balsheet-eg.scm balsheet-eg.scm]
|-
 
| Template file: || [http://www.fb-cs.co.uk/files/gnucash/balsheet-eg.eguile.scm balsheet-eg.eguile.scm]
 
 
|-
 
|-
| CSS file: || [http://www.fb-cs.co.uk/files/gnucash/balsheet-eg.css balsheet-eg.css]
+
| Template file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/balsheet-eg.eguile.scm balsheet-eg.eguile.scm]
 
|-
 
|-
| Sample output: || [http://www.fb-cs.co.uk/files/gnucash/balsheet-eg-1.pdf PDF]
+
| CSS file: || [https://raw.githubusercontent.com/Gnucash/gnucash/maint/gnucash/report/business-reports/balsheet-eg.css balsheet-eg.css]
 
|-
 
|-
 
| Author: || [[User:ChrisDennis|ChrisDennis]]
 
| Author: || [[User:ChrisDennis|ChrisDennis]]
 
|-
 
|-
| Version: || 0.01
+
| Version: || 1.54
 
|-
 
|-
| Last update: || June 2009
+
| Last update: || June 2018
 
|}
 
|}
 
===== Features =====
 
===== Features =====
 +
* This report has been included in GnuCash.
 
* Displays the balance sheet in a 'text book' style with rules under columns etc.
 
* Displays the balance sheet in a 'text book' style with rules under columns etc.
 
* Uses the 'Assets = Equity + Liabilities' model.  If there is demand for an 'Assets - Liabilities = Equity' version, then that could be done as a separate report, or by adding an option and some extra code to this one.
 
* Uses the 'Assets = Equity + Liabilities' model.  If there is demand for an 'Assets - Liabilities = Equity' version, then that could be done as a separate report, or by adding an option and some extra code to this one.
Line 219: Line 230:
 
   Less: Drawings        (£1000.00)
 
   Less: Drawings        (£1000.00)
 
===== Issues =====
 
===== Issues =====
* Needs people to test it and comment on it.
+
* No known issues.
  
 
==Proposed Reports==
 
==Proposed Reports==
 
===Cash Based Income Statement===
 
===Cash Based Income Statement===
I posted to the dev list with regard to sponsoring the development of this report.  This seems to be a recurring problem/topic/request as demonstrated by the few mailing-list posts I found:
+
Because of the importance and impacts this discussion moved to [[Cash Based Accounting]].
*http://lists.gnucash.org/pipermail/gnucash-devel/2003-May/009125.html
 
*http://lists.gnucash.org/pipermail/gnucash-user/2010-July/035854.html
 
We have been using gnucash for a while and it seems to always cause a problem around tax time for our accountants.  As I am not an accountant and I do not know anything about scheme, I would like to see if based on community input I can garner a requirement spec that solves this long standing issue in a report and then assuming it is a reasonable expense we can pay for the creation of the report.
 
 
 
:As far as I understand the problem with the current business mechanics, an invoice posted this month and payed next month is reported as income in this month. This would be correct for ''accrual accounting'', but wrong for ''cash based accounting'', where it should become income next month.
 
 
 
:This affects not only the Income statement, but also [https://bugzilla.gnome.org/show_bug.cgi?id=95700 Bug #95700: accrual and cash sales tax (VAT/GST) reporting in business invoices], other reports and the CoA.
 
 
 
:To implement an cash based accounting feature, we would need:
 
* An option ''accounting is cash based'': It should be per file, because one user could own different companies with different rules here. Backward compatibility would say, it should be false by default, but I assume, (at least) most (new) users wish cash based accounting. Eventually we should set it in the account templates to true, so it would be the default for new files.
 
* A quick way, to decide if income/expense are realized or pending. There are 3 possibilities to decide this:
 
** Scan the path of transactions:
 
*** It is quite clear, if the counter accounts are current assets like cash or bank.
 
*** I am not sure, how to handle credit cards in a) US and b) other countries.
 
*** For A/P and A/R accounts one had to check, if there is a corresponding payment in the time range of question. Do we have a function for this?
 
** Use separate accounts for unrealized income/expense.
 
*** E.g. the account templates in Germany have separate accounts for ''tax undue x%''. Here the payment process should move the tax amount from ''tax undue x%'' to ''tax due x%''
 
*** OTOH it would be hard to duplicate more complex income/expense hierarchies.
 
:Requesting for comments of other devs and users, --[[User:Fell|Fell]] 03:51, 1 April 2011 (UTC) (No joke)
 
** Use the Lots to determine if an invoice/bill has been paid.  Following the Lot from invoice to payment lets you not only know if it's been paid, but when.  The only significant challenge here is partial payments.  If an invoice has only been partially paid it's harder to determine which portion of the payment should be applied to tax.
 
====Features====
 
As a way to sharpen the requirements, we should start a list of specific features here:
 
*From a display perspective, it should mirror the accrual income statement
 
 
 
 
 
====Comments====
 
*Thank you for your input.  I have a few questions though.
 
**It seems you are proposing a change to the accounting system. Is this necessary? 
 
**Couldn't the a report just pull from different date fields and determine when the money actually hit the accounts, thus building a cash based report?
 

Latest revision as of 22:52, 4 February 2020

What is eguile?

eguile is a way of processing a template file to create a guile script.

More specifically, within GnuCash, guile is used to combine HTML and guile code to create a report, such as an invoice or balance sheet.

The GnuCash version of eguile is eguile-gnc.scm, written in early 2009 by Chris Dennis, and based on Neale Pickett's eguile.scm.

For example,

<h3><?scm:d coyname ?></h3>
<h2><?scm:d reportname ?> as at <?scm:d (gnc-print-date opt-date-tp) ?></h2>

would become

(display "<h3>")(display "Acme Tools Ltd.")(display "</h3>
<h2>)(display "Balance Sheet")(display " as at ")
(display "05/04/2009")(display "<h2">)

which is then evaluated as guile code to create the text of the report.

How to install an eguile report

To try out eguile-based reports, you first need to download eguile-gnc.scm and put it into the report folder. On my system -- Ubuntu -- that's /usr/share/gnucash/guile-modules/gnucash/report/eguile-gnc.scm. In general, it should go into the same folder as files such as fancy-invoice.scm.

Note
GnuCash >=2.3 already includes eguile-gnc.scm.

Install the report and its associated files in the usual way (see Custom Reports#Loading the Report for a full explanation).

Your report should start with a define-module statement like (define-module (gnucash report my-report-name)) and have a unique name (GnuCash 2.2.x and before)/a unique id (GnuCash 2.3.x and later).

The easiest way is to put all the files for a report into your .gnucash folder, and then add a line to .gnucash/config.user like this:
(load "/path/to/my/.gnucash/report.scm")

If .gnucash/config.user does not already exist, just create it and add the new line.

For example, on a Linux system, for a user called 'chris', the Tax Invoice report can be installed by:

  1. Downloading taxinvoice.scm and taxinvoice.eguile.scm, and putting them into the /home/chris/.gnucash/ folder.
  2. Adding this line to /home/chris/.gnucash/config.user:
    (load "/home/chris/.gnucash/taxinvoice.scm")
    

Restart GnuCash, and the report should then show up somewhere in the reports menu, depending on the menu-path option in the report. The Tax Invoice and Balance Sheet reports (see below) put themselves into the Reports/Business sub-menu.

How to create an eguile report

...

eguile syntax

Within what is otherwise an HTML source file, Guile/Scheme code is wrapped in '<?scm ... ?>' (whitespace is required after '<?scm' and before '?>')

'<?scm ... ?>' pairs can NOT be nested.

The optional :d modifier (i.e. '<?scm:d' ) is just a shortcut for '(display ... )', so '<?scm:d x ?>' is the same as '<?scm (display x) ?>'

Note that s-expressions can be spread across more than one '<?scm ... ?>',

for example:
<?scm (if (> x 3) (begin ?>Bigger<?scm ) (begin ?>Smaller<?scm )) ?>

Each chunk of text outside a '<?scm ... ?>' pair ends up wrapped in a (display ... ), after having had double quotes etc. escaped.

The processing happens in two passes. Initially the input file is converted to a Guile script, and then that script is evaluated to produce the final result (as a string which is passed back to the report-displaying part of GnuCash).

For example, if the input file contained these lines:
 <h1 align="center">Invoice <?scm:d invoiceid ?></h1>
 <?scm (for entry in entries do ?>
   <p>Date: <?scm:d (entry date) ?>, description: <?scm:d (entry desc) ?>
 <?scm ) ?>
the resulting script would look like:
 (display "<h1 align=\"center\">Invoice ")(display invoiceid)(display "</h1>")
 (for entry in entries do
   (display "<p>Date: ")(display (entry date))
   (display ", description: ")(display (entry desc))
 )
and the final result might be this:
 <h1 align="center">Invoice 002345</h1>
   <p>Date: 04/03/2009, description: Widgets
   <p>Date: 05/03/2009, description: Modified widgets

...

Custom for-loop syntax

To simply looping over a list or map (which by default is a bit cumbersome in scheme), GnuCash defines a custom for-loop syntax, which works similar to for loops in some imperative languages. There are three forms of this syntax: For a single list, for multiple lists and for hashes. This for loop syntax should be available in all eguile-based reports (both in the report itself as well as in the eguile templates). This syntax is defined in eguile-utilities.scm, so it might be available in other parts of scheme as well.

Single list

 (for <var> in <list> do <expr> ...)

This syntax loops over <list>, assigning each value to <var> in turn and evaluating all <expr>'s. In other words, it takes the first element of <list>, assigns it to , evaluates each <expr>, takes the second element of <list>, etc.

Consider the following example:
 (for entry in (gncInvoiceGetEntries invoice) do
   (displayEntry entry))

This example would evaluate the "displayEntry" function for each entry in a given invoice.

Multiple lists

 (for (<var> ...) in (<list> ...) do <expr> ...)

This syntax loops over all <list>'s in parallel, assigning each value to the corresponding and evaluates all <expr>'s. In other words, it takes the first element of the first <list>, assigns it to the first , takes the first element of the second <list>, assigns it to the second , up to the last <list> and . Then it evaluates each <expr> and starts over with the second element of each list, etc.

Consider the following example:
 (let ((descriptions (list "Company name" "Address" "Website"))
       (values (list "Example Corp" "Example street 1" "http://example.org")))
   (for (desc val) in (descriptions values) do
     (display desc)
     (display ": ")
     (display val)
     (display "<br/>\n")))
This example would output:
Website: http://example.org<br/>
Company name: Example Corp<br/>
Address: Example street 1<br/>

Hashes (removed in Gnucash 3.7)

 (for <key> => <value> in <hash> do <expr> ...)

This syntax loops over all keys and values in a hash, assiging each key to <key> and each value to <value> in turn and evaluating all <expr>'s. Note that as always with hashes, the keys from the hash are looped in arbitrary order.

Consider the following example:
 (let ((company (make-hash-table 16)))
   (hash-set! company "Company name" "Example Corp")
   (hash-set! company "Address" "Example street 1")
   (hash-set! company "Website" "http://example.org")
   (for desc => val in company do
     (display desc)
     (display ": ")
     (display val)
     (display "<br/>\n")))

This example would output exactly the same as the previous example.

This syntax was removed in Gnucash 3.7 (in this commit). Instead, you can use the scheme built-in hash-for-each, e.g.:
   (hash-for-each (lambda (desc val) (
     (display desc)
     (display ": ")
     (display val)
     (display "<br/>\n")
   )) company)

...the rest of this page will be here very soon

Internationalisation

Always use _ rather than N_ in the template file. N_ can be used for report option names, help text, and default values.

More precise N_ means NOP, no operation. It can be used to mark strings for translation e.g. in array declarations, but doesn't translate them. Then later the translation is called with _. More Details in Translation#Tips for Developers.


Available Reports

The following eguile-based reports are available. More will be contributed soon (hopefully).

Tax Invoice

Report file: taxinvoice.scm
Template file: taxinvoice.eguile.scm
CSS file: taxinvoice.css
Author: ChrisDennis
Version: 0.03
Last update: June 2018
Features
  • Included in the GnuCash source tree
  • Includes full company and customer details, including a company logo if required.
  • Automatically includes only relevant columns. For example, if none of the items on the invoice have discounts applied, then the discount columns will be omitted.
Issues
  • No known issues

Balance Sheet

Report file: balsheet-eg.scm
Template file: balsheet-eg.eguile.scm
CSS file: balsheet-eg.css
Author: ChrisDennis
Version: 1.54
Last update: June 2018
Features
  • This report has been included in GnuCash.
  • Displays the balance sheet in a 'text book' style with rules under columns etc.
  • Uses the 'Assets = Equity + Liabilities' model. If there is demand for an 'Assets - Liabilities = Equity' version, then that could be done as a separate report, or by adding an option and some extra code to this one.
  • One- or two-column layout.
  • Negative values can be shown as, for example, '-£100.00' or '(£100.00)'.
  • Deliberately has fewer options than the standard balance sheet. It makes 'intelligent' decisions about what to display. For example, parent accounts that are marked as placeholders and have a zero balance do not have their balance shown at all.
  • Handles commodities/currencies in a basic way -- exchange rates are calculated as at the date of the balance sheet.
  • A balancing entry (labelled 'Retained Earnings' by default) is calculated so that the sheet always balances.
  • Only displays Imbalance and Orphan accounts if non-zero.
  • Does not have a account selection option -- I don't see why you would want a balance sheet with some accounts missing.
  • Does not deal with unrealised gains/losses.
To Do
  • Option to put the currency symbol at the top of each column, rather than on every value.
  • Option to put "Less: " in front of negative accounts, e.g.
 Less: Drawings        (£1000.00)
Issues
  • No known issues.

Proposed Reports

Cash Based Income Statement

Because of the importance and impacts this discussion moved to Cash Based Accounting.