2017年6月30日 星期五

GnuCash 台幣小數位數

雖然 新台幣 最小單位是 0.01,以前也有 5 角的硬幣,但現在並不通行,在 GnuCash 中看到所有的數字都多寫「.00」實在很煩(小聲說,其實看久就習慣了),本文說明如何讓那「.00」不見,畫面更清爽。

基本設定

各個科目顯示幾位小數是可以改的,在「編輯科目」的「最小單位」,把「Use Commodity Value」改成「1」就可以了。每個科目都要一一修改。
但還是有滿多地方會出現「.00」,譬如

  • 各交易的金額雖然寫整數,但 cursor 移上去要修改時,還是會出現兩位小數
  • 科目樹有些欄位還是會有兩位小數
  • 報表

以下說明如何消除那些「.00」

1. TWD 的定義

所有貨幣的定義都在 src/engine/iso-4217-currencies.scm 這個檔案,譬如 TWD 的定義是
( "New Taiwan Dollar" "dollar" "cent" "ISO4217" "TWD" "901" 100 100 "NT$" )

在編譯的過程中,iso-4217-currencies.scm 會產生 iso-4217-currencies.c 的下面幾行
    const char *fullname = "New Taiwan Dollar";
    gnc_commodity *c = gnc_commodity_new(book,
                                         CUR_I18N(fullname),
                                         "ISO4217",
                                         "TWD",
                                         "901",
                                         100);
這個檔案是 libgncmod-engine 的一部份,也就是說,TWD 的定義最終是寫死在程式執行檔裡,不是在設定檔中。

修改方法

如果是從 source code 開始 build GnuCash, 修改方法很簡單,只要把 iso-4217-currencies.scm 裡
( "New Taiwan Dollar" "dollar" "cent" "ISO4217" "TWD" "901" 100 100 "NT$" )
那行改成
( "New Taiwan Dollar" "dollar" "cent" "ISO4217" "TWD" "901" 1 1 "NT$" )
再重 build 就好了。

或是把 iso-4217-currencies.c 那個 100 改成 1 也可以。

如果是直接安裝執行檔,就比較麻煩了(譬如在 Windows)。我目前的解法是用 OllyDbg 開 libgncmod-engine.dll,找 reference 到 TWD 字串的程式碼位置前兩個 instruction
把 64 (十六進位,就是 100)改成 01。

2. 帳本存檔

程式改完把 GnuCash 開起來,會發現每筆交易的數字都正常了。但是科目樹有的欄位還是錯的,像是

這是因為早在建立帳本時,TWD 的定義也寫到帳本資料檔中了。還要修改帳本資料檔才行。

  • 若是存成舊的 xml 格式,請搜尋檔案中 "TWD" 字串附近的 "fraction" 改成 1
  • 若是存成新的 SQLite 格式,用 sqlite 打開存檔,執行以下指令

UPDATE commodities SET fraction = 1 WHERE mnemonic = 'TWD';

3. 報表

在稍微新一點的版本(我不確定版號,大概是 2.6 開始),在某些執行環境(譬如 windows),報表上的新台幣金額還是會出現小數點。

這是因為 GnuCash 產生報表時會用 locale 的設定,若抓不到(windows)就會用預設值 2。

修改方法是改 gnc-ui-util.c 的 gnc_default_print_info() 裡,
- info.min_decimal_places = lc->frac_digits;
+ info.min_decimal_places = 0;