TL;DR — どちらも「長方形全体」を取得しますが、答えている問いが違います。
Worksheet.UsedRangeは Excel がこれまでに触れたすべて — 書式だけのセルも 含み、データを削除しても縮まないキャッシュ済みの外接矩形で、過大に報告 します。Range.CurrentRegionは1 つのセルの周囲の連続ブロックで、その場で 計算され(Ctrl+Shift+*が選択するのと同じもの)、最初の完全な空白行または 空白列で止まります。きれいな 1 つの表なら、Range("A1").CurrentRegionが信頼 できる選択です。UsedRangeは「シート全体を消去する」ときのためにとっておき、UsedRange.Rows.Countを最終行の番号のように読んでは決していけません。
最終行を求める ことができるようになると、次の質問は たいてい「ループ・コピー・書式設定できるように、ブロック全体を一度にちょうだい」 です。VBA には、一見どちらでもよさそうに見えて実はそうではない組み込みが 2 つ あります。選択を間違えると、最もよくあるマクロのバグ 2 つの原因になります。数百も の幽霊行を処理してしまうこと、そして行数を行番号のように読んでしまうことです。
この記事で学べること
- 考え方の軸:キャッシュされた外接矩形 vs. その場で測る連続ブロック
- なぜ
UsedRangeは過大に報告し、縮むのを拒むのか - なぜ
UsedRangeは A1 から始まるとは限らないのか — 数え違いのバグ - なぜ
CurrentRegionは空白行で止まるのか、そしてそれがまさに望みどおりになるのはいつか - どの仕事にどちらを使うかの明確なルール
考え方の軸:古いスナップショット vs. その場の測定
UsedRange は、Excel が自分用に持っているスナップショットです。シート上で
あなたがしたこと — 値を入力した、罫線を引いた、塗りつぶしを設定した — を、これまで
に囲んだ中で最小の長方形です。Excel はこれをキャッシュし、遅延して更新するため、
現実に後れを取ります。広がるのには積極的で、縮むのには消極的なのです。
CurrentRegion は、今立っている場所から取る、その場の測定です。セルを 1 つ
渡すと、外へ — 上・下・左・右へ — 広がり、四方すべてで完全な空白行または空白列に
当たるまで伸びます。これは、セルをクリックして Ctrl+Shift+*(または一度
Ctrl+A)を押すことのコード版です。何もキャッシュされず、尋ねた瞬間に計算されます。
Sub GrabTheBlock()
Dim ws As Worksheet
Set ws = ActiveSheet
Debug.Print ws.UsedRange.Address ' シートのキャッシュされた外接矩形
Debug.Print ws.Range("A1").CurrentRegion.Address ' A1 周辺のその場のブロック
End Sub
この違い — キャッシュされて居座る vs. その場で局所的に測る — が、以下のすべての 罠を説明します。
幽霊行バグを防ぐルール:UsedRange は過大に報告する
最も時間を無駄にする失敗パターンです。UsedRange をループすると、データよりずっと
多くの行を処理してしまいます。UsedRange は書式だけを持つセルも数えるからです。
A1000 に一度罫線を引いて値を削除しても、A1000 は UsedRange の中に残ります。さらに
悪いことに、行の中身を削除しても UsedRange は縮みません — Excel は、ブックを
保存するか明示的にリセットするまで、古い外接矩形を保持します。
' UsedRange は実際のデータよりはるかに大きくなりうる
Dim r As Range
For Each r In ws.UsedRange.Rows
' ...空で書式だけの行を数百も処理してしまうことがある
Next r
大幅に編集した後でどうしても UsedRange を使う必要があるなら、一度読み取って
Excel に再計算を促すか、明示的にリセットします。
Dim junk As Range
Set junk = ws.UsedRange ' 触れることで再計算を促す
より深い教訓です。UsedRange が答えるのは「Excel は何に触れたか?」であって、
「私のデータはどこか?」ではありません。これは別々の問いであり、答えが同じになる
のは時々だけです。
数と番号のルール:UsedRange は A1 から始まるとは限らない
2 つ目の定番バグです。データが C5 から始まっていれば、UsedRange も C5 から
始まります — A1 ではありません。ですから、その .Rows.Count はブロックの高さで
あって最終行の番号ではなく、.Cells(1, 1) は A1 ではなく C5 です。
' データは C5:F20 にある
ws.UsedRange.Rows.Count ' -> 16 (行数:5〜20 行)
ws.UsedRange.Row ' -> 5 (開始位置)
' 最終行の番号 = 開始行 + 行数 - 1
ws.UsedRange.Row + ws.UsedRange.Rows.Count - 1 ' -> 20 (実際の最終行)
UsedRange.Rows.Count を「最終行」として読むのが正しいのは、データがたまたま
1 行目から始まっているときだけです。その偶然に頼ってはいけません — Row + Count - 1
の計算をするか、本当の最終行の番号には .End(xlUp) を使いましょう。
連続性のルール:CurrentRegion は空白で止まる
CurrentRegion は 1 つの連続した島を取得します。完全な空白行または空白列が
1 つあれば、それは越えられない壁になります。シートに空白で囲まれた表が 1 つだけ
あるときは、これが利点です — その表がちょうど、本当の左上を起点に、幽霊行なしで
得られます。
Dim block As Range
Set block = ws.Range("A1").CurrentRegion ' 見出し + 連続するデータすべて
しかし、データに意図的な空白の区切り行(小計の空き、視覚的な仕切り)があるときは
罠になります。CurrentRegion は、種となるセルに接している部分だけを返し、残りを
無言で取りこぼします。そして種セルはブロックの内側になければなりません — A1 が
空白のときの Range("A1").CurrentRegion は、A1 だけを返します。
判断の目安:いつ、どちらを使うか
- 見出し付きで、途中に空白行のないきれいな表 1 つ →
Range("A1").CurrentRegion。その場で測り、本当の左上から始まり、空白に正直で、 幽霊行がありません。「自分の表を取得する」ときの既定です。 - 「シート全体を消去・リセット・書式設定する」 →
ws.UsedRange。消したり書式を 一掃したりするときは、過大報告は無害 — むしろ好都合です。 - 「データ行は何行あるのか?」 → どちらも直接は使いません。
最終行ガイド の最終行検出(
.End(xlUp)か.Find)を 使うか、UsedRangeに対してRow + Count - 1の計算をします。 - 意図的な空白の区切り行があるデータ →
CurrentRegionは使いません(最初の 切れ目で止まります)。本当の最終行を求めて、範囲を明示的に組み立てましょう。
簡単に言えば、表を読むなら CurrentRegion、シートを一掃するなら UsedRange、
行を数えるなら最終行検出です。
ExcelMaster の活用
ブロックの取得は、常に目的のための手段です — 並べ替える、重複を除く、コピーする、 要約する。ExcelMaster は、その最終目標を平易な日本語で受け取ります — 「注文テーブル全体を整えて、重複行を削除して」といった具合に — そして確実な方法で データを選ぶので、空で書式だけの 900 行をループするマクロを出荷したり、行数を行番号 と取り違えたりすることが決してありません。
定期実行するマクロの中では、これからも CurrentRegion を書くでしょう。しかし
「表全体に対して操作する」という単発の作業なら、操作を言葉で説明することで、
UsedRange と CurrentRegion のどちらにするかという判断そのもの — そしてその 2 つの
有名なバグ — を丸ごと回避できます。
よくある質問
VBA の UsedRange と CurrentRegion の違いは何ですか?
UsedRange は、Excel がこれまでに触れたすべてのセル(書式だけのセルも含む)を
ワークシート単位でキャッシュした外接矩形です。過大に報告し、保存するまで縮みません。
CurrentRegion は特定のセルの周囲でその場で計算され、空白行または空白列に当たる
まで広がるので、1 つの連続ブロックを返します。表を読むなら CurrentRegion、シート
を一掃するなら UsedRange を使いましょう。
なぜ UsedRange がデータより大きくなるのですか?
UsedRange が、書式(罫線・塗りつぶし)だけを持つセルも数え、値を削除しても
縮まないからです — Excel はファイルを保存するまで古い外接矩形を保持します。余分な
行・列を丸ごと削除するか、Range("A1").CurrentRegion を使って連続するデータだけを
取得しましょう。
UsedRange は必ずセル A1 から始まりますか?
いいえ。UsedRange は使用領域の左上から始まるので、データが C5 から始まって
いれば C5 から始まります。だからこそ UsedRange.Rows.Count は行数であって最終行の
番号ではありません — 最終行は UsedRange.Row + UsedRange.Rows.Count - 1 で計算します。
なぜ CurrentRegion はデータの一部を取りこぼすのですか?
CurrentRegion は種セルの周囲の連続ブロックだけを取得し、完全な空白行または空白列
があればそこで止まります。データに意図的な空白の区切り行があると、CurrentRegion は
セルに接している部分だけを返します。途中に空白があるデータには、最終行検出を使って
範囲を明示的に組み立てましょう。
VBA でデータ表全体を選択するには?
きれいな表 1 つなら、Range("A1").CurrentRegion.Select が、本当の左上を起点に、
見出しと連続するデータすべてを取得します。種セルが表の内側にあることを確認して
ください — 空白の種セルは、そのセル 1 つだけを返します。
検証環境
検証環境: Excel 365(Windows 11)、VBA 7.1 — 最終確認 2026-07-30。
関連ガイド: VBA Last Row · VBA Offset · VBA Range · VBA For Loop
