Claude CodeでExcel VBAマクロの書き方 — CLAUDE.mdで規約化して検証する
Claude CodeにExcel VBAを書かせる手順。モジュールをテキストで書き出し、CLAUDE.mdにObject Modelの規約を置き、F8のステップ実行で検証する反復をまとめます。
Claude CodeでExcel VBAマクロを書かせるときの壁は、コードの質より「Excelの外にいる」ことです。Claude CodeはExcelを起動できず、マクロが動いたかどうかを自分では見られません。そこで、コードをテキストで受け渡す形にし、書き方の規約をCLAUDE.mdに固定し、動作確認だけを人が受け持つ分業にします。この記事では、その3点を実際の設定とプロンプトで示します。
手順の全体像 — 書くのはClaude、動かすのは人
流れは次の4ステップです。
- VBEでモジュールを .basなどのテキストファイルに書き出す(またはClaude Codeに新規作成させる)
- Claude CodeにVBAコードを書かせる
- VBEにインポートし、F8でステップ実行する
- エラーメッセージとImmediateウィンドウの出力をClaude Codeに貼って直させる
.xlsmはバイナリを含むブック形式なので、Claude Codeの編集対象はブック本体でなくモジュールのテキストにします。Claude Codeが扱うのは、Excelの外に置いた .bas / .clsのテキストだけ、という線引きです。
vba-project/
├── CLAUDE.md
├── .claude/
│ └── rules/
│ └── vba.md
├── src/
│ ├── modMain.bas
│ ├── modUtil.bas
│ └── clsLogger.cls
└── testdata/
└── sample.xlsx文字コードは環境で変わり得ます。書き出したファイルを編集して戻したあと日本語のコメントや文字列が化けた場合は、VBEが読み書きする文字コードとClaude Codeが保存した文字コードの食い違いを疑い、ファイル単位で確認します。
CLAUDE.mdにObject Modelの規約を書く
Claude CodeはCLAUDE.mdをセッション開始時にコンテキストへ読み込みます。公式ドキュメントは、1ファイル200行未満を目安に、検証できる具体さで書くよう案内しています。「きれいに書く」ではなく「Option Explicitを必ず付ける」のように、守れたかどうかが機械的に判断できる粒度にします。
VBAで規約にすべきなのは、Excel Object Modelの階層(Application、Workbook、Worksheet、Range)をどう指すかです。暗黙のアクティブシートに頼るコードが、動いたり動かなかったりの最大の原因になります。
# VBAマクロ規約
## 構成
- モジュールは src/ 配下の .bas / .cls。ブック(.xlsm)は編集しない
- 新しいプロシージャは modMain.bas か modUtil.bas に足す
## 書き方
- すべてのモジュールの先頭に Option Explicit を置く
- 変数は Dim で型を宣言する。Variant は配列の一括読み込みのときだけ
- Select / Activate / ActiveSheet / ActiveCell を使わない
- シートは Worksheet 型の変数に代入し、Range は必ず親シートから辿る
例: ws.Range("A1")。Range("A1") と単独で書かない
- 最終行は ws.Cells(ws.Rows.Count, "A").End(xlUp).Row で取る
- ScreenUpdating / Calculation / EnableEvents を変えたら、
エラー時も含めて必ず元に戻す(エラーハンドラで復元)
## 検証
- 変更したプロシージャごとに、testdata/ のサンプルで動かす手順を書く
- 途中経過は Debug.Print で出し、F8 でステップ実行できる粒度に分けるルールごとの根拠はMicrosoft LearnのVBAリファレンスにあります。
| 規約 | 根拠(VBAリファレンス) |
|---|---|
| Option Explicit | 根拠(VBAリファレンス)使うと未宣言の変数がコンパイル時エラーになる。使わないと未宣言の変数はすべてVariantになる |
| End(xlUp)で最終行 | 根拠(VBAリファレンス)Range.EndはEnd+↑ などのキー操作に相当するセルを返す。例はRange("B4").End(xlUp) |
| ScreenUpdatingを戻す | 根拠(VBAリファレンス)「マクロ終了時にTrueへ戻すこと」と注記がある |
| EnableEventsの一時停止 | 根拠(VBAリファレンス)保存時にBeforeSaveを発火させない例が載っている |
マクロ専用のルールだけをpath-scoped rulesに分ける
CLAUDE.mdに他の作業の指示が混ざっているなら、VBAの規約は .claude/rules/vba.md に切り出し、paths で対象を絞れます。該当ファイルを扱うときだけコンテキストに載る仕組みです。
---
paths:
- "src/**/*.bas"
- "src/**/*.cls"
---
# VBA規約
- Option Explicit を先頭に置く
- Select / Activate を使わない
- ScreenUpdating・Calculation・EnableEvents は変更後に必ず復元する公式は、CLAUDE.mdが長くなるとルールが埋もれ、従わなくなると説明しています。VBAだけのリポジトリならCLAUDE.mdに直接書けば足ります。
最初のプロンプト — 規約と検証方法を一緒に渡す
規約があっても、依頼が曖昧だとコードは曖昧になります。依頼には「何を入れて何を出すか」と「どう確かめるか」を入れます。
src/modMain.bas に、Sheet1 の A 列(品目)と B 列(金額)を読み、
品目ごとの合計を Sheet2 の A2 から書き出す Sub SummarizeByItem を作って。
- 見出しは 1 行目。データは 2 行目から最終行まで
- 空行は無視する
- 処理の前後で Debug.Print に対象行数と出力行数を出す
- 検証は testdata/sample.xlsx に貼って F8 で確認する。手順も末尾に書いてClaude Codeのベストプラクティスも、検証条件を与えることが自走できるかどうかを分けると説明しています。テストや出力の比較のように、結果をClaudeが読める信号を用意する考え方です。VBAではExcelを動かせないため、その信号を「人が貼るエラー文とImmediateウィンドウの出力」に置き換えます。
ステップ実行で検証し、結果をClaude Codeに返す
インポートしたら、VBEでプロシージャの先頭にカーソルを置いてF8を押し、1行ずつ進めます。確認する点は3つです。
- 変数の値(ローカルウィンドウまたはマウスオーバー)がデータどおりか
- ImmediateウィンドウのDebug.Printが想定の行数を出しているか
- 実行後のシートが、手で作った期待値と一致するか
失敗したら、次のように状況を貼ります。
SummarizeByItem を F8 で進めたら、
「実行時エラー '9': インデックスが有効範囲にありません」が
For Each 行の次の行で出た。
Immediate の出力: 対象行数=12
ws は Sheet2 を指している。直して、原因も1行で。エラー番号、停止した行、その時点の変数の値を添えるのがコツです。「動かない」だけでは、Claude Codeは推測でコードを書き換えるしかありません。
直し方の型 — 落とし穴をあらかじめ塞ぐ
Claudeが書いたVBAで実際につまずきやすい箇所を、CLAUDE.mdの規約と照らして確認します。
| つまずき | 症状 | 規約での塞ぎ方 |
|---|---|---|
| アクティブシート依存 | 症状別のシートを開いていると結果が変わる | 規約での塞ぎ方ws変数で親シートを明示 |
| 最終行の取り違え | 症状最後の行が抜ける、空行まで回る | 規約での塞ぎ方End(xlUp)を規約化し、空行の扱いをプロンプトで指定 |
| 画面更新の戻し忘れ | 症状エラー後に画面が固まったように見える | 規約での塞ぎ方エラーハンドラでScreenUpdatingを復元 |
| イベントの連鎖 | 症状Worksheet_Changeが再帰的に走る | 規約での塞ぎ方EnableEventsを一時的にFalseにして復元 |
| 計算モードの放置 | 症状数式が更新されない | 規約での塞ぎ方Calculationを元の値に戻す |
ScreenUpdatingとEnableEventsは、Microsoft Learnの例がそのまま書き方の型になります。
Sub SafeRun()
Dim prevCalc As XlCalculation
prevCalc = Application.Calculation
On Error GoTo Cleanup
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
' 本処理
Cleanup:
If Err.Number <> 0 Then Debug.Print Err.Number, Err.Description
Application.Calculation = prevCalc
Application.EnableEvents = True
Application.ScreenUpdating = True
End SubCleanupでErr.NumberとErr.DescriptionをImmediateウィンドウに出しているのがポイントです。これを省くと、エラーが起きても何も表示されずに終わり、次節でClaude Codeに貼るエラー番号が手元に残りません。このパターンをCLAUDE.mdに「処理の入口と出口はこの雛形に従う」と書いておけば、Claudeが新しいSubを足すたびに同じ形で出してきます。
hooksでOption Explicitの書き忘れを止める
規約をCLAUDE.mdに書いても、守られる保証はありません。公式はCLAUDE.mdを強制ではなくコンテキストと位置づけています。確実に守らせたい規則は、hooksに落とします。
PostToolUse に Edit|Write のマッチャーを付けると、Claudeがファイルを編集した直後にコマンドが走ります。公式の例では、編集したファイルのパスをjqで取り出して整形コマンドに渡しています。同じ形で、.bas / .clsの先頭付近にOption Explicitがあるか調べる例です(あくまで一例です)。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/check-vba.sh"
}
]
}
]
}
}#!/bin/bash
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
case "$FILE" in
*.bas|*.cls)
if ! head -n 5 "$FILE" | grep -q "Option Explicit"; then
echo "Option Explicit がありません: $FILE" >&2
exit 2
fi
;;
esac
exit 0exit 2の扱いは、イベントごとに異なります(フィードバックとして返るもの、ユーザーへの表示にとどまるものがある)。使う前にイベント別の挙動を確認してください。hooksの全体像はClaude Code Hooks完全ガイド、Lintの自動修正への応用はPostToolUse hookのLint自動修正にまとめています。
ブックに戻すときの注意 — 形式とマクロセキュリティ
最後にモジュールを .xlsmへインポートして保存します。VBAを含むブックは、Microsoft LearnのXlFileFormat列挙でxlOpenXMLWorkbookMacroEnabled(値52)が対応する形式です。VBAでSaveAsするときはFileFormat引数に指定します。指定しないと、既存ファイルでは最後に使った形式が既定になります。
ThisWorkbook.SaveAs Filename:="C:\work\report.xlsm", _
FileFormat:=xlOpenXMLWorkbookMacroEnabled開く側の設定にも注意が要ります。Microsoft 365のTrust Centerには「通知してVBAマクロを無効にする」「デジタル署名されたマクロを除いて無効にする」などの選択肢があり、既定のままでは配布したブックのマクロが止まることがあります。会社支給のPCでは、管理者が設定変更を禁じている場合もあります。信頼できる場所(Trusted location)にブックを置く方法も公式に案内されています。メールやダウンロードで届いたブックは、インターネット由来のファイルとしてマクロがブロックされる場合があります。同じページには「Macros from the internet are blocked by default in Office」という別ページへの案内があるので、ブロックの解除方法はそちらで確認してください。配布先で「動かない」と言われたら、コードの前に、この設定とファイルの由来を確認します。
既存マクロのリファクタリングを頼む — 遅いループを配列に置き換える
新規作成より効果が出やすいのは、既存マクロの直しです。セルを1つずつ読み書きするループは、行数が増えると急に遅くなります。書き出した .basを渡し、規約に沿った形へ変えてもらいます。
src/modUtil.bas の CopyPrices を読んで、次の順で進めて。
1. 何をしているマクロか、3行で説明する
2. Select / Activate と、セルを1つずつ読む箇所を洗い出す
3. 規約に沿って、Range.Value を配列に一括で読み込む形へ直す
4. 直す前後で結果が変わらないことを確かめる Debug.Print を足す
挙動を変える修正は、直す前にどこを変えるか先に見せて。直した結果は、たとえば次のような形になります(依頼内容と規約から想定した例で、Claudeの実出力ではありません)。
Option Explicit
Sub CopyPrices()
Dim wsSrc As Worksheet, wsDst As Worksheet
Dim lastRow As Long
Dim data As Variant
Set wsSrc = ThisWorkbook.Worksheets("Sheet1")
Set wsDst = ThisWorkbook.Worksheets("Sheet2")
lastRow = wsSrc.Cells(wsSrc.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then Exit Sub ' 見出しだけでデータが0行
data = wsSrc.Range("A2:B" & lastRow).Value
wsDst.Range("A2").Resize(UBound(data, 1), 2).Value = data
Debug.Print "copied rows=" & UBound(data, 1)
End Sub配列にするのは、規約で「Variantは配列の一括読み込みのときだけ」と許した使い方です。2列の範囲なら、データが1行でもValueは2次元配列で返ります。境界になるのは、見出しだけでデータが0行のときです。最終行が1行目になり、Range("A2:B1") はA1:B2として解釈されるため、見出し行までコピーしてしまいます。冒頭の If lastRow < 2 Then Exit Sub はその対策で、データ0行と1行のブックでF8を進めて確認します。ここが、Claudeが書いたコードで人が最初に見るべき境界条件です。
差分の確認は、Claude Codeを使う利点がいちばん出る場面です。テキストファイルなので、Gitでコミットしておけば、直す前と後をdiffで比べ、うまくいかなければ戻せます。ブック本体をバイナリのまま扱っていては、この履歴管理はできません。
依頼は1プロシージャずつに区切る
公式のベストプラクティスは、対象のファイルと場面を絞って依頼するよう勧めています。VBAでも同じで、「請求書処理のマクロを一式作って」と頼むと、どこで失敗したのかが切り分けられません。次の単位で区切ると、F8での確認が1回で済みます。
- 読み込み(シートから配列へ)
- 加工(集計・変換)
- 書き出し(結果を別シートへ)
- 後始末(画面更新・イベント・計算モードの復元)
1つ動いたら、次のプロシージャを頼みます。前のプロシージャの名前と引数を示しておくと、Claudeが呼び出しの型を揃えてくれます。
Claude Codeに向く作業と向かない作業
| 作業 | 向き不向き | 理由 |
|---|---|---|
| 既存のSubのリファクタリング | 向き不向き向く | 理由テキストだけで完結し、Option Explicitなどの規約を守らせやすい |
| 配列を使った高速化 | 向き不向き向く | 理由変更範囲が閉じていて、Debug.Printの件数で確認できる |
| 新規マクロの下書き | 向き不向き条件次第 | 理由入出力の列・見出し・空行の扱いを依頼に書けば精度が上がる |
| 書式やグラフの見た目調整 | 向き不向き不向き | 理由結果を人が目で見るしかなく、往復が増える |
| ブックの中の既存マクロの解析 | 向き不向き条件次第 | 理由いったんモジュールをテキストに書き出せば読める |
チャットにブックを渡して数式や集計を任せる使い方は、Claude Code側の記事ではなくClaude Excel関数の書き方やClaude Excel読み込みと作成の領分です。マクロを残したい、繰り返し動かしたいという要件が出た時点で、この記事の分業(コードはテキスト、動作確認は人)が効いてきます。
まとめ
Claude CodeでVBAを書く手順は、モジュールをテキストで受け渡し、規約をCLAUDE.mdに置き、動作確認を人が担う形に落ち着きます。規約の中心はOption Explicit、Select / Activateの禁止、親シートから辿るRange、最終行の取り方、画面更新・イベント・計算モードの復元の5点です。守らせたい規則はhooksに移し、エラーは番号・行・変数の値を添えて返します。規約を育てる流れはClaude CodeのCLAUDE.mdを実用に引き上げる10のパターンと同じです。