[{"data":1,"prerenderedAt":397},["ShallowReactive",2],{"content-/excel-cross-sheet-reference-diagram":3,"all-pages-for-dir":395,"og-image-/excel-cross-sheet-reference-diagram":396},{"id":4,"title":5,"body":6,"category":376,"description":377,"extension":378,"meta":379,"navigation":336,"path":380,"project_name":381,"published":382,"publishedAt":383,"seo":384,"stem":385,"tags":386,"todo":393,"updatedAt":393,"__hash__":394},"pages/2026-04/2026-04-27/excel-cross-sheet-reference-diagram.md","Excelのシート間参照をPNG図解する：pywin32 COM CopyPicture + Pillow矢印合成スクリプトの試作",{"type":7,"value":8,"toc":369},"minimark",[9,14,18,22,35,38,54,61,64,70,115,122,197,200,204,207,282,289,293,296,319,322,325,365],[10,11,13],"h1",{"id":12},"excelのシート間参照をpng図解するpywin32-com-pillowで矢印を合成する","Excelのシート間参照をPNG図解する：pywin32 COM + Pillowで矢印を合成する",[15,16,17],"p",{},"Excelコンテンツを書くとき、Sheet1のマスタ表からSheet2へINDEX/MATCHで参照していることを図で示す機会が多い。今までは Excelのウィンドウを Snipping Tool でキャプチャして、Illustrator を立ち上げて矢印を1本1本引いていた。1図あたり20分ほど消えていく。今日はこれをスクリプト化する方針を決めて、最初のプロトタイプまで動かした。",[19,20,21],"h2",{"id":21},"既存スキルとのすみ分け",[15,23,24,25,29,30,34],{},"リポジトリには既に ",[26,27,28],"code",{},"excel-screenshot"," スキルがあり、こちらは ",[31,32,33],"strong",{},"HTMLレンダリング方式","でExcel風のテーブルを描画する。文字組みもセル罫線もきれいに揃うが、本物のExcelとは見た目がわずかに違う。読者に「これは現物のExcelだ」と伝えたいときには使いにくい。",[15,36,37],{},"そこで今回は方針を分けた。",[39,40,41,48],"ul",{},[42,43,44,47],"li",{},[31,45,46],{},"HTML方式（既存）",": 文字情報が主で、見た目より構造を伝えたいとき",[42,49,50,53],{},[31,51,52],{},"現物Excel方式（新規）",": シート間の参照リンクを「実際のExcelで動いている図」として見せたいとき",[15,55,56,57,60],{},"「現物Excelらしさ」を残す方を優先したかったので、pywin32 COM で本物のExcelを開いて ",[26,58,59],{},"CopyPicture"," で範囲を画像化することにした。",[19,62,63],{"id":63},"試作したスクリプトの流れ",[15,65,66,69],{},[26,67,68],{},"scripts/excel-ref-diagram/"," に以下の3要素を置いた。",[71,72,73,91,105],"ol",{},[42,74,75,78,79,82,83,86,87,90],{},[31,76,77],{},"サンプルExcel生成",": openpyxl で ",[26,80,81],{},"Sheet1"," にマスタ表（社員ID・氏名・部署・給与）、",[26,84,85],{},"Sheet2"," に ",[26,88,89],{},"=INDEX(Sheet1!C:C, MATCH(A2, Sheet1!A:A, 0))"," の参照式を入れた検証用ファイルを作る",[42,92,93,96,97,100,101,104],{},[31,94,95],{},"範囲キャプチャ",": pywin32 で Excel.Application を起動し、",[26,98,99],{},"Range(\"B5:E10\").CopyPicture(Appearance:=1, Format:=2)"," でクリップボードにビットマップを置き、PIL の ",[26,102,103],{},"ImageGrab.grabclipboard()"," で取り出す",[42,106,107,110,111,114],{},[31,108,109],{},"矢印合成",": Pillow で2枚のキャプチャ画像を左右に並べ、",[26,112,113],{},"ImageDraw"," で参照元セルから参照先セルへ曲線矢印を引く",[15,116,117,118,121],{},"最終的に ",[26,119,120],{},"scripts/excel-ref-diagram/output.png"," が生成される。指定はYAML/JSONで以下のように from/to を並べる想定にした。",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-yaml shiki shiki-themes vitesse-light vitesse-light","arrows:\n  - from: \"Sheet1!C5:C5\"\n    to: \"Sheet2!B2:B2\"\n    label: \"INDEX/MATCH\"\n","yaml","",[26,130,131,144,167,182],{"__ignoreMap":128},[132,133,136,140],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"sz8Xr","arrows",[132,141,143],{"class":142},"shFtX",":\n",[132,145,147,150,153,156,160,164],{"class":134,"line":146},2,[132,148,149],{"class":142},"  -",[132,151,152],{"class":138}," from",[132,154,155],{"class":142},":",[132,157,159],{"class":158},"sMJiu"," \"",[132,161,163],{"class":162},"sdGka","Sheet1!C5:C5",[132,165,166],{"class":158},"\"\n",[132,168,170,173,175,177,180],{"class":134,"line":169},3,[132,171,172],{"class":138},"    to",[132,174,155],{"class":142},[132,176,159],{"class":158},[132,178,179],{"class":162},"Sheet2!B2:B2",[132,181,166],{"class":158},[132,183,185,188,190,192,195],{"class":134,"line":184},4,[132,186,187],{"class":138},"    label",[132,189,155],{"class":142},[132,191,159],{"class":158},[132,193,194],{"class":162},"INDEX/MATCH",[132,196,166],{"class":158},[15,198,199],{},"複数の参照線がある場合も、配列に追記すれば一気に描ける構造にしてある。",[19,201,203],{"id":202},"excelスクショ手段の選択肢比較","Excelスクショ手段の選択肢比較",[15,205,206],{},"途中でユーザーから「そもそもExcelスクショをきれいに撮る方法はないか」と聞かれて、4つの選択肢を整理した。",[208,209,210,229],"table",{},[211,212,213],"thead",{},[214,215,216,220,223,226],"tr",{},[217,218,219],"th",{},"方法",[217,221,222],{},"クリーンさ",[217,224,225],{},"手軽さ",[217,227,228],{},"自動化",[230,231,232,247,258,269],"tbody",{},[214,233,234,238,241,244],{},[235,236,237],"td",{},"現物Excel + COM CopyPicture（今回）",[235,239,240],{},"高",[235,242,243],{},"中",[235,245,246],{},"可能",[214,248,249,252,254,256],{},[235,250,251],{},"HTMLレンダリング（既存スキル）",[235,253,243],{},[235,255,240],{},[235,257,246],{},[214,259,260,263,265,267],{},[235,261,262],{},"LibreOffice CLI でPDF出力→画像化",[235,264,243],{},[235,266,243],{},[235,268,246],{},[214,270,271,274,276,279],{},[235,272,273],{},"Snipping Tool 等の手動",[235,275,240],{},[235,277,278],{},"低",[235,280,281],{},"不可",[15,283,284,285,288],{},"「現物の見た目」と「自動化」を両立できるのが COM 方式しかなく、結果として今回の方針に落ち着いた。ただし pywin32 COM は Windows 限定で、ヘッドレスでは動かない（Excel.exe を実際に起動する必要がある）という制約は残る。CI で回すのは現実的ではないので、",[31,286,287],{},"ローカルで記事を書くときに走らせる手元スクリプト","という位置づけになる。",[19,290,292],{"id":291},"朝の別セッションで話したsvgの話","朝の別セッションで話したSVGの話",[15,294,295],{},"同じ日の朝、SVGをPowerPoint/Illustratorに貼り付けられるかを別セッションで聞かれていた。これも今回の図解方針と地続きの話で、整理だけ残しておく。",[39,297,298,309,312],{},[42,299,300,301,304,305,308],{},"SVGは ",[31,302,303],{},"ベクター","形式（Scalable ",[31,306,307],{},"Vector"," Graphics）。PowerPoint 2016以降と Illustrator の両方で扱える",[42,310,311],{},"ピクセル/ラスター（PNG・JPG）と対比される。拡大しても破綻しない",[42,313,314,315,318],{},"「HTMLをSVGに変換する」のは罠が多い。一般的な方法では正確に変換できず、",[26,316,317],{},"html2canvas"," 経由でラスタライズしてしまうのが現実解",[15,320,321],{},"今回のExcel図はラスター（PNG）で出している。CopyPicture には EMF 出力もあるので、必要になったらベクター化も検討する余地がある。",[19,323,324],{"id":324},"次にやること",[39,326,329,339,345,359],{"className":327},[328],"contains-task-list",[42,330,333,338],{"className":331},[332],"task-list-item",[334,335],"input",{"disabled":336,"type":337},true,"checkbox"," YAML設定ファイルのスキーマを固める（複数矢印・ラベル位置・色）",[42,340,342,344],{"className":341},[332],[334,343],{"disabled":336,"type":337}," 矢印が表をまたぐときの自動レイアウト（縦並び vs 横並びの判定）",[42,346,348,350,351,354,355,358],{"className":347},[332],[334,349],{"disabled":336,"type":337}," スキル化して ",[26,352,353],{},"excel-ref-diagram"," として ",[26,356,357],{},".claude/skills/"," に登録",[42,360,362,364],{"className":361},[332],[334,363],{"disabled":336,"type":337}," サンプル出力をブログ記事に貼って実例を示す",[366,367,368],"style",{},"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 .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);}",{"title":128,"searchDepth":146,"depth":146,"links":370},[371,372,373,374,375],{"id":21,"depth":146,"text":21},{"id":63,"depth":146,"text":63},{"id":202,"depth":146,"text":203},{"id":291,"depth":146,"text":292},{"id":324,"depth":146,"text":324},"dev","Excelコンテンツ作成時、Sheet1のマスタ表からSheet2へのINDEX/MATCH参照を図示するワークフローを自動化したい。現状はExcelのスクショを撮ってIllustratorで矢印を引いており、毎回20分かかる。今回はpywin32 COMのCopyPictureで2つの範囲をキャプチャし、Pillowで矢印を合成してPNG出力するスクリプトを試作した。指定方法はYAML/JSONで `Sheet1!B5:E10 → Sheet2!C8:F12` のようにfrom/toを書く想定。既存のexcel-screenshotスキル（HTMLレンダリング版）との使い分けも整理した。","md",{},"/excel-cross-sheet-reference-diagram","excel-viewer",false,"2026-04-27T00:00:00.000Z",{"title":5,"description":377},"2026-04/2026-04-27/excel-cross-sheet-reference-diagram",[387,388,389,390,391,392,194],"Excel","Python","pywin32","Pillow","図解","COM",null,"Twx9u60CtxzKmQIWNOVXIHTmvKbITO4QV9OBaoHtHmc",[],"https://log.eurekapu.com/favicon.svg",1777329227000]