Claude Media
Claude CodeでVBAマクロを解読する — oletoolsでテキスト化して棚卸し

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. 1

    olevbaを入れる

    oletoolsをpipで入れます。

  2. 2

    VBAをテキストに書き出す

    olevbaでモジュールのソースだけを取り出し、作業用フォルダに保存します。

  3. 3

    権限を読み取り専用に絞る

    元のブックを触らせず、olevbaだけを許可します。

  4. 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に元のブックを開かせてはいけませんか?

禁止ではありません。ただ、バイナリのままでは読み取りに向かず、コンテキストを無駄に使います。テキストに書き出す分担のほうが、読ませる範囲を人が制御できます。

書き出したコードに、機密が入っていることはありますか?

あります。接続文字列やパスワードがコードに直書きされている例があるため、棚卸しの観点に含めておきます。共有するときは、書き出したテキストの該当行を伏せてから渡します。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/permissions
  2. github.com/decalage2/oletools
  3. github.com/decalage2/oletools/blob/master/oletools/doc/olevba.md
この記事を共有:XはてブLinkedIn