[{"data":1,"prerenderedAt":711},["ShallowReactive",2],{"content-/ib-format-cf-worksheet-automation":3,"all-pages-for-dir":709,"og-image-/ib-format-cf-worksheet-automation":710},{"id":4,"title":5,"body":6,"category":688,"description":689,"extension":690,"meta":691,"navigation":692,"path":693,"project_name":694,"published":695,"publishedAt":696,"seo":697,"stem":698,"tags":699,"todo":706,"updatedAt":707,"__hash__":708},"pages/2026-04/2026-04-01/ib-format-cf-worksheet-automation.md","投資銀行モデル書式の自動適用とCF精算表生成スキルを構築した",{"type":7,"value":8,"toc":671},"minimark",[9,14,18,23,27,30,86,89,98,105,108,132,136,139,149,152,335,338,348,352,355,358,361,364,367,373,399,402,407,418,423,429,594,597,601,604,607,610,618,621,624,627,658,661,664,667],[10,11,13],"h1",{"id":12},"投資銀行モデル書式の自動適用とcf精算表生成スキル","投資銀行モデル書式の自動適用とCF精算表生成スキル",[15,16,17],"p",{},"朝、財務モデルのExcelを開いて手作業でセルの色を塗り分けている自分に気づいた。青はハードコード値、黒は数式、緑は他シート参照。毎回同じ作業を繰り返している。これをClaude Codeのスキルにしてしまえば二度と手で塗らなくて済む。そこから一日が始まった。",[19,20,22],"h2",{"id":21},"ib-format-スキル-投資銀行カラーコーディングの自動適用","/ib-format スキル: 投資銀行カラーコーディングの自動適用",[24,25,26],"h3",{"id":26},"書式ルール",[15,28,29],{},"投資銀行の財務モデルには暗黙の書式ルールがある。",[31,32,33,49],"table",{},[34,35,36],"thead",{},[37,38,39,43,46],"tr",{},[40,41,42],"th",{},"セルの中身",[40,44,45],{},"フォント色",[40,47,48],{},"意味",[50,51,52,64,75],"tbody",{},[37,53,54,58,61],{},[55,56,57],"td",{},"ハードコード値（手入力）",[55,59,60],{},"青",[55,62,63],{},"前提条件。変えてよい数字",[37,65,66,69,72],{},[55,67,68],{},"数式（同一シート内参照）",[55,70,71],{},"黒",[55,73,74],{},"計算ロジック",[37,76,77,80,83],{},[55,78,79],{},"他シート参照の数式",[55,81,82],{},"緑",[55,84,85],{},"外部依存。参照先を追う必要あり",[15,87,88],{},"これをExcelとGoogle Sheetsの両方に自動適用するスキルを作った。",[24,90,92,93,97],{"id":91},"数値書式の-red-除去","数値書式の ",[94,95,96],"code",{},"[Red]"," 除去",[15,99,100,101,104],{},"既存のExcelファイルに ",[94,102,103],{},"#,##0;[Red](#,##0)"," のような数値書式が設定されていた。マイナス値が強制的に赤になる書式だ。投資銀行モデルではフォント色に意味があるので、数値書式側で色を上書きされると困る。",[15,106,107],{},"修正内容は2つ。",[109,110,111,121],"ol",{},[112,113,114,116,117,120],"li",{},[94,115,96],{}," を除去して ",[94,118,119],{},"#,##0;(#,##0)"," に変更（フォント色に従うようになる）",[112,122,123,124,127,128,131],{},"マイナス表記を ",[94,125,126],{},"△"," から ",[94,129,130],{},"▲"," に変更（視認性向上）",[24,133,135],{"id":134},"google-sheets-api-での書式適用","Google Sheets API での書式適用",[15,137,138],{},"Excel側はopenpyxlで素直に実装できた。問題はGoogle Sheets API側だった。",[15,140,141,144,145,148],{},[94,142,143],{},"batchUpdate"," の ",[94,146,147],{},"repeatCell"," リクエストでセル範囲にフォント色を適用する方式を採った。ここでバッチサイズの壁にぶつかった。",[15,150,151],{},"最初は全セルを1リクエストにまとめて送った。シートが大きいとAPIがタイムアウトする。セルごとに1リクエストにすると、今度はAPI呼び出し回数の上限に引っかかる。結局、100セルずつにチャンクして送る方式に落ち着いた。",[153,154,159],"pre",{"className":155,"code":156,"language":157,"meta":158,"style":158},"language-python shiki shiki-themes vitesse-light vitesse-light","# セルをチャンクに分割してbatchUpdate\nBATCH_SIZE = 100\nfor i in range(0, len(requests), BATCH_SIZE):\n    chunk = requests[i:i + BATCH_SIZE]\n    service.spreadsheets().batchUpdate(\n        spreadsheetId=sheet_id,\n        body={\"requests\": chunk}\n    ).execute()\n","python","",[94,160,161,170,185,229,262,282,297,323],{"__ignoreMap":158},[162,163,166],"span",{"class":164,"line":165},"line",1,[162,167,169],{"class":168},"sxvE3","# セルをチャンクに分割してbatchUpdate\n",[162,171,173,177,181],{"class":164,"line":172},2,[162,174,176],{"class":175},"snbK4","BATCH_SIZE",[162,178,180],{"class":179},"shFtX"," =",[162,182,184],{"class":183},"sM54T"," 100\n",[162,186,188,192,196,199,203,206,209,212,215,217,220,223,226],{"class":164,"line":187},3,[162,189,191],{"class":190},"sHkkW","for",[162,193,195],{"class":194},"sG7-3"," i ",[162,197,198],{"class":190},"in",[162,200,202],{"class":201},"sz8Xr"," range",[162,204,205],{"class":179},"(",[162,207,208],{"class":183},"0",[162,210,211],{"class":179},",",[162,213,214],{"class":201}," len",[162,216,205],{"class":179},[162,218,219],{"class":194},"requests",[162,221,222],{"class":179},"),",[162,224,225],{"class":175}," BATCH_SIZE",[162,227,228],{"class":179},"):\n",[162,230,232,235,238,241,244,247,250,253,257,259],{"class":164,"line":231},4,[162,233,234],{"class":194},"    chunk ",[162,236,237],{"class":179},"=",[162,239,240],{"class":194}," requests",[162,242,243],{"class":179},"[",[162,245,246],{"class":194},"i",[162,248,249],{"class":179},":",[162,251,252],{"class":194},"i ",[162,254,256],{"class":255},"stQ0i","+",[162,258,225],{"class":175},[162,260,261],{"class":179},"]\n",[162,263,265,268,271,274,277,279],{"class":164,"line":264},5,[162,266,267],{"class":194},"    service",[162,269,270],{"class":179},".",[162,272,273],{"class":194},"spreadsheets",[162,275,276],{"class":179},"().",[162,278,143],{"class":194},[162,280,281],{"class":179},"(\n",[162,283,285,289,291,294],{"class":164,"line":284},6,[162,286,288],{"class":287},"s4oTP","        spreadsheetId",[162,290,237],{"class":179},[162,292,293],{"class":194},"sheet_id",[162,295,296],{"class":179},",\n",[162,298,300,303,306,310,313,315,317,320],{"class":164,"line":299},7,[162,301,302],{"class":287},"        body",[162,304,305],{"class":179},"={",[162,307,309],{"class":308},"sMJiu","\"",[162,311,219],{"class":312},"sdGka",[162,314,309],{"class":308},[162,316,249],{"class":179},[162,318,319],{"class":194}," chunk",[162,321,322],{"class":179},"}\n",[162,324,326,329,332],{"class":164,"line":325},8,[162,327,328],{"class":179},"    ).",[162,330,331],{"class":194},"execute",[162,333,334],{"class":179},"()\n",[24,336,337],{"id":337},"gws認証の問題",[15,339,340,341,344,345,347],{},"Google Sheets APIへのアクセスには自前のCLIツール ",[94,342,343],{},"gws"," を使っている。Pythonスクリプトから直接Google APIを叩くのではなく、",[94,346,343],{}," 経由でOAuth認証済みトークンを取得してAPIに渡す方式にした。認証フローを二重に持たなくて済む。",[19,349,351],{"id":350},"cf-worksheet-スキル-cf精算表の自動生成","/cf-worksheet スキル: CF精算表の自動生成",[24,353,354],{"id":354},"何を作ったか",[15,356,357],{},"会計ソフトAから出力した合計残高試算表（TB）のExcelを入力として、間接法のキャッシュフロー精算表（CFWS）をopenpyxlで自動生成するスキル。",[15,359,360],{},"決算のたびにExcelで手作業していたCF精算表を、コマンド一発で生成できるようにした。",[24,362,363],{"id":363},"v1からv13まで13回のイテレーション",[15,365,366],{},"一発で完成したわけではない。v1で基本構造を組んでから、v13まで13回書き直した。主な改善の流れを振り返る。",[15,368,369],{},[370,371,372],"strong",{},"構造の整理（v1-v5）",[374,375,376,379,382,385],"ul",{},[112,377,378],{},"I列（不要だった中間計算列）を削除",[112,380,381],{},"P列（予備列）を削除",[112,383,384],{},"J列の幅を18に統一",[112,386,387,388],{},"各CF区分の列範囲を制限した\n",[374,389,390,393,396],{},[112,391,392],{},"営業CF: J-M列",[112,394,395],{},"投資CF: N列のみ",[112,397,398],{},"財務CF: O列のみ",[15,400,401],{},"列範囲の制限が地味に効いた。全区分が全列に値を持てる状態だと、どの列がどの区分か一目で判別できない。列を絞ることで、シートを開いた瞬間に構造が目に入るようになった。",[15,403,404],{},[370,405,406],{},"見た目の調整（v6-v10）",[374,408,409,412,415],{},[112,410,411],{},"合計行にグレー濃淡を適用しボールドに",[112,413,414],{},"ズーム85%に設定（全体が一画面に収まる）",[112,416,417],{},"H列にPL計上額チェックを移動",[15,419,420],{},[370,421,422],{},"CFラベルマッピング（v11-v13）",[15,424,425,428],{},[94,426,427],{},"cf-labels.json"," を作成した。BS科目からCFラベルへの対応表だ。",[153,430,434],{"className":431,"code":432,"language":433,"meta":158,"style":158},"language-json shiki shiki-themes vitesse-light vitesse-light","{\n  \"売掛金\": { \"cf_label\": \"売上債権の増減額\", \"cf_category\": \"operating\" },\n  \"建物\": { \"cf_label\": \"有形固定資産の取得\", \"cf_category\": \"investing\" },\n  \"借入金\": { \"cf_label\": \"借入れによる収入\", \"cf_category\": \"financing\" }\n}\n","json",[94,435,436,441,495,542,590],{"__ignoreMap":158},[162,437,438],{"class":164,"line":165},[162,439,440],{"class":179},"{\n",[162,442,443,447,450,452,454,457,460,463,465,467,469,472,474,476,478,481,483,485,487,490,492],{"class":164,"line":172},[162,444,446],{"class":445},"sqvqQ","  \"",[162,448,449],{"class":201},"売掛金",[162,451,309],{"class":445},[162,453,249],{"class":179},[162,455,456],{"class":179}," {",[162,458,459],{"class":445}," \"",[162,461,462],{"class":201},"cf_label",[162,464,309],{"class":445},[162,466,249],{"class":179},[162,468,459],{"class":308},[162,470,471],{"class":312},"売上債権の増減額",[162,473,309],{"class":308},[162,475,211],{"class":179},[162,477,459],{"class":445},[162,479,480],{"class":201},"cf_category",[162,482,309],{"class":445},[162,484,249],{"class":179},[162,486,459],{"class":308},[162,488,489],{"class":312},"operating",[162,491,309],{"class":308},[162,493,494],{"class":179}," },\n",[162,496,497,499,502,504,506,508,510,512,514,516,518,521,523,525,527,529,531,533,535,538,540],{"class":164,"line":187},[162,498,446],{"class":445},[162,500,501],{"class":201},"建物",[162,503,309],{"class":445},[162,505,249],{"class":179},[162,507,456],{"class":179},[162,509,459],{"class":445},[162,511,462],{"class":201},[162,513,309],{"class":445},[162,515,249],{"class":179},[162,517,459],{"class":308},[162,519,520],{"class":312},"有形固定資産の取得",[162,522,309],{"class":308},[162,524,211],{"class":179},[162,526,459],{"class":445},[162,528,480],{"class":201},[162,530,309],{"class":445},[162,532,249],{"class":179},[162,534,459],{"class":308},[162,536,537],{"class":312},"investing",[162,539,309],{"class":308},[162,541,494],{"class":179},[162,543,544,546,549,551,553,555,557,559,561,563,565,568,570,572,574,576,578,580,582,585,587],{"class":164,"line":231},[162,545,446],{"class":445},[162,547,548],{"class":201},"借入金",[162,550,309],{"class":445},[162,552,249],{"class":179},[162,554,456],{"class":179},[162,556,459],{"class":445},[162,558,462],{"class":201},[162,560,309],{"class":445},[162,562,249],{"class":179},[162,564,459],{"class":308},[162,566,567],{"class":312},"借入れによる収入",[162,569,309],{"class":308},[162,571,211],{"class":179},[162,573,459],{"class":445},[162,575,480],{"class":201},[162,577,309],{"class":445},[162,579,249],{"class":179},[162,581,459],{"class":308},[162,583,584],{"class":312},"financing",[162,586,309],{"class":308},[162,588,589],{"class":179}," }\n",[162,591,592],{"class":164,"line":264},[162,593,322],{"class":179},[15,595,596],{},"このマッピングがあると、TBの科目名を読んだ時点でCF精算表のどの行・どの列に値を配置するかが自動で決まる。手動で科目を分類する必要がなくなった。",[24,598,600],{"id":599},"tbシート特定ルール","TBシート特定ルール",[15,602,603],{},"会計ソフトAからエクスポートしたExcelファイルには複数シートが含まれることがある。TBシートを自動特定するルールを追加した。シート名に「残高試算表」「TB」「合計残高」のいずれかが含まれるシートを探す。見つからなければ最初のシートをTBとして扱う。",[24,605,606],{"id":606},"出力先の固定",[15,608,609],{},"生成したCF精算表の出力先をDropbox配下に固定した。ファイル名にはタイムスタンプを付与する。",[153,611,616],{"className":612,"code":614,"language":615},[613],"language-text","~/Dropbox/会計/CFWS_2026-04-01_143022.xlsx\n","text",[94,617,614],{"__ignoreMap":158},[15,619,620],{},"同じTBから何度生成しても上書きされない。過去の生成結果を比較できるようにした。",[19,622,623],{"id":623},"bashのクォーティング問題",[15,625,626],{},"開発中、Claude Codeからbashコマンドでスキルを呼び出す際にクォーティングが壊れる問題に何度かぶつかった。JSONの中にダブルクォートがあると、bash側のクォートと干渉する。ヒアドキュメントで回避した。",[153,628,632],{"className":629,"code":630,"language":631,"meta":158,"style":158},"language-bash shiki shiki-themes vitesse-light vitesse-light","python cf_worksheet.py \u003C\u003C'EOF'\n{\"input\": \"path/to/tb.xlsx\", \"output_dir\": \"~/Dropbox/会計/\"}\nEOF\n","bash",[94,633,634,648,653],{"__ignoreMap":158},[162,635,636,639,642,645],{"class":164,"line":165},[162,637,157],{"class":638},"senZ8",[162,640,641],{"class":312}," cf_worksheet.py",[162,643,644],{"class":255}," \u003C\u003C",[162,646,647],{"class":308},"'EOF'\n",[162,649,650],{"class":164,"line":172},[162,651,652],{"class":312},"{\"input\": \"path/to/tb.xlsx\", \"output_dir\": \"~/Dropbox/会計/\"}\n",[162,654,655],{"class":164,"line":187},[162,656,657],{"class":308},"EOF\n",[19,659,660],{"id":660},"振り返り",[15,662,663],{},"朝の「手作業が面倒だ」から始めて、2つのスキルが形になった。/ib-formatは書式適用の5分を0秒にし、/cf-worksheetはCF精算表の2時間を10秒に縮めた。",[15,665,666],{},"13回のイテレーションは多いように見えるが、実際にシートを開いて「ここが見づらい」「この列は要らない」と気づくたびに直した結果だ。最初から完成形を設計しようとするより、生成結果を眺めながら削り込むほうが速かった。",[668,669,670],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sqvqQ, html code.shiki .sqvqQ{--shiki-default:#99841877;--shiki-dark:#99841877}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}",{"title":158,"searchDepth":172,"depth":172,"links":672},[673,680,686,687],{"id":21,"depth":172,"text":22,"children":674},[675,676,678,679],{"id":26,"depth":187,"text":26},{"id":91,"depth":187,"text":677},"数値書式の [Red] 除去",{"id":134,"depth":187,"text":135},{"id":337,"depth":187,"text":337},{"id":350,"depth":172,"text":351,"children":681},[682,683,684,685],{"id":354,"depth":187,"text":354},{"id":363,"depth":187,"text":363},{"id":599,"depth":187,"text":600},{"id":606,"depth":187,"text":606},{"id":623,"depth":172,"text":623},{"id":660,"depth":172,"text":660},"dev","Excelとスプレッドシートに投資銀行カラーコーディング（青/黒/緑）を自動適用する/ib-formatスキルと、会計ソフトの残高試算表からCF精算表を自動生成する/cf-worksheetスキルをClaude Code上で構築した記録","md",{},true,"/ib-format-cf-worksheet-automation","eurekapu-nuxt4",false,"2026-04-01T00:00:00.000Z",{"title":5,"description":689},"2026-04/2026-04-01/ib-format-cf-worksheet-automation",[700,701,702,703,704,705],"投資銀行モデル","Excel自動化","CF精算表","Claude Code","openpyxl","Google Sheets API","memo",null,"y_gTOqbVJ5SPnKx1BC1JLN_P-Dprck6E3gH7bcZ5J4c",[],"https://log.eurekapu.com/favicon.svg",1775338203697]