Range・Cells・Worksheets・Workbooksと種類が多くて迷う方へ。丸暗記ではなく、「ブック → シート → セル」の階層という1本の軸で整理します。
この記事で分かること
- VBAのセル指定が「ブック → シート → セル」の3階層でできていること
- 階層を省略すると、意図しないシートを書き換える事故が起きる理由
RangeとCells、シートの名前指定と番号(インデックス)指定の使い分けWithで階層をまとめる書き方
どんな場面で使うか
- 複数のシートやブックをまたいで処理するマクロを書く
- マクロの記録で作ったコードを、書き直したい
- 「実行するたびに結果が違う」「別のシートに書き込まれた」を防ぎたい
基本説明
使うデータ
サンプルファイル(記事末尾)には、「東京」「大阪」「名古屋」の3シートがあります。

「東京」シートの元データ(A1:B6。A列=商品名、B列=売上、2〜6行目に5件)
どのシートも、A列が商品名、B列が売上です。データは2〜6行目の5件で、大阪・名古屋は値だけが違います。最後に、この3シートの売上を合計するマクロを作ります。
セルの指定は3階層でできている
「東京シートのB2」と言うとき、私たちはブック → シート → セルの順に絞り込んでいます。VBAも同じ順に書きます。
ThisWorkbook.Worksheets("東京").Range("B2").Value
.(ドット)は「の」と読むと分かりやすくなります。
| 位置 | 意味 | 上の例 |
|---|---|---|
| 1つめ | どのブックの | ThisWorkbook |
| 2つめ | どのシートの | Worksheets("東京") |
| 3つめ | どのセルの | Range("B2") |
| 4つめ | 何を | .Value |
Range・Cells・Worksheetsは別々の機能ではなく、この階層のどこを指すかの違いです。
省略すると「今アクティブなもの」が使われる
上の階層は省略できます。ただし標準モジュールでは、Excelが今アクティブなブックの、今アクティブなシートを補います。
Range("B2").Value = 100
' ↑ 実際は ActiveWorkbook.ActiveSheet.Range("B2") として実行される
別のブックを開いた状態で実行すると、そちらのB2を書き換えます。 エラーは出ません。「昨日は動いたのに」の多くはこれが原因です。
迷ったら、階層を省略せずに書きます。
マクロ記録が Select・Activate だらけになる理由
記録機能は、人のクリック操作をそのまま文字にします。そのため Range("B2").Select のように、「シートやセルを選んでから操作する」コードになります。
VBAでは、Worksheets("東京").Range("B2").Value のように階層で書けば、シートを切り替えずに読み書きできます。Select・Activate の比較は【Excel VBA】Select、Activate、他セル指定方法の比較で扱っています。
階層① ブック — ThisWorkbook を基本にする
ThisWorkbook… このマクロが書かれているブック。アクティブなブックが変わっても、指す先は変わらないActiveWorkbook… 今アクティブなブック。別のブックを開くと変わるWorkbooks("集計元.xlsx")… 開いている別のブックを、ファイル名(拡張子込み)で指定する
マクロが入っているブック自身に書くときは、ThisWorkbook を使います。
階層② シート — 名前で指定する
- 名前指定 …
Worksheets("東京") - 番号(インデックス)指定 …
Worksheets(1)(何番目のシートか)
番号指定は、左側にシートを足したり、並びを動かしたりすると、別のシートを指すことがあります。 しかもエラーにならず、黙って別のシートを処理します。
名前指定は、シート名を変えられると実行時エラーで止まります。止まるので気づけます。特別な理由がなければ、名前指定を使います。
階層③ セル — Range と Cells
| 書き方 | 向いている場面 | |
|---|---|---|
Range |
Range("B2")・Range("B2:B6") のように、Excelの表記のまま |
決まったセル・範囲を指定する |
Cells |
Cells(2, 2) のように、行番号・列番号の数値 |
ループで行や列を動かす |
Worksheets("東京").Range("B2").Value ' B2 をそのまま指定
Worksheets("東京").Cells(2, 2).Value ' 2行目・2列目 = 同じB2
どちらもB2です。Cells は行番号が数値なので、Cells(i, 2) のように変数を入れられます。
With で階層をまとめる
同じシートを何度も書くときは、With でまとめます。
With ThisWorkbook.Worksheets("東京")
MsgBox .Range("B2").Value & " / " & .Cells(3, 2).Value
End With
. で始まる部分は、With で指定したシートの続きとして読まれます。この例は、東京シートのB2とB3を読んで 100 / 200 と表示します。
With の内側で . を付け忘れると、省略した書き方に戻ります。
手順
VBEにコードを書く
Alt+F11でVBE(Visual Basic Editor)を開く- 「挿入」→「標準モジュール」を選ぶ
- モジュールの1行目に
Option Explicitが最初から入っていたら、消しておく(下のステップ1のコードの先頭にも入っていて、1行目の1つだけで足りるため) - 下の「サンプルコード」のステップ1〜3を、順に貼り付ける
- 左側のプロジェクトエクスプローラーで、東京・大阪・名古屋の3シートが並んでいることを確かめる

VBEのプロジェクトエクスプローラーとコード画面
Worksheets("東京") と名前で書いたシートが、このツリーに並ぶ実物です。
実行して確認する
- 実行したい
Subの中をクリックする F5を押す- メッセージボックスで結果を確かめる
サンプルコード
3段階に分けて積み上げます。3つとも同じ標準モジュールに貼ります。Option Explicit は1行目の1つだけです。
ステップ1:1つのセルを階層つきで読む
Option Explicit
Sub 東京のB2を読む()
MsgBox ThisWorkbook.Worksheets("東京").Range("B2").Value
End Sub
100 と表示されます。大阪シートをアクティブにして実行しても、結果は変わりません。 階層を書いているためです。
ステップ2:1シートの売上を合計する
Sub 東京の売上を合計する()
Dim r As Long
Dim total As Double
With ThisWorkbook.Worksheets("東京")
For r = 2 To 6
total = total + .Cells(r, 2).Value
Next r
End With
MsgBox "東京 : " & total
End Sub
「東京 : 1000」と表示されます。Cells(r, 2) なら、r が2→6と変わるだけで下の行へ進めます。
ステップ3:3シートを横断して合計する
Sub 支店別売上を合計する()
Dim shopNames As Variant
shopNames = Array("東京", "大阪", "名古屋")
Dim shopName As Variant
Dim r As Long
Dim lastRow As Long
Dim shopTotal As Double
Dim grandTotal As Double
Dim msg As String
For Each shopName In shopNames
shopTotal = 0
With ThisWorkbook.Worksheets(shopName)
' B列の最終行を取得する(データが増減しても追従する)
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
For r = 2 To lastRow
shopTotal = shopTotal + .Cells(r, 2).Value
Next r
End With
msg = msg & shopName & " : " & shopTotal & vbCrLf
grandTotal = grandTotal + shopTotal
Next shopName
MsgBox msg & vbCrLf & "合計 : " & grandTotal, vbInformation, "支店別売上"
End Sub
ステップ2から変わったのは2か所です。
- シート名を変数で渡す …
Worksheets(shopName)。対象を増やすときは、Arrayに店舗名を足すだけ - 最終行を自動で求める …
.Cells(.Rows.Count, "B").End(xlUp).Rowは、B列の一番下からCtrl+↑を押す操作と同じ。行数が増えても追いつく
動作確認
サンプルファイル(記事末尾)を開き、ステップ1〜3の Sub を貼った状態で確かめます。途中の短いコードは説明用なので、実行しなくて構いません。
Alt+F11でExcelの画面に戻り、「東京」シートのタブをクリックするAlt+F11でVBEに戻り、東京のB2を読むの中をクリックしてF5→100と表示されれば成功- 同じようにExcelの画面で「大阪」シートのタブをクリックしてから、
東京のB2を読むをもう一度F5で実行する →100のままなら成功(アクティブなシートに左右されない) 支店別売上を合計するの中をクリックしてF5→ 「東京 : 1000」「大阪 : 500」「名古屋 : 350」「合計 : 1850」と表示されれば成功
よくあるエラー
実行時エラー「9」(インデックスが有効範囲にありません)
原因: Worksheets("東京") のシート名が実在しません。全角・半角の違いや、名前の前後の空白もよくある原因です。
直し方: シートのタブの名前と、コードの "" の中を1文字ずつ見比べます。
別のシートが書き換わっていた(エラーは出ない)
原因: With の内側で . を付け忘れています。Range("B2") はアクティブシートのB2を指します。
直し方: With の内側は、.Range・.Cells のように . から書き始めます。
Worksheets(1) で書いたら、後で別のシートを処理していた
原因: シートを足したり動かしたりして、並び順が変わりました。
直し方: Worksheets("東京") のような名前指定に書き換えます。
実行時エラー「13」(型が一致しません)
原因: 合計するB列に、「未入力」「−」などの文字が混ざっています。
直し方: 数値以外を飛ばすなら、足し算の行を If IsNumeric(.Cells(r, 2).Value) Then 〜 End If で囲みます。
まとめ
- セル指定は「どのブックの → どのシートの → どのセル」の階層で読む
- 上の階層を省略すると、今アクティブなものが使われる。エラーにならないので気づきにくい
- 基本は
ThisWorkbookとシート名から書き始める - 決まった範囲なら
Range、ループで動かすならCells - 同じ階層を繰り返すなら
With。内側は.から書く
関連記事
- 【Excel VBA】Select、Activate、他セル指定方法の比較 — Select/Activateを使わない書き方の比較
- 【VBA】コピペで使える定番スニペット10選(最終行取得・シート存在確認・ファイル選択ほか) — 最終行取得などの定番パターン
サンプルファイル
記事中で使用しているサンプルデータはこちらからダウンロードできます。
