Claude CodeでVBAマクロを解読する — oletoolsでテキスト化して棚卸し
他人が作った.xlsmのVBAを、olevbaでテキストに書き出してClaude Codeに読ませる分担と、読み取り専用で回す権限設定、棚卸しの依頼文をまとめます。
前任者が残した.xlsmを引き継いだものの、VBAの中身が誰にも分からない。この状況で効くのは、Claude Codeにブックを直接開かせることではありません。oletoolsのolevbaでVBAをテキストに書き出し、そのテキストだけを読ませる分担です。この記事では、書き出しのコマンド、読み取り専用で回すための権限、棚卸しの依頼文を順に示します。新しくマクロを書く手順はClaude CodeでExcel VBAマクロを書く記事が扱っているので、ここでは既存マクロを読む側に絞ります。
解読の分担 — 取り出すのはolevba、読むのはClaude Code
olevbaは、WordやExcelなどのOLEファイルとOpenXMLファイルを解析し、VBAマクロを検出してソースコードを平文で取り出すスクリプトです。oletoolsのREADMEは、VBAマクロのほかOLEオブジェクト、Excel 4マクロ(XLM)、DDEリンクも解析できると説明しています。
分担にすると、Claude Codeの仕事は「テキストになったコードを読んで説明する」だけになります。.xlsmの中身をClaude Codeに解釈させる必要がなく、取り出しの正しさはolevbaの出力で目視確認できます。
既存マクロを読めるようにするまで
- 1
olevbaを入れる
oletoolsをpipで入れます。
- 2
VBAをテキストに書き出す
olevbaでモジュールのソースだけを取り出し、作業用フォルダに保存します。
- 3
権限を読み取り専用に絞る
元のブックを触らせず、olevbaだけを許可します。
- 4
棚卸しを依頼する
モジュール、入口、外部への接続の3点を表にさせます。
olevbaで.xlsmからVBAを書き出す
READMEの案内では、インストールはpipで行います。
pip install -U oletools[full]olevbaの使い方は olevba [options] <filename> です。ソースコードだけが欲しいときは、解析結果を出さない -c(--code)を使います。
mkdir -p extracted
olevba -c old-book/budget.xlsm > extracted/budget.vba.txt出力にはモジュールごとの見出しが付きます。olevbaのドキュメントにある出力例では、VBA MACRO ThisDocument.cls のようにモジュール名が示され、続けて in file: の行でファイル名とOLEストリームのパスが示されています。つまり1つのテキストの中に、標準モジュール、クラス、ThisWorkbookのコードが連なって入ります。
用途別のオプションは次の表のとおりです。
| やりたいこと | オプション | 補足 |
|---|---|---|
| ソースだけが欲しい | オプション-c / --code | 補足解析はしない |
| 危険そうな記述だけ確認したい | オプション-a / --analysis | 補足ソースは出さない |
| 難読化された文字列を戻したい | オプション--reveal | 補足難読化された文字列を復号した内容に置き換えて表示 |
| パスワード付きのブック | オプション-p パスワード | 補足暗号化されたOfficeファイルを復号して開く |
| フォルダ内の複数ファイル | オプションワイルドカードを引用符で囲む | 補足シェルに展開させない |
複数ファイルを渡すと、サマリー表(トリアージモード)が既定で表示されます。表のフラグは、M がVBAマクロあり、A が自動実行マクロあり、S が不審なキーワードあり、I がIOC(URLやIPアドレスなど)の可能性あり、という意味です。フォルダ一括の入口として、まずこの表で「どのブックにマクロが入っているか」を絞ってから、1本ずつ -c で書き出す使い方ができます。
読み取り専用の権限を書く
書き出したテキストは作業フォルダの中のファイルなので、Claude Codeは読むための承認を求められません。公式の権限ドキュメントでは、ファイルの読み取りやGrepは作業ディレクトリ内なら承認不要とされています。一方でBashコマンドは、組み込みの読み取り専用コマンド(ls・cat・grep など)を除いて承認が必要です。olevbaはその例には挙がっていないので、毎回の承認を避けたいなら許可規則に書きます。
{
"permissions": {
"allow": [
"Bash(olevba *)"
],
"deny": [
"Edit(./old-book/**)",
"Read(**/*.xlsm)"
]
}
}これを .claude/settings.json に置いた場合の意味は次のとおりです。
Bash(olevba *)— olevbaのどの引数でも実行を許可します。*は任意のテキストに一致しますEdit(./old-book/**)— 元のブックを置いたフォルダへの編集を拒否します。Editの拒否規則は、ファイルを編集する組み込みツール全般に効きますRead(**/*.xlsm)— .xlsmを読み取りツールで開くことを拒否します。バイナリがコンテキストに流れ込むのを防ぎます
ここで押さえておきたいのは、拒否規則が届く範囲です。公式ドキュメントによると、Read と Edit の拒否規則は組み込みのファイルツールと、cat や sed のようなClaude Codeが認識するファイルコマンド、Bashのリダイレクトの書き先に効きます。一方で、ファイルを内部で開くサブプロセスには効きません。olevbaが.xlsmを自分で開く動作は後者にあたるため、上の設定でも olevba -c old-book/budget.xlsm は通ります。「直接は読ませず、olevba経由でだけ読ませる」という分担が、そのまま規則で表現できるわけです。
逆に、拒否規則はOSレベルの強制ではないことも示しています。経路を完全に塞ぎたいときは、公式がサンドボックスを案内しています。
書き出しのリダイレクト(> extracted/budget.vba.txt)は、書き先が Edit の許可・拒否規則と作業ディレクトリに照らして確認されます。出力先は作業ディレクトリの中の extracted/ に置き、元のブックのフォルダとは分けておくと、上の拒否規則と衝突しません。
複数の規則が競合したときは、拒否が優先されます。たとえば広い拒否規則があると、より狭い許可規則があっても止まります。許可を足してもつながらないときは、先に拒否側を見直します。
棚卸しを依頼する
テキストができたら、最初の依頼で「説明して」とだけ頼まないのがコツです。長いVBAを順に説明させると、どこが重要か分からない解説が続きます。棚卸しの観点を先に固定して、表で返させます。
extracted/budget.vba.txt を読んで、棚卸し表を extracted/inventory.md に作って。
1. モジュール一覧: 名前・種類(標準/クラス/ThisWorkbook)・役割を1行で
2. 入口: Auto_Open / Workbook_Open / Worksheet_Change と、ボタンから呼ばれる Sub
3. 外部への接続: Shell・CreateObject・Declare ... Lib・ファイルパス・URL・
接続文字列。見つけた行は該当コードを引用して
4. ハードコード: シート名・セル番地・固定パス
5. 読み切れなかった箇所は「不明」と書いて、推測で埋めない
コードは修正しないで。観点は次の目的に対応しています。
- 入口と外部接続 — マクロを有効にしたときに自動で動くものと、ブックの外へ出ていくものを先に洗い出します。引き継ぎでも、セキュリティ確認でも最初に必要になる情報です
- ハードコード — シート名や固定パスが埋まっていると、引っ越しや改名で壊れます。後からリファクタリングするときの地図になります
- 不明の明示 — 説明が自信ありげでも、実行して確かめていない部分は推測です。「不明」と書かせると、人が確認すべき箇所が残ります
次は、気になったプロシージャを個別に掘ります。
extracted/budget.vba.txt の modReport.MakeMonthly を、
行ごとではなく処理のまとまりごとに説明して。
読み書きしているシート・範囲・変数を最後に一覧にして。コメントが日本語で書かれたマクロでは、コード上の識別子が x1 や tmp2 のように意味を持たないことがあります。この場合は「識別子の意味はコードの使われ方から推定した」と書かせ、推定と事実を分けます。
olevbaの出力で足りないとき
-a(--analysis)の解析結果は、読む前のふるい分けに使えます。ドキュメントの出力例では、Auto_Open や Workbook_Open がAutoExec(開くと自動で動く)、Shell や Environ や URLDownloadToFileA がSuspicious(不審なキーワード)、URLや実行ファイル名がIOCとして表に並びます。「ブックを開くと動くものがあるか」「外部へ出ていく記述があるか」は、この表だけでおおむね把握できます。
ただし、表に出るのはキーワードの有無です。業務マクロの Shell が、ただの explorer 起動だったということも起きます。検出された行はClaude Codeに文脈ごと読ませ、何を実行しているのかを説明させます。
読めないものも出てきます。複数ファイルを渡したサマリー表で、フラグ欄に ? が出たものは、olevbaが対応していない形式です。暗号化されたブックは、パスワードを知っていれば -p で渡せます。パスワードが分からない場合の扱いは、olevbaのドキュメントに記載がありません。
書き出しを繰り返せる形にしておく
引き継いだマクロは、解読している最中にも更新されます。前任者が差し替えた新しいブックが届くたびに、読み直すのは非効率です。書き出しのコマンドを固定し、書き出し先をGitで管理しておくと、更新のたびに差分だけを見られます。
olevba -c old-book/budget.xlsm > extracted/budget.vba.txt
git diff --stat extracted/差分が出た行だけをClaude Codeに渡し、「前回の棚卸し表のどの行が変わるか」を聞きます。棚卸し表の inventory.md も同じリポジトリに置いておけば、表のどの行を更新すべきかをそのまま依頼できます。
この運用で守りたいのは、元のブックを動かさないことです。上の Edit の拒否規則は、この目的のためのものです。Claude Codeが読むのは extracted/ のテキストだけで、ブック側への書き戻しは行いません。VBAを直す場合は、直したモジュールを人がVBEでインポートし直します。
説明のどこまでが事実か
Claude Codeの説明は、コードを読んだ結果です。マクロを実行した結果ではありません。この手順ではマクロを実行せず、書き出したテキストだけを読ませるため、Range が実際に何を指し、シートにどんな値が入るかは、テキストからは分かりません。
| 説明の種類 | 確かさ | 確かめ方 |
|---|---|---|
| 呼び出し関係(AがBを呼ぶ) | 確かさ高い | 確かめ方コード上の記述から直接追える |
| 外部接続の有無 | 確かさ高い | 確かめ方引用された行を目視で確認 |
| 処理の意図(月次集計をしている等) | 確かさ中程度 | 確かめ方コメントや名前からの推定 |
| 実際の動作結果 | 確かさ確認不能 | 確かめ方VBEのF8で人が実行する |
この区分を依頼文に入れておくと、返答に「推定」「不明」が正しく付きます。動作の確認が要る箇所は、棚卸し表の末尾に「人が確認する項目」として並べさせます。
解読してから、どうするか
棚卸しが済んだら、次の判断は3つに分かれます。
| 状況 | 次にやること |
|---|---|
| 引き継いで使い続ける | 次にやること動作確認は人がVBEのF8で行い、規約化・改修はVBAマクロを書く記事の手順に移る |
| 外部接続や自動実行が見つかった | 次にやることその行だけを人が読み、出どころと目的を確認してから有効化を判断する |
| 使わない | 次にやること棚卸し表を残して、Excelの機能や別ツールに置き換える設計に使う |
台帳を作って整理する発想は、他のツールのマクロにも応用できます。たとえば問い合わせ対応のマクロ(定型文)を使用回数と重複から整理する進め方は、Zendeskマクロの棚卸しにまとめています。
よくある質問
拡張子から、マクロの有無は分かりますか?
拡張子だけに頼らず、olevbaに渡して M フラグの有無で確かめます。複数ファイルを渡すと、フラグ付きのサマリー表が出ます。
Claude Codeに元のブックを開かせてはいけませんか?
禁止ではありません。ただ、バイナリのままでは読み取りに向かず、コンテキストを無駄に使います。テキストに書き出す分担のほうが、読ませる範囲を人が制御できます。
書き出したコードに、機密が入っていることはありますか?
あります。接続文字列やパスワードがコードに直書きされている例があるため、棚卸しの観点に含めておきます。共有するときは、書き出したテキストの該当行を伏せてから渡します。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。