#!/usr/local/bin/perl -w use strict; # 財務諸表を作成する。 # Usage: account.pl journal_file # [入力] 次の二つを空行で区切って置く # 期首貸借対照表 (initial balance sheet) # 仕訳帳 (book-keeping journal) # [出力] 次の 5個の財務諸表 (statements) # キャッシュフロー計算書 (cash flow statement) # 非キャッシュフロー計算書 (non-cash flow statement) # 実在フロー計算書 (real flow statement) # 名目フロー計算書 (nominal flow statement)、損益計算書 (income statement) # 貸借対照表 (balance sheet) # 期首貸借対照表および仕訳帳の各行は次の形。/ から始まる行はコメント。 # # 日付 借方科目(left) 金額(amount) 貸方科目(right) # # データ区切は tab、レコード区切は改行、データの終了は空行。 # 科目名中のスペースなどは科目名の一部と理解される。前期繰越のように対 # 応項のないものは、未対応項の代わりに 8個のスペースを入れる。この結果、 # 全体「空白科目」の合計が 0 かどうかでバランスチェックができる。 # !名目勘定(nominal accounts) の科目名には、頭に ! を付けること。 # 出力の科目の左右は、最初に出現した入力データの左右により決定される。 # キャッシュフロー計算書を作成するには、左右の科目に「現金」、「普通預 # 金」、「当座預金」、「 」という現金同等物を現わす言葉が入って # いるとキャッシュ、ないと非キャッシュの仕訳とみなす。 # (注意) 非キャッシュ行の左右には「 」があってはならない。 # したがって、非キャッシュの複数行の仕訳には「n 」を用いるとよい。 # 出力財務諸表を作成後、仕訳帳の後に一行空けて付けておくとよい。 sub print_line { # 仕訳行の打ち出し my ($_l_term, $_accnt, $_r_term, $_total) = @_; return if $$_accnt == 0; $$_total += $$_accnt; printf "\t%s\t%7d\t%s\n", $$_l_term, $$_accnt, $$_r_term; } sub print_error { # 空白科目不平衡時の打ち出し my ($_l, $_r) = @_; if ($$_l != $$_r) { printf "\t<<<<<<<< %7d 不平衡 %7d >>>>>>>>\n", $$_l, $$_r; } } sub print_total { # 小計の打ち出し my ($_l, $_r) = @_; if ($$_l != $$_r) { printf "\t<<<<<<<< %7d 不平衡 %7d >>>>>>>>\n", $$_l, $$_r; } $_ = sprintf "/\t %7d \n", $$_l; s/ /_/g; print; } $#ARGV == 0 || die "Usage: balance journal_file.t\n"; # 入力用 my (%iRl, %iRr, %iNl, %iNr); # init: Real/Nominal, left/right my (%fRl, %fRr, %fNl, %fNr); # flow: Real/Nominal, left/right my (%cfRl, %cfRr, %cfNl, %cfNr);# cash flow: Real/Nominal, left/right my (%nfRl, %nfRr, %nfNl, %nfNr);# non-cash flow: Real/Nominal, left/right # 出力用 my (%lRl, %lRr, %lNr, %lNl); # last: Real/Nominal, left/right my ($null, $l_term, $accnt, $r_term, $prof, $term, $l_total, $r_total); my $zero = 0; # zero my $spaces = ' '; # 空白8文字 my $prof_str = '当期利益'; # 当期利益は仕訳から無視する my $r_prof_str = '*当期利益'; # right Real profit (右実在利益) my $l_prof_str = '!*当期利益'; # left Nominal profit (左名目利益) # 期首データ読み込み while (<>) { # initial last if /^$/; # 空行で終了 next if /^[\/#]/; # コメント行無視 chomp; ($null, $l_term, $accnt, $r_term) = split("\t"); if ($l_term) { # 左借方の処理 if ($l_term !~ /^!/) { # Real if (defined $iRr{$l_term}) { # aleady in right $iRr{$l_term} -= $accnt; } else { # left or 1st appearance $iRl{$l_term} += $accnt; } } else { # Nominal if (defined $iNr{$l_term}) { # already in right $iNr{$l_term} -= $accnt; } else { # left or 1st appearance $iNl{$l_term} += $accnt; } } } if ($r_term) { # 右貸方の処理 if ($r_term !~ /^!/) { # Real if (defined $iRl{$r_term}) { # aleady in left $iRl{$r_term} -= $accnt; } else { # right or 1st appearance $iRr{$r_term} += $accnt; } } else { # Nominal if (defined $iNl{$r_term}) { # already in left $iNl{$r_term} -= $accnt; } else { # right or 1st appearance $iNr{$r_term} += $accnt; } } } } # 期中データ読み込み while (<>) { last if /^$/; # 空行で終了 next if /^\//; # コメント行無視 chomp; ($null, $l_term, $accnt, $r_term) = split("\t"); if (/現金|普通|当座|$spaces/) { # cash if ($l_term) { # 左借方の処理 if ($l_term !~ /^!/) { # Real if (defined $iRr{$l_term} || defined $fRr{$l_term}) { # aleady in right $fRr{$l_term} -= $accnt; $cfRr{$l_term} -= $accnt; } else { # left or 1st appear. $fRl{$l_term} += $accnt; $cfRl{$l_term} += $accnt; } } else { # Nominal if (defined $iNr{$l_term} || defined $fNr{$l_term}) { # aleady in right $fNr{$l_term} -= $accnt; $cfNr{$l_term} -= $accnt; } else { # left or 1st appear. $fNl{$l_term} += $accnt; $cfNl{$l_term} += $accnt; } } } if ($r_term) { # 右貸方の処理 if ($r_term !~ /^!/) { # Real if (defined $iRl{$r_term} || defined $fRl{$r_term}) { # aleady in left $fRl{$r_term} -= $accnt; $cfRl{$r_term} -= $accnt; } else { # right or 1st appear. $fRr{$r_term} += $accnt; $cfRr{$r_term} += $accnt; } } else { # Nominal if (defined $iNl{$r_term} || defined $fNl{$r_term}) { # aleady in left $fNl{$r_term} -= $accnt; $cfNl{$r_term} -= $accnt; } else { # right or 1st appear. $fNr{$r_term} += $accnt; $cfNr{$r_term} += $accnt; } } } } else { # non-cash if ($l_term) { # 左借方の処理 if ($l_term !~ /^!/) { # Real if (defined $iRr{$l_term} || defined $fRr{$l_term}) { # aleady in right $fRr{$l_term} -= $accnt; $nfRr{$l_term} -= $accnt; } else { # left or 1st appear. $fRl{$l_term} += $accnt; $nfRl{$l_term} += $accnt; } } else { # Nominal if (defined $iNr{$l_term} || defined $fNr{$l_term}) { # aleady in right $fNr{$l_term} -= $accnt; $nfNr{$l_term} -= $accnt; } else { # left or 1st appear. $fNl{$l_term} += $accnt; $nfNl{$l_term} += $accnt; } } } if ($r_term) { # 右貸方の処理 if ($r_term !~ /^!/) { # Real if (defined $iRl{$r_term} || defined $fRl{$r_term}) { # aleady in left $fRl{$r_term} -= $accnt; $nfRl{$r_term} -= $accnt; } else { # right or 1st appear. $fRr{$r_term} += $accnt; $nfRr{$r_term} += $accnt; } } else { # Nominal if (defined $iNl{$r_term} || defined $fNl{$r_term}) { # aleady in left $fNl{$r_term} -= $accnt; $nfNl{$r_term} -= $accnt; } else { # right or 1st appear. $fNr{$r_term} += $accnt; $nfNr{$r_term} += $accnt; } } } } } # キャッシュフロー計算書の打ち出し print <