少し興味が沸いたので、JavaScript を使って財務諸表のグラフを描画してみます。
以下の環境で動作確認をしています。
環境: Windows パソコン、Microsoft Edge
背景 ~ 財務諸表の描画にトライ!
日本の株をいくらか持っています。
株式の売買を検討するとき、各銘柄の売上高、営業利益、資産・負債などの財務データについては、証券会社のサイトやネットから比較的簡単に入手できます。
しかしながら、数値だけでは企業全体としての業績の把握が難しくなることがあります。
とくに、売買する候補を3~4社ピックアップして比較しようとすると、数値だけでは直感的ではないため、財務諸表を視覚化して把握したくなります。
ということで、財務諸表のテキストデータから、財務諸表のグラフを生成するスクリプトを作ってみることにします。
一番重要なポイントは、売上高などの数値データがテキストで与えられたとき、最短の手間でグラフ化できるかといったところです。
すると、Python を使うよりは、JavaScript でブラウザ上で簡単に使えるようにするのがよさそうです。
また、生成したグラフは、ボタン1つで SVG や PNG 形式でダウンロードできるとよいです。
グラフの描画は基本機能しか使いませんので、JavaScript やプログラミングが得意な方は、もっと洗練したデザインにするなどアレンジしてみてください。
いまは ChatGPT などが普及して、必要とされる一般教養の知識のレベルが上がってきているので、技術系、理系の人であっても、経済や会計・財務、法律など、文系分野などで知識の抜けがあると、判断を間違えたり、損をしてしまう場面が増えているのではないかなと思っています。
手順
① パソコン内に財務諸表の分析用のフォルダ(例: financial_statements1)を作ります。
例: c:\user\financial_statements1/
② フォルダ内にテキストファイルを2つ作成して以下のファイル名とし、末尾のサンプルスクリプトをコピー&ペーストで貼りつけて保存します。
例:
c:\user\financial_statements1/financial_statements1.html
c:\user\financial_statements1/financial_statements1.js
③ 上記の HTML をダブルクリックします。
→ 起動したら、設定まで完了です。
使い方
動くサンプル
まずは、動くサンプルを以下に貼っておきます。
下記の財務データを、上の画面右側(上の表示では右側に隠れています)のテキストボックスにコピー&ペーストし、[draw] ボタンをクリックしてみてください。
事例1:某自動車メーカーの財務データの例(単位:百万円(BS、PL)、億円(CF))
総資産 93000000
純資産 36000000
年 売上高 営業利益 純利益
23.3 37000000 2700000 2400000
24.3 45000000 5300000 4900000
25.3 48000000 4700000 4700000
営業CF 36000
投資CF -41000
財務CF 1000
現金等 89000
上記は、日本を代表する某自動車企業の財務データの数値を有効2桁程度で丸めたものです。
数値の部分を差し替えることで、任意の企業の財務データ、企業業績をグラフ化できます。
操作画面について
操作画面の中央に描画領域があります。
右側に財務データの入力欄があります。
[draw] ボタンをクリックすると、入力された財務データに基づきグラフを描画します。
[clear] ボタンをクリックすると、財務データと描画を消去します。
[save svg] ボタンをクリックすると、描画されたグラフを SVG 形式でダウンロードできます。
[save png] ボタンをクリックすると、描画されたグラフを PNG 形式でダウンロードできます。
[width], [height] 欄で、画像サイズ(描画領域)を設定できます。
財務データの記載方法について
財務データは、各科目を各行で記載していきます。
各行は、半角スペース区切りとし、数値は半角で記載します。
たとえば、総資産であれば、”総資産” の文字列 + ” ” (半角スペース) + 総資産の金額 のフォーマットで、1行で記載します。
他の、純資産、営業CF(営業キャッシュフロー)、投資CF、財務CF、現金等、についても同じです。
損益計算書(PL)については、1行目に “年 売上高 営業利益 純利益” の記載とします。
加えて、2行目以降に各年の売上高等の数値データを続けて(空行を入れずに、対応させて)記載します。
損益計算書のグラフは、末尾行(最新)の数値データのみを表示します。売上高に関しては複数年で記載されていることが多いため、よく使われる表記に合わせた記載としています。
グラフ表示について
財務諸表のグラフは、左から、貸借対照表(バランスシート、BS)、損益計算書(PL)、キャッシュフロー計算書(CF)の順で表示されます。
上記の事例の場合、BSとPLは、百万円単位、CFは一億円単位としています。
ただし、各グラフはそれぞれ最大値でスケールしていますので、単位系は任意に変更できます。
たとえば、すべての数値を一億円単位(百万円単位の記載があった場合は、末尾の0を2つ削除して切り捨てる)で表示しても、同様に機能します。
計算式のまとめ
スクリプトで使用している計算式は以下のとおりです。必要により、任意にカスタマイズしてみてください。
(総資産)=(負債)+(純資産) … (*01)
(期首現金等)=(現金等)ー((営業CF)+(投資CF)+(財務CF)) … (*02)
SBI証券のサービスを使っている場合について
加えて、SBI証券のサービスを使っている場合は、SBI証券のサイトにある財務データをコピー&ペーストすることで、かんたんにグラフ描画ができるようにしてあります。具体的な手順は以下のとおりです。
(1) SBI証券のサイトにログインし、国内株式の任意の銘柄を表示します。
(2) 表示されている画面で「四季報」→「財務状況」のタブをクリックします。
(3) 「財務状況」の欄に表示されるデータをコピーし、上記の Web アプリの画面下にあるテキストボックスにペーストします。
(4) [convert] ボタンをクリックすると、財務三表の表示に必要な財務データを引き抜くことができます。この状態で [draw] ボタンをクリックすると、グラフ表示できます。
たとえば、某自動車企業であれば、”72XX XXX自動車 … 売上高 … 有利子負債 XX,XXX,XXX” といった表示がされていると思います。
この部分のテキストをまるごと、上記の [convert] ボタンを配置した欄にコピー&ペーストすることで、財務諸表をかんたんに表示できるようにしてあります。
ブラウザ画面を複数開いて財務諸表のグラフを表示させることで、最小限の手間で、たとえば、T自動車とN自動車の財務状況を比較する、などがかんたんに可能になります。
なお、四季報やSBI証券のサイトでは、(純資産)ではなく(自己資本)が書かれていることが多いです。そこで、この場合は、以下の近似を使うことにします。
(純資産)=(自己資本)+(新株予約権)+(非支配株主持分)≒(自己資本) … (*03)
具体的には、SBI証券のサイトの四季報のテキストデータをコピー&ペースして[convert] ボタンをクリックする際は、(*03) 式を用いて、自己資本を純資産と読み替えて使用することにします。
また、銀行業の場合は、財務諸表の記載が他の一般企業とは異なっています。業態が異なるため、一般企業と同等に扱うことができません。そこで、一般企業のグラフ表記と対応させるため、プログラム内で下記の変換をしています。具体的には、売上高の記載が見つからない場合は、経常収益等の部分を下記で読み替えて変換します。
経常収益 → 売上高
経常利益 → 営業利益
SBI証券のサービスを使っている場合は、銀行の財務データを表示してみてください。上記の変換をするように作ってあります。
うまく動いたら
うまく動いたら、調べたい企業の財務諸表の数値に差し替えて活用してみてください。
また、JavaScript がわかる方、プログラミングが得意な方は、プログラムを修正して、改善してみてください。
以前に、財務諸表などネット上のファイルを自動ダウンロードするスクリプトをまとめ、公開しています。ダウンロードしたデータから、Python などを使って、上記のフォーマットでの財務データを書き出すことで、財務データの可視化も可能です。
また、株価の機械学習などのスクリプトも公開しています。機械学習を使った株価予測と財務分析を連動させることも可能になります。
その他
応用例
・ 株式の売買をされている方、持株会などをやっている方は、検討している銘柄について財務諸表を表示してみてください。負債が大きすぎる、営業利益率が低すぎる/高すぎるなど、気づいた点を掘り下げていくことで、独自の財務分析が可能となります。
よく経験するのが、以下のようなケースです。
配当利回りがひじょうに高くなっている銘柄があったので買おうかなと思い、財務諸表を確認すると、営業利益率が下がって負債の比率が高くなりつつあった。このため、株が売られて、見かけの配当利回りが上昇していた。現金や利益が減るといずれは減配になる可能性が高いので、購入前に財務を把握しておくほうがよい。
企業全体の資金の流れや財務を把握せずに、いくつかの限られた指標やニュースだけを見て売買をしてしまうとリスクが大きすぎると思います。株主優待も同じで、優待が充実している銘柄は配当利回りや営業利益率が低めのものが多い印象がありますので、財務を中長期でチェックしておき、割安になったタイミングで少しずつ買っていくのがよいのかなと思っています(主観です。ご自分の責任で、リスクの判断をお願いいたします)。
・ 同業種の中で、売上高のトップの企業、優良といわれている企業と下位の企業を比べてみてください。
負債の比率や営業利益率などの違いから、財務の良し悪しがすぐにわかると思います。
また、異業種の代表企業どおしを比較してみてください。各業種ごとの利益構造の違い、稼ぎ方の違いがわかると思います。
総資産の内訳も切り替えて表示できるようにしたり、PL の過去数年の経緯を表示できるようにしても面白そうですが、プログラムが複雑化するため、今回は省略しています。
・ 会計学、経済学などを勉強する際、PL、BS などの財務関連の用語が出てくることがあります。このとき、本を読むだけでは忘れていく一方となりがちです。こうしたとき、上記のスクリプトなどを使って、代表的な企業、興味のある企業の財務データをいくつか表示させてみるとよく理解できると思います。
グラフで比較検討をしてみると、各企業について、どうやって稼いでいるのか、また、稼げなくなってきているのかなど、肌感覚として納得しやすくなると思います。
・ 就職、転職を検討されている方も、候補となる企業の財務諸表を表示して、企業分析をしておくことをお勧めします。利益が出せなくなってきている企業や組織を選択してしまうと、その後のリスクが大きすぎるからです。
また、サラリーマンや公務員などとして数年働くと、どうやって価値を生み出しているのかわからなくなり、予算・現金を使いきることを覚えてしまいがちです。上からいわれた作業だけをしていたり、赤字を生み出すことを覚えてしまうと、他では通用しない職務経験になりがちです。財務の数字が把握できると、マーケットでの価値に経験や判断をつなげやすくなると思います。
財務諸表(財務三表)での資金の流れの整理
上記の財務三表で現金の流れを整理しておきます。
厳密な定義は書籍を参照するものとし、概要のみを整理しておくことにします。
まず、バランスシート(BS)の図で、もっともシンプルな例として、たとえば、総資産ゼロ、負債ゼロで、講師業(知的サービス業)をスタートするとします。すると、総資産 0、負債 0、自己資本 0 となります。
もし、自己資本 500万円、銀行借り入れ 500万円で事業を始めるのであれば、総資産 1,000万円のバランスシートとなります。
つぎに、損益計算書(PL)の図について、1年間仕事をしたとして、得られた年収を売上高とします。売上高を得るために要した売上原価、一般管理費などを差し引いて、本業での儲け、すなわち、営業利益が求められます。
営業利益に、本業以外の収益(銀行利息、配当収入など)などを加除することで、税引き前の純利益が求められます。この純利益部分に法人税等がかかり、純利益(税引き後)が求められます。
税引き後の純利益で株主配当等を行った残りは、年度ごとに(毎年)、バランスシートの右下の純資産に積み上がっていきます。
同時に、バランスシートの左側では、まずは現金のままとみなして、現金の科目が増額することになります。
バランスシートの左右はつねに一致することになります。
キャッシュフロー(CF)の図について、仮に、上記の知的サービス業(講師業)で、現金商売のみ、経費もすべて現金で支払う、パソコンなどの設備投資もしないとします。すると、営業CFは、上記の営業利益とほぼ一致してくることになります。
期中に減価償却となるパソコンなどを何も買わなければ、投資CF はゼロとなります。配当なども何もしなければ、財務CFもゼロとなって、現金等の金額が積み上がっていきます。
ここで仮に、パソコンや自動車などを現金で買ったとします。すると、投資CFがマイナスとなり、キャッシュフロー計算書上で、手持ちの現金等が減ることになります。
また、このとき、バランスシート上の左側では、現金及び預金が減り、有形固定資産(パソコン等)の科目の金額が増えることになります。このとき、バランスシートの左右の総資産の額は不変です。
パソコン等がバランスシートの有形固定資産に計上されても、損益計算書(PL)上では、直接的には金額の増減は反映されないことになります。損益計算書(PL)上では、減価償却の形で、少しずつ、費用として計上されていくことになります。
たとえば、パソコンを購入すると、その年は、月あたりの減価償却の額を、販売費及び一般管理費の科目などで計上し、費用として以後、償却していくことになります。
したがって、固定資産を購入すると、キャッシュフローとしては手元の現金はなくなるけれども、損益計算書上の見かけの営業利益は直接的には減額されないことになります。つまり、帳簿上の営業利益はプラスであっても、手元のキャッシュを使いすぎると、黒字倒産の可能性が出てくることになります。
ここで、ある年度に売上高や営業利益が急に増えたとします。すると、手元の現金が増えることになります。現金を残しておくと、純利益が増額するので、純利益に比例するように税金の支払いも増えることになります。
手元の現金が増えて、いずれにせよ税金の支払いも急増するのであれば、これまで買いたかった高額な固定資産などをまとめて購入し、現金を使ってしまいたくなることがあります。サラリーマンであれば、今年はボーナスが想定外に増えたので、高級車を買おうかなと思うようなものです。
この場合、キャッシュフローとしては手元の現金がなくなりますが、帳簿上の営業利益は残ったままとなり、減価償却による減額分は小さいので、税金の支払いはほとんど残る格好となります。手元の現金がなくなったのだから赤字に近づくはずなのに、現金を使った後で税金の支払いが発生するので感覚に合わない、といった現象が生じることになります。
減価償却について本などで読むと、なぜ、こんな複雑なことをわざわざするのかという印象を受けると思います。
しかし、売上高や営業利益が多くなったタイミングで固定資産など出費が大きいものをまとめて買って、利益を例年程度にする(税金の支払いを逃れる)といった調整ができない仕組みになっていると理解するとわかりやすいです。キャッシュフローが急に赤字になっても税金を徴収できるようにする仕組みと理解したほうが腹に落ちると思います。
自分の収入・預貯金を財務諸表で表示してみる
わかりやすい事例として、個人の収入・預貯金を、財務諸表のフォーマットを使って表示してみることにします。
経済や財務などを勉強し始めの方、また、株売買を始めようかなといった方は、このあたりから入るとわかりやすいかと思います。財務諸表のグラフを表示してみてください。
事例2:サラリーマン(新入社員)の収入・貯蓄を財務諸表のフォーマットで記載した例(単位:万円)
総資産 60
純資産 50
年 売上高 営業利益 純利益
25.3 300 50 50
営業CF 50
投資CF -20
財務CF 0
現金等 30
税引後の手取り年収 300万円の新入社員として、住居費、飲食費、光熱・通信費などの諸経費を差し引いた残り(営業利益)を50万円とした例です。
総資産(貯金など)が60万円、カード払い(負債)が年10万円としています。
営業利益がそのまま営業キャッシュフロー(営業CF)となるものとみなして、パソコンなどの設備投資で20万円のマイナスとし、直近1年の締め日での現金等が30万円となっている例としています。
貯金を頑張ると、純利益が大きくなって、バランスシートの左右の各科目に年々積みあがっていくことになります。また、パソコンなどの設備投資は、バランスシートの左側で、現金が減り、固定資産が増えることになります。
貯金をしたり、家電製品(固定資産)を買ったりして資産を増やすと、バランスシートの総資産が積みあがっていくことになります。
興味のある方は、ご自分の年収(売上高)、貯蓄額(総資産)などを表示してみてください。
つぎに平均世帯での財務諸表の例を以下に挙げてみます。
事例3:平均世帯の収入・貯蓄を財務諸表のフォーマットで表示する例(単位:万円)
総資産 3000
純資産 2000
年 売上高 営業利益 純利益
25.3 550 200 200
営業CF 200
投資CF -50
財務CF -30
現金等 500
平均世帯の年収や貯蓄額などはネットで調べることが可能です。そこで上記は、世帯での収入・貯蓄をざっと見積もってみたものです。
マンション等を購入していて、総資産は3000万円、ローン残高が1000万円あるといった例としています。東京など都市部であればさらに高額化する可能性がありますが、全国平均を仮定しています。
現実と乖離があると思う方は、妥当な数値に差し替えてシミュレーションをしてみてください。
ご自分の預貯金や資産をグラフ化することで、財務諸表の感覚がわかるかと思います。
日本の国の財務諸表を表示してみる
つぎに、日本の国(政府)の財務諸表を表示してみます。数値はやはりネットなどから概算値を得ることができます。
事例4:日本の国家(単体)の財務諸表(単位:兆円)
総資産 1050
純資産 -530
年 売上高 営業利益 純利益
25.3 70 -30 -10
営業CF -20
投資CF -6
財務CF 28
現金等 13
グラフを表示してみると、これは何か情報に抜けがあるはずだとすぐに気づくと思います。
よく言われているように負債が大きく、マイナスのグラフになっています。
ネットで調べると、負債の大半は国債であり、国債の多くを政府の子会社(55%)である日銀が買い取っています。また、国債の利払いは多額ですが、多くを日銀が受け取っています。
日本政府という親会社から、子会社である日銀に利益を移転させる格好になっています。全体を把握するには、連結決算を見ないと実態が把握できないことがすぐにわかると思います。そこで、日銀も含めた日本国の連結での決算(推測)を作ると以下のようになります。
事例5:日本の統合政府の財務データ(単位:兆円、推測)
総資産 1800
純資産 40
年 売上高 営業利益 純利益
25.3 121 21 19
営業CF -18
投資CF -10
財務CF 30
現金等 65
政府の資産が国債の格好で日銀等に移転され、利払い等も子会社である日銀が受け取る格好になっているため、連結決算で見ないと実態が把握できないことがわかります。
国債残高のニュースをよく見ますが、詭弁でいう、”片側提示” (Cherry Picking、一部だけのつまみ食い、一部だけを報道する) に該当する可能性が高いことが理解できます。
負債だけではなく、バランスシートの両側、つまり総資産の内訳や、子会社も含めた連結決算を見ないと利益の移転が把握できず、妥当な議論にならないことがわかります。
スクリプトの説明
・ スクリプトの冒頭で初期設定用のファイルとして、financial_statements1.js を読み込み、テキストボックスに表示するようにしています。財務諸表を記録しておけるようにしています。
・ let w1_svg, h1_svg は、図形領域のサイズです。
・ bs1, pl1, cf1 は、それぞれ、貸借対照表 BS、損益計算書 PL、キャッシュフロー計算書 CF に対応しています。BS と CF は1年分のデータを確保できるようにします。PL は過去3年など、数年にわたりグラフ描画することが多いため、配列を追加していく形式としています。
・ function load1() は、ページを読み込んだときの初期設定を行う関数です。set_size1() は画面上で設定された描画領域を反映させる関数です。
・ clar1()、draw1()、save_svg1()、save_png1() は、画面上のボタンをクリックしたときに実行する関数です。それぞれ、画面の消去、描画、SVG 画像の保存、PNG 画像の保存、に対応します。
・ convert1() は、SBI証券のサイトで取得できる四季報のデータから、財務諸表に必要なデータを抜き出して変換する関数です。この中で上記の (*03) の式を使っています。
・ check1() は、読み込んだ財務諸表の各パラメータから、(*01)、(*02) の式を使って、残りの科目の数値を求める関数です。この関数を事前に実行することで、財務諸表の各グラフの高さが確定します。
・ show1() は、BS、PL、CF の内部のパラメータをテキストエリアに書き出す関数です。
・ clear_statements1() は、内部パラメータとして定義してある BS、PL、CF の値をクリアして初期化する関数です。
・ read_statements1() は、テキストエリアに書かれた内容から、財務諸表の各科目を読み取って内部パラメータ BS、PL、CF に保存する関数です。
・ svg_rect1()、svg_bs1()、svg_pl1()、svg_cf1() は、内部のパラメータを読み取って、グラフの矩形、貸借対照表(BS)、損益計算書(PL)、キャッシュフロー計算書(CF)の画像を描く関数です。画像は SVG タグの文字列で返します。
・ svg_statements1() は、上記の財務三表をまとめて生成する関数です。生成した文字列は、画面下のテキストエリアに記載されます。
・ <body> タグ以降で、画面全体のレイアウトを定義しています。
この中で、各ボタンとテキストエリアを配置しています。
まとめ
財務諸表のグラフを表示する JavaScript のスクリプトをまとめました。
財務がわからないと就職・進学などの際に選択を間違えてしまうことがあります。また、NISA など株式の売買をする機会も増えています。金融リテラシーの教育や、高校・大学くらいで学んでいてもよい程度の内容だと思います。
プログラミングが得意な方や興味のある方は、スクリプトをカスタマイズして発展させてみてください。どうやって計算しているのか定義を確認してグラフを作っているうちに、財務の数値がどのように動くのか理解ができると思います。どちらかというと数学やプログラミング、自然科学の素養を先に身につけた人のほうが、経営指標の定量的な把握や分析力といった点で理解が早いと思います。
他にも、株価データの機械学習なども試みています。
もし興味があるようでしたら参照してみてください。
関連リンク
・ サイトを巡回してファイルをダウンロードする 【Python】
・ 機械学習で株価予測 【Python】
外部リンク [PR]
![]() |
![]()
サンプルスクリプト
財務諸表ビューア financial_statements1.html
<!DOCTYPE html>
<html lang="ja">
<title>financial_statements_generator v0.1</title>
<head>
<meta charset="UTF-8"/>
<script src="./financial_statements1.js"></script>
<script>
let str1_js = "";
let w1_svg = 750;
let h1_svg = 300;
let bs1 = [["総資産", ""], ["負債", ""], ["純資産", ""]];
let pl1 = [["年", "売上高", "営業利益", "純利益"]];
let cf1 = [["期首現金等", ""], ["営業CF", ""], ["投資CF", ""], ["財務CF", ""], ["現金等", ""]];
window.onload = load1;
function load1() {
if (typeof str1_statements !== 'undefined') { str1_js = str1_statements.trim(); }
document.getElementById("textarea2").value = str1_js;
document.getElementById("textbox1").value = w1_svg;
document.getElementById("textbox2").value = h1_svg;
textarea2();
set_tags1();
}
function set_size1() {
w1_svg = document.getElementById("textbox1").value;
h1_svg = document.getElementById("textbox2").value;
let str1 = '0 0 ' + w1_svg + ' ' + h1_svg;
document.getElementById('svg01').setAttribute('width', w1_svg);
document.getElementById('svg01').setAttribute('height', h1_svg);
document.getElementById('svg01').setAttribute('viewBox', str1);
set_tags1();
}
function clear1() {
document.getElementById("textarea2").value = "";
document.getElementById("textarea3").value = "";
draw1();
}
function draw1() {
let str1 = document.getElementById("textarea3").value.trim();
try {
document.getElementById("svg01").innerHTML = str1;
} catch (error) {
console.error("Invalid SVG script:", error);
}
}
function save_svg1() {
let file1 = "svg01.svg"
let str1 = document.getElementById("textarea4").value.trim();
let blob1 = new Blob([str1], {type: 'text/plain'});
let link1 = document.createElement('a');
link1.href = URL.createObjectURL( blob1 );
link1.download = file1;
link1.click();
}
function save_png1() {
let file1 = "image01.png";
let svg1 = document.getElementById('svg01');
let str1 = new XMLSerializer().serializeToString(svg1);
let canvas1 = document.createElement('canvas');
let context1 = canvas1.getContext('2d');
let img1 = new Image();
let blog1 = new Blob([str1], {type: 'image/svg+xml;charset=utf-8'});
let url1 = URL.createObjectURL( blog1 );
img1.onload = function() {
canvas1.width = svg1.clientWidth;
canvas1.height = svg1.clientHeight;
context1.drawImage(img1, 0, 0);
URL.revokeObjectURL(url1);
let url2 = canvas1.toDataURL('image/png').replace('image/png', 'image/octet-stream');
let link1 = document.createElement('a');
link1.href = url2;
link1.download = file1;
document.body.appendChild(link1);
link1.click();
document.body.removeChild(link1);
};
img1.src = url1;
}
function set_tags1() {
let str1 = document.getElementById("textarea3").value.trim();
str1 = '<svg x="0" y="0" width="' + w1_svg + '" height="' + h1_svg + '" xmlns="http://www.w3.org/2000/svg">\n' + str1 + '\n</svg>';
document.getElementById("textarea4").value = str1;
}
function convert1() {
clear_statements1();
clear1();
let str1 = document.getElementById("textarea1").value.trim();
str1 = str1.replace(/負債\t\n/g, "負債\t").replace(/. /g, ".").replace(/◇/g, "");
str1 = str1.replace(/自己資本/g, "純資産").replace("", "");
str1 = str1.replace(/,/g, "").replace(/\t/g, " ").replace(/ /g," ");
let a1 = str1.split("\n");
for (let i1 = 0; i1 < a1.length; i1++) {
a1[i1] = a1[i1].split(" ");
}
let str2 = "";
for (let i1 = 0; i1 < bs1.length; i1++) {
for (let i2 = 0; i2 < a1.length; i2++) {
if (a1[i2][0] == bs1[i1][0]) {
str2 = str2 + a1[i2][0] + " " + a1[i2][1] + "\n";
break;
}
}
}
str2 = str2 + "\n";
let type1 = -1;
let n1 = -1;
for (let i1 = 0; i1 < a1.length; i1++) {
if (type1 == -1 && a1[i1][1] == pl1[0][1]) { // normal format, sales
type1 = 1;
n1 = a1[i1].length;
str2 = str2 + pl1[0][0] + " " + pl1[0][1] + " " + pl1[0][2] + " " + pl1[0][3] + "\n";
} else if (type1 == -1 && a1[i1][1] == "経常収益") { // bank
type1 = 2;
n1 = a1[i1].length;
str2 = str2 + pl1[0][0] + " " + pl1[0][1] + " " + pl1[0][2] + " " + pl1[0][3] + "\n";
} else if (type1 > 0) {
if (a1[i1][0].includes("予") || a1[i1].length != n1 || type1 > 2) {
break;
} else if (a1[i1].length == n1) {
if (type1 == 1) {
str2 = str2 + a1[i1][0] + " " + a1[i1][1] + " " + a1[i1][2] + " " + a1[i1][4] + "\n"; // normal format
} else if (type1 == 2) {
str2 = str2 + a1[i1][0] + " " + a1[i1][1] + " " + a1[i1][3] + " " + a1[i1][4] + "\n"; // bank
} else {
type1 = 3;
}
}
}
}
str2 = str2 + "\n";
for (let i1 = 0; i1 < cf1.length; i1++) {
for (let i2 = 0; i2 < a1.length; i2++) {
if (a1[i2][0] == cf1[i1][0]) {
str2 = str2 + a1[i2][0] + " " + a1[i2][1] + "\n";
break;
}
}
}
document.getElementById("textarea2").value = str2;
read_statements1();
}
function check1() {
if ( bs1[1][1] == "" ) {
bs1[1][1] = bs1[0][1] - bs1[2][1];
}
if ( cf1[0][1] == "" ) {
cf1[0][1] = parseInt(cf1[4][1]) - ( parseInt(cf1[1][1]) + parseInt(cf1[2][1]) + parseInt(cf1[3][1]) );
}
}
function show1() {
let str1 = "";
for (let i1 = 0; i1 < bs1.length; i1++) {
str1 = str1 + bs1[i1][0] + " " + bs1[i1][1] + "\n";
}
str1 = str1 + "\n";
for (let i1 = 0; i1 < pl1.length; i1++) {
str1 = str1 + pl1[i1][0] + " " + pl1[i1][1] + " " + pl1[i1][2] + " " + pl1[i1][3] + "\n";
}
str1 = str1 + "\n";
for (let i1 = 0; i1 < cf1.length; i1++) {
str1 = str1 + cf1[i1][0] + " " + cf1[i1][1] + "\n";
}
document.getElementById("textarea2").value = str1;
}
function clear_statements1() {
for (let i1 = 0; i1 < bs1.length; i1++) { // BS
bs1[i1][1] = "";
}
pl1 = [pl1[0]]; // PL
for (let i1 = 0; i1 < cf1.length; i1++) { // CF
cf1[i1][1] = "";
}
}
function textarea2() {
read_statements1();
}
function read_statements1() {
clear_statements1();
let str1 = document.getElementById("textarea2").value.trim();
str1 = str1.replace(/\t/g, " ").replace(/,/g, "").replace(/ /g, " ");
let a1 = str1.split("\n");
for (let i1 = 0; i1 < a1.length; i1++) {
a1[i1] = a1[i1].split(" ");
}
for (let i1 = 0; i1 < a1.length; i1++) {
for (let i2 = 0; i2 < bs1.length; i2++) {
if (a1[i1][0] == bs1[i2][0]) {
bs1[i2][1] = a1[i1][1];
break;
}
}
}
let i2 = -1;
for (let i1 = 0; i1 < a1.length; i1++) {
if (i2 > 0) {
if (a1[i1].length != pl1[0].length) {
break;
}
pl1.push(["", "", "", ""]);
pl1[i2][0] = a1[i1][0];
pl1[i2][1] = a1[i1][1];
pl1[i2][2] = a1[i1][2];
pl1[i2][3] = a1[i1][3];
i2 = i2 + 1;
} else {
if (a1[i1][1] == pl1[0][1]) { // sales
i2 = 1;
}
}
}
for (let i1 = 0; i1 < a1.length; i1++) {
for (let i2 = 0; i2 < cf1.length; i2++) {
if (a1[i1][0] == cf1[i2][0]) {
cf1[i2][1] = a1[i1][1];
break;
}
}
}
check1();
svg_statements1();
}
function svg_rect1(x0, y0, y1, dely0, w0, h0, fill1, s11, s12) {
let h1 = h0;
let y2 = y1;
if (h1 < 0) {
h1 = -h1;
y2 = y2+h1-1;
}
let str0 = `
<rect x="${x0 }" y="${y0-h0-y2 }" width="${w0}" height="${h1}" fill="${fill1}" />
<text x="${x0+w0/2}" y="${y0-h0-y2+h1/2+dely0-8}" text-anchor="middle" font-size="12">${s11}</text>
<text x="${x0+w0/2}" y="${y0-h0-y2+h1/2+dely0+8}" text-anchor="middle" font-size="12">${s12}</text>
`;
return str0.trim() + "\n";
}
function svg_bs1() {
let x0 = 20;
let y0 = 40;
let h0 = 200;
let s11 = bs1[0][0];
let s12 = bs1[0][1];
let s21 = bs1[1][0];
let s22 = bs1[1][1];
let s31 = bs1[2][0];
let s32 = bs1[2][1];
let str0 = "";
if (s12 != "") {
let h1 = Math.floor(s22 / s12 * h0);
let h2 = h0 - h1;
let h3 = s12;
str0 = str0 + svg_rect1(x0 , y0+h0, 0, 0, 80, h0, "#aaffaa", s11, s12);
str0 = str0 + svg_rect1(x0+80, y0+h0, h2, 0, 80, h1, "#ffaaaa", s21, s22);
str0 = str0 + svg_rect1(x0+80, y0+h0, 0, 0, 80, h2, "#aaaaff", s31, s32);
str0 = str0.trim() + "\n";
}
return str0;
}
function svg_pl1() {
let x0 = 20;
let y0 = 40;
let h0 = 200;
let n1 = pl1.length-1;
let str0 = "";
if (pl1.length > 1) {
let s11 = pl1[ 0][1];
let s12 = pl1[n1][1];
let s21 = pl1[ 0][2];
let s22 = pl1[n1][2];
let s31 = pl1[ 0][3];
let s32 = pl1[n1][3];
let h1 = Math.floor(s22/s12 * h0);
let h2 = Math.floor(s32/s12 * h0);
str0 = str0 + svg_rect1(x0+190, y0+h0, 0, 0, 60, h0, "#aaeeee", s11, s12);
str0 = str0 + svg_rect1(x0+250, y0+h0, 0,-22, 60, h1, "#ffaaff", s21, s22);
str0 = str0 + svg_rect1(x0+310, y0+h0, 0,-22, 60, h2, "#aaaaff", s31, s32);
str0 = str0.trim() + "\n";
}
return str0;
}
function svg_cf1() {
let x0 = 20;
let y0 = 40;
let h0 = 200;
let s11 = cf1[0][0];
let s12 = cf1[0][1];
let s21 = cf1[1][0];
let s22 = cf1[1][1];
let s31 = cf1[2][0];
let s32 = cf1[2][1];
let s41 = cf1[3][0];
let s42 = cf1[3][1];
let s51 = cf1[4][0];
let s52 = cf1[4][1];
let str0 = "";
if (s22 != "") {
let y1 = 0;
let h1 = parseInt(s12);
let y2 = y1 + h1;
let h2 = parseInt(s22);
let y3 = y2 + h2;
let h3 = parseInt(s32);
let y4 = y3 + h3;
let h4 = parseInt(s42);
let y5 = y4 + h4;
let h5 = parseInt(s52);
let max1 = y1;
if (max1 < y2) { max1 = y2; }
if (max1 < y3) { max1 = y3; }
if (max1 < y4) { max1 = y4; }
if (max1 < y5) { max1 = y5; }
y1 = Math.floor(y1/max1 * h0);
y2 = Math.floor(y2/max1 * h0);
y3 = Math.floor(y3/max1 * h0);
y4 = Math.floor(y4/max1 * h0);
y5 = Math.floor(y5/max1 * h0);
h1 = Math.floor(h1/max1 * h0);
h2 = Math.floor(h2/max1 * h0);
h3 = Math.floor(h3/max1 * h0);
h4 = Math.floor(h4/max1 * h0);
h5 = Math.floor(h5/max1 * h0);
str0 = str0 + svg_rect1(x0+400, y0+h0, y1, 0, 60, h1, "#ffbb88", s11, s12);
str0 = str0 + svg_rect1(x0+460, y0+h0, y2, 0, 60, h2, "#ffaaff", s21, s22);
str0 = str0 + svg_rect1(x0+520, y0+h0, y3, 0, 60, h3, "#aaeeff", s31, s32);
str0 = str0 + svg_rect1(x0+580, y0+h0, y4, 0, 60, h4, "#ffbbbb", s41, s42);
str0 = str0 + svg_rect1(x0+640, y0+h0, y1, 0, 60, h5, "#ffbb88", s51, s52);
str0 = str0.trim() + "\n";
}
return str0;
}
function svg_statements1() {
let str1 = "";
str1 = str1 + svg_bs1() + "\n";
str1 = str1 + svg_pl1() + "\n";
str1 = str1 + svg_cf1() + "\n";
document.getElementById("textarea3").value = str1.trim();
set_tags1();
}
</script>
<style>
body {
margin: 10px;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 5fr 3fr;
grid-template-areas:
"buttons1 buttons1"
"area1 text1"
"text2 text2";
column-gap: 10px;
height: 100vh;
}
</style>
</head>
<body style="background-color:#eeeeee; font-family: helvetica, arial, sans-serif, 'Meiryo UI', Meiryo; ">
<div style="grid-area:buttons1;">
<button onclick="clear1()">clear</button>
<button onclick="draw1()">draw</button>
<button onclick="save_svg1()">save svg</button>
<button onclick="save_png1()">save png</button>
width:<input type="text" id="textbox1" style="width:60px; height:14px; margin-right:-5px;" onchange="set_size1()">
height:<input type="text" id="textbox2" style="width:60px; height:14px; margin-right:-5px;" onchange="set_size1()"><br>
</div>
<div style="grid-area:area1;">
<svg id="svg01" x="0" y="0" width="750" height="300" viewBox= "0 0 750 300" style="background-color:#ffffff" xmlns="http://www.w3.org/2000/svg"></svg><br>
</div>
<div style="grid-area:text1;">
<textarea id="textarea2" rows="22" cols="30" onchange="textarea2()"></textarea><br>
</div>
<div style="grid-area:text2;">
<br><br>
<button onclick="convert1()">convert</button><br>
<textarea id="textarea1" rows="5" cols="80"></textarea><br>
<textarea id="textarea3" style="width:10px; height:10px;"></textarea>
<textarea id="textarea4" style="width:10px; height:10px;"></textarea><br>
</div>
</body>
</html>
設定ファイル financial_statements1.js
window.str1_statements = `
総資産 93000000
純資産 36000000
年 売上高 営業利益 純利益
23.3 37000000 2700000 2400000
24.3 45000000 5300000 4900000
25.3 48000000 4700000 4700000
営業CF 36000
投資CF -41000
財務CF 1000
現金等 89000
`;


