0x00 历程

大学四年记了4年的账,用了好多方法来记账,感觉自己记账的历程都快赶上一部会计记账的发展史了。

大一一开始的记账用Excel,当时还没有深入学习Excel,不会使用公式和VBA编程,而且所有的数字都是自己手算的,导致用Excel记账的效率极差,这基本上也可以折射会计发展中手工记账的年代了。

后来呢,自己开发了一款记账软件,用C++开发的,纯命令行工具,这个工具呢一共开发了2版,第一版代码可参考GitHub,第二版的代码可参考GitHub,均是我大一时的作品。这2个作品有2个共同的缺陷:

  1. 所有货币数额均使用double类型进行存储和计算,这其实是不合乎编码规范的。实际使用中应使用intlong乃至long long这样的整数类型来存储货币,将货币数额乘以100就可以消除掉小数点,比如10.24元就可以存储为整数1024分,然后在显示的时候除以100再显示就好了。
  2. 没有引入货币符号的概念,两个作品均只支持一种货币记账——人民币,主要是设计程序的时候没有考虑到后来会买美元花美元这种情况,这就导致算总账的时候,两个货币不能在总账上直接加减计算余额啊,然后就不知道怎么弄。后来我在工行开设了一个外币账户,使用这两个程序来记录这个外币账户上的花销就成了一个问题。

此后,我便没有继续再开发第三个程序,转而用了一款叫口袋记账的APP。口袋记账这款APP功能相对全面,而且首页是以时间轴的顺序来展示你相关的花销和收入的,这是我最喜欢的一个功能。而且,这款APP还带有同步功能,你只需要注册一个账号,你的所有账本数据就都会给你同步到云端。这个功能其实有利也有弊,方便的同时,你也很难以想象,APP的开发者会不会利用你同步上去的账本数据对你进行画像,或者进行一些非法的操作。

就是处于对同步数据安全以及预防数据非法利用和保护隐私这个目的,我最终还是弃用了口袋记账APP,转而投向了那个最原始的工具——Excel。Excel这款软件其实异常强大,尤其是在你学会了公式和VBA编程以后。用Excel的公式可以生成联动的单元格,只需在一个单元格上设置好公式后,使用单元格右下角的那个下拉功能,即可将公式自动联想填充到当前这一列的所有单元格中,而且可以使用IF函数判断收入/支出,方便地不得了。同时还可以使用VBA脚本来定期对账目进行核查和统计。这样,每次记账,我都只需要填几个小项就可以了,其余的均指望Excel的公式功能来自动计算和填充。

这些记账的方法使用没有逃出单式记账法(Single-entry bookkeeping)的范围。虽然由一开始的手工记账发展到后来的电算化,自己开发了软件也好,用Excel或者口袋记账这样的APP也好。

后来呢,经过短暂的学习,我学会了复式记账法(Double-entry bookkeeping),一种更为先进的记账方法。

0x01 复式记账法

我们并不是专业的会计专业,记账的目标也不是某一企业,我们是个人记账。所以我们抛弃其中的大多数会计概念,简明扼要地讲明白这些东西。

首先呢,我们并不需要知道单式记账法和复式记账法严格的定义。二者最根本的区别在于单式记账法每笔账只记一笔,而复式记账法在任何情况下都是记两笔账。例如:

我用余额宝买了10块钱的饭,买之前余额宝里还有100元。

在单式记账法中,这是一笔账,我们可以简要地将其描述为:

账户名称 收支方向 金额 余额 缘由
余额宝 支出 10 90 买饭

在复式记账法里,这就成了2笔账了:

账户名称 缘由
余额宝 10 买饭
账户名称 缘由
你的胃 10 吃饭

看到这个借和这个贷是不是感到很懵啊,其实我第一次看到这两个字我也是感觉懵懵的。没事,接下来,我们一步步地理清这里面的关系。

复式记账有一个核心公式就是:

Assert=Liability+Equity资产=负债+所有者权益\text{Assert}=\text{Liability}+\text{Equity} \\ \text{资产}=\text{负债}+\text{所有者权益}

上述公式中,等式左边增加记为借,减少记为贷。等式右边增加记为贷,减少记为借。借和贷分别对应英文里的Debit和Credit,或许你已经差不多知道我接下来要说啥了,就是Debit card和Credit card,储蓄卡和信用卡。

其实储蓄卡(Debit card)和信用卡(Credit card)英文里的Debit和Credit就分别对应了银行负债的两种流动情况。你有一张储蓄卡,你需要先往里面存钱,然后才能消费,你往里面存了100块钱,对于银行而言,银行的负债增加了100块钱,然后你用这张卡消费了20块钱,银行的负债对应也就减少了20块钱,等式右边减少记为借,也就是Debit。你还有一张信用卡,有一定的透支额度,你透支了20块钱购物,你欠了银行20块钱,对于银行而言,银行又欠卖你东西的商户20块钱,银行的负债增加了,等式右边增加记为贷,也就是Credit。

读到这,你差不多也就能理解了借(Debit)和贷(Credit)的关系了,有借必有贷,借贷必相等,这是复式记账法的一大准则。

上述公式中,资产(Assert)和负债(Liability)对于一般人来说,都容易理解,那所有者权益(Equity)到底是个什么东西呢?

对于一般人来说,我们并不需要知道所有者权益代表了啥,我们只需要认识其中的一个科目——期初余额(Opening Balances)就可以了。期初余额说白了就是初始化一个账本的余额,按字面理解也就是记账的日子开始的那一天,我有这么些钱。例如,你第一次使用复式记账法,你新建了个账户,用来表示你钱包里的现金,你开始记账时,你钱包里面有5块钱现金,那么用复式记账法就可以记为:

账户名称 缘由
钱包现金 5 第一次记账
账户名称 缘由
期初余额 5 第一次记账

上面的概念和例子,如果还是没有明白,也没关系,下面我给你安利一款复式记账软件——GNU cash,这款软件从根本上消除了这些难以理解的复杂会计概念。

0x02 GNU cash

GNU cash是GNU软件基金会开发的一款财会软件,支持复式记账,而且摒弃了很多复杂的会计概念。详情请了解GnuCash.org

首先我们来谈一下这个软件的第一个好处,就是消除了很多复杂的会计概念,最突出的一点就是消除了难以理解的借和贷的概念。转而用如下几个词汇代替:

  • 对于资产中的现金账户:使用Receive(存入)和Spend(消费)代替
  • 对于资产中的支票或储蓄账户:使用Deposit(存款)和Withdrawal(取款)代替
  • 对于资产中的投资账户、所有者权益账户以及负债账户下的所有子账户:均使用Increase(增加)和Decrease(减少)代替
  • 对于消费类账户及其子账户:均使用Expense(消费)和Rebate(退款)代替
  • 对于收入类账户及其子账户:均使用Charge(支出)和Income(收入)代替

使用上述词汇来代替单纯的借和贷这两个词是不是感觉清晰易用了许多。

第二个好处呢,就是对于复式记账中的借贷双方,我们只需要输入其中一方的账目信息,另一方的信息则由软件自动填充,我们只需要指定一个Transfer就可以,让你像单式记账一样进行复式记账。例如我们打开一个账本可以看到如下样式的表格:

Date Num Description Transfer R Receive Spend Balance
  • Date就是日期,Num就是编号(可自己指定),Description就是账单描述
  • Transfer用于标记复式记账中的另一方的账户,如果你不设置这个字段,GNU cash则会在后面标注出In-balance(账不平)的字样,而且账本名会变成红色。还是要恪守复式记账的一大准则,有借必有贷,借贷必相等。
  • R是对账标签,刚创建这个账单条目的时候,它的默认值为n,也就是no,表示未经对账。如果你手工对账并确认无误了,可以点击一下,将其状态切换为c表示cleared,手工对账无误。如果你使用GNU cash里的对账(reconciled)功能对账无误的话,其值将会被设置为y,表示yes。如果这个账单条目过了你一开始设置的冻结时间后,其值记为f,表示frozen已冻结。当然也可以将其设置为v,表示voided,表示条目作废。详情可参考文章Setting the reconcile status (R field) of a transaction
  • Receive和Spend表示收入还是支出,也就是对应复式记账概念里的借还是贷啊,GNU cash对借和贷的概念做了彻底的消除,因此我们看到的都是这样的替换词。
  • Balance表示余额,将由系统自动计算填充。

我们设置借贷双方中的一个,另一个就由GNU cash自动生成了。

同时GNU cash的Report下拉菜单还具有报表功能,Action菜单下还具有对账等功能,Business菜单下的功能主要面向企业,个人貌似用不着,比如给员工发工资等。这些功能在此均不一一赘述了。