[{"data":1,"prerenderedAt":438},["ShallowReactive",2],{"content-/cfws-screenshot-structuring":3,"all-pages-for-dir":436,"og-image-/cfws-screenshot-structuring":437},{"id":4,"title":5,"body":6,"category":415,"description":416,"extension":417,"meta":418,"navigation":419,"path":420,"project_name":421,"published":422,"publishedAt":423,"seo":424,"stem":425,"tags":426,"todo":433,"updatedAt":434,"__hash__":435},"pages/2026-04/2026-04-15/cfws-screenshot-structuring.md","CF精算表スクリーンショット撮影からHTMLテーブル構造化までの全工程記録",{"type":7,"value":8,"toc":396},"minimark",[9,13,17,20,24,29,37,40,43,46,48,52,55,62,66,73,92,130,133,136,139,141,145,149,156,160,167,170,174,184,344,346,350,353,356,378,381,383,386,389,392],[10,11,12],"h2",{"id":12},"この日やったこと",[14,15,16],"p",{},"参考書PDFに掲載されている全37論点（Q1〜Q37）のCF精算表を、スクリーンショット撮影 → クロップ → HTMLテーブル化 → 照合レビューまで一気に通した。朝はズーム倍率の試行錯誤に手が止まり、昼からクロップ座標の微調整を繰り返し、夕方にはHTMLテーブル化と全Q照合まで駆け抜けた。",[18,19],"hr",{},[10,21,23],{"id":22},"スクリーンショット撮影全39枚","スクリーンショット撮影（全39枚）",[25,26,28],"h3",{"id":27},"chrome-devtoolsでpdfページ移動を自動化","Chrome DevToolsでPDFページ移動を自動化",[14,30,31,32,36],{},"Chrome DevToolsのMCP経由でPDFを開き、ページ入力欄（",[33,34,35],"code",{},"uid=1_5","）に値をfillしてページ移動する方式を採った。各Q番号に対応するページ番号はTurso DBから引いてきたが、PDFの実ページとDBのページ番号がずれているケースがあり、1件ずつ照合して補正した。",[25,38,39],{"id":39},"ズーム設定の試行錯誤",[14,41,42],{},"最初は横画面モニターで75%ズームで撮影を始めた。数枚撮って確認すると、精算表の細かい数字が潰れて読めない。縦モニターに切り替えて200%ズームに変更したら、セルの罫線まではっきり写った。最初の数枚は撮り直しになったが、200%ズームにしてからは数字の1と7、6と8の区別もつくようになり、早めに切り替えて正解だった。",[14,44,45],{},"撮影は全39枚（Q3など複数ページにまたがる論点がある）。1枚あたりの撮影サイクルは「ページ番号fill → スクリーンショット取得 → ファイル保存」で、リズムに乗ると1枚30秒ほどで回せた。",[18,47],{},[10,49,51],{"id":50},"imagemagickによる精算表クロップ","ImageMagickによる精算表クロップ",[25,53,54],{"id":54},"指示書を作って段取りを固める",[14,56,57,58,61],{},"クロップ作業に入る前に、手順を",[33,59,60],{},"crop-cfws-screenshots.md","として指示書にまとめた。Codexレビューを2回かけて、座標指定の考え方とエッジケース（注記が表の下にはみ出すパターン）を洗い出した。",[25,63,65],{"id":64},"座標特定クロップ確認のサイクル","座標特定→クロップ→確認のサイクル",[14,67,68,69,72],{},"ImageMagickの",[33,70,71],{},"convert","コマンドで座標指定クロップを実行した。基本フローは以下の繰り返し:",[74,75,76,80,86,89],"ol",{},[77,78,79],"li",{},"元画像を読み取って精算表の四隅の座標を特定",[77,81,82,85],{},[33,83,84],{},"convert input.png -crop WxH+X+Y output.png"," で切り出し",[77,87,88],{},"クロップ結果を目視確認",[77,90,91],{},"問題があれば座標を修正して再クロップ",[93,94,99],"pre",{"className":95,"code":96,"language":97,"meta":98,"style":98},"language-bash shiki shiki-themes vitesse-light vitesse-light","# クロップの基本コマンド（座標は論点ごとに異なる）\nconvert Q03-2.png -crop 1800x900+120+340 Q03-2_cropped.png\n","bash","",[33,100,101,110],{"__ignoreMap":98},[102,103,106],"span",{"class":104,"line":105},"line",1,[102,107,109],{"class":108},"sxvE3","# クロップの基本コマンド（座標は論点ごとに異なる）\n",[102,111,113,116,120,124,127],{"class":104,"line":112},2,[102,114,71],{"class":115},"senZ8",[102,117,119],{"class":118},"sdGka"," Q03-2.png",[102,121,123],{"class":122},"snbK4"," -crop",[102,125,126],{"class":118}," 1800x900+120+340",[102,128,129],{"class":118}," Q03-2_cropped.png\n",[25,131,132],{"id":132},"注記切れとの格闘",[14,134,135],{},"精算表の下部には「＜＊A＞」〜「＜＊F＞」といった注記が付いている論点がある。最初に設定したbottom座標では注記が途中で切れた。bottomを50px拡大して再クロップ → まだ切れる → さらに80px拡大 → 今度は余白が大きすぎる → 60pxに戻す、というサイクルを何度か回した。",[14,137,138],{},"論点によって注記の行数が1行〜6行まで幅があるため、一律の座標では対応できない。結局、1枚ずつ画像を読み取って注記の有無と行数を確認し、個別に座標を調整する方式に落ち着いた。手間はかかるが、注記が欠けた状態で後工程に進むとHTMLテーブル化の段階で情報が抜け落ちるので、ここは妥協しなかった。",[18,140],{},[10,142,144],{"id":143},"htmlテーブル化構造化データ変換","HTMLテーブル化（構造化データ変換）",[25,146,148],{"id":147},"q3-2をサンプルとして手動変換","Q3-2をサンプルとして手動変換",[14,150,151,152,155],{},"まずQ3-2（固定資産の減損）を1件だけ手動でHTMLテーブルに変換し、品質を確かめた。精算表のセル構造をそのまま",[33,153,154],{},"\u003Ctable>","に写し取り、数値の正負・空白セル・結合セルを再現する。サンプル1件の変換で「この粒度なら全Q分いける」と手応えを掴んだ。",[25,157,159],{"id":158},"全37q分をindexhtmlに統合","全37Q分をindex.htmlに統合",[14,161,162,163,166],{},"37Q分のHTMLテーブルを1つの",[33,164,165],{},"index.html","に統合した。タブ切替UIを実装し、各Qをワンクリックで表示できるようにした。左右の矢印キーでQ間を移動できる操作性も追加した。",[14,168,169],{},"各タブにはクロップ済みのスクリーンショット画像も並べて配置し、「元画像」と「HTMLテーブル」を横に並べて照合できる構成にした。",[25,171,173],{"id":172},"build_indexpyで再構築可能に","build_index.pyで再構築可能に",[14,175,176,177,179,180,183],{},"個別のHTMLテーブルファイルから",[33,178,165],{},"を再生成する",[33,181,182],{},"build_index.py","を用意した。新しいQ番号が追加されたり、既存のテーブルを修正したりしたときに、スクリプトを1回叩けば統合ファイルが再構築される。",[93,185,189],{"className":186,"code":187,"language":188,"meta":98,"style":98},"language-python shiki shiki-themes vitesse-light vitesse-light","# build_index.py の骨格（個別HTMLを読み込んでタブUIに統合）\nfor q_file in sorted(glob(\"Q*.html\")):\n    q_name = q_file.stem\n    tabs.append(f'\u003Cbutton onclick=\"showTab(\\'{q_name}\\')\">{q_name}\u003C/button>')\n    panels.append(f'\u003Cdiv id=\"{q_name}\">{q_file.read_text()}\u003C/div>')\n","python",[33,190,191,196,234,252,298],{"__ignoreMap":98},[102,192,193],{"class":104,"line":105},[102,194,195],{"class":108},"# build_index.py の骨格（個別HTMLを読み込んでタブUIに統合）\n",[102,197,198,202,206,209,213,217,220,222,226,229,231],{"class":104,"line":112},[102,199,201],{"class":200},"sHkkW","for",[102,203,205],{"class":204},"sG7-3"," q_file ",[102,207,208],{"class":200},"in",[102,210,212],{"class":211},"sz8Xr"," sorted",[102,214,216],{"class":215},"shFtX","(",[102,218,219],{"class":204},"glob",[102,221,216],{"class":215},[102,223,225],{"class":224},"sMJiu","\"",[102,227,228],{"class":118},"Q*.html",[102,230,225],{"class":224},[102,232,233],{"class":215},")):\n",[102,235,237,240,243,246,249],{"class":104,"line":236},3,[102,238,239],{"class":204},"    q_name ",[102,241,242],{"class":215},"=",[102,244,245],{"class":204}," q_file",[102,247,248],{"class":215},".",[102,250,251],{"class":204},"stem\n",[102,253,255,258,260,263,265,269,272,275,278,281,284,287,289,292,295],{"class":104,"line":254},4,[102,256,257],{"class":204},"    tabs",[102,259,248],{"class":215},[102,261,262],{"class":204},"append",[102,264,216],{"class":215},[102,266,268],{"class":267},"stQ0i","f",[102,270,271],{"class":118},"'\u003Cbutton onclick=\"showTab(",[102,273,274],{"class":122},"\\'{",[102,276,277],{"class":204},"q_name",[102,279,280],{"class":122},"}\\'",[102,282,283],{"class":118},")\">",[102,285,286],{"class":122},"{",[102,288,277],{"class":204},[102,290,291],{"class":122},"}",[102,293,294],{"class":118},"\u003C/button>'",[102,296,297],{"class":215},")\n",[102,299,301,304,306,308,310,312,315,317,319,321,324,326,329,331,334,337,339,342],{"class":104,"line":300},5,[102,302,303],{"class":204},"    panels",[102,305,248],{"class":215},[102,307,262],{"class":204},[102,309,216],{"class":215},[102,311,268],{"class":267},[102,313,314],{"class":118},"'\u003Cdiv id=\"",[102,316,286],{"class":122},[102,318,277],{"class":204},[102,320,291],{"class":122},[102,322,323],{"class":118},"\">",[102,325,286],{"class":122},[102,327,328],{"class":204},"q_file",[102,330,248],{"class":215},[102,332,333],{"class":204},"read_text",[102,335,336],{"class":215},"()",[102,338,291],{"class":122},[102,340,341],{"class":118},"\u003C/div>'",[102,343,297],{"class":215},[18,345],{},[10,347,349],{"id":348},"全q照合レビュー","全Q照合レビュー",[14,351,352],{},"最後に、全37Q分のスクリーンショットとHTMLテーブルを1セルずつ突き合わせた。数値の転記ミス、符号の反転、空白セルの見落としを1件ずつ潰していく作業で、全てOKを確認して完了とした。",[14,354,355],{},"照合で見つかりやすいミスのパターン:",[357,358,359,366,372],"ul",{},[77,360,361,365],{},[362,363,364],"strong",{},"符号反転",": 減算項目（△表記）の符号が正になっている",[77,367,368,371],{},[362,369,370],{},"空白セルの誤入力",": 元画像では空白なのにHTMLに0が入っている",[77,373,374,377],{},[362,375,376],{},"桁ずれ",": 千円単位と百万円単位の混同",[14,379,380],{},"今回は全Q通して照合エラーゼロだったが、照合工程を省略すると後工程で「数値が合わない」デバッグに時間を取られるので、この手間は省けない。",[18,382],{},[10,384,385],{"id":385},"振り返り",[14,387,388],{},"1日で撮影39枚 → クロップ39枚 → HTMLテーブル37Q分 → 全Q照合を完走した。ボトルネックはクロップ座標の試行錯誤で、注記の有無を事前に分類しておけばもう少し早く回せたはず。次回同様の作業があれば、「注記行数の事前カウント → 座標テンプレート3パターン用意 → 一括クロップ」の段取りで効率化できる。",[14,390,391],{},"HTMLテーブル化によって、精算表の数値がテキストデータとして検索・比較可能になった。この構造化データがあれば、今後のExcel自動生成パイプラインとの突合チェックもプログラムで回せる。",[393,394,395],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}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 .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 .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}",{"title":98,"searchDepth":112,"depth":112,"links":397},[398,399,403,408,413,414],{"id":12,"depth":112,"text":12},{"id":22,"depth":112,"text":23,"children":400},[401,402],{"id":27,"depth":236,"text":28},{"id":39,"depth":236,"text":39},{"id":50,"depth":112,"text":51,"children":404},[405,406,407],{"id":54,"depth":236,"text":54},{"id":64,"depth":236,"text":65},{"id":132,"depth":236,"text":132},{"id":143,"depth":112,"text":144,"children":409},[410,411,412],{"id":147,"depth":236,"text":148},{"id":158,"depth":236,"text":159},{"id":172,"depth":236,"text":173},{"id":348,"depth":112,"text":349},{"id":385,"depth":112,"text":385},"dev","教科書PDF全37論点の精算表をChrome DevToolsで撮影し、ImageMagickでクロップ、HTMLテーブルに構造化データ変換して照合レビューまで完了した1日の作業ログ","md",{},true,"/cfws-screenshot-structuring","eurekapu-nuxt4",false,"2026-04-15T00:00:00.000Z",{"title":5,"description":416},"2026-04/2026-04-15/cfws-screenshot-structuring",[427,428,429,430,431,432],"cashflow","screenshot","imagemagick","html","automation","data-extraction","memo",null,"RsfbKEZwrCjnpYVzgNIU7zXfocczj-yvBsQ3S3jL5ik",[],"https://log.eurekapu.com/favicon.svg",1776326292493]