🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の UsedRange と CurrentRegion — データブロック全体を取得する(どちらを信じるべきか)

|

Excel VBA の UsedRange と CurrentRegion — データブロック全体を取得する(どちらを信じるべきか)

TL;DR — どちらも「長方形全体」を取得しますが、答えている問いが違います。 Worksheet.UsedRange は Excel がこれまでに触れたすべて — 書式だけのセルも 含み、データを削除しても縮まないキャッシュ済みの外接矩形で、過大に報告 します。Range.CurrentRegion1 つのセルの周囲の連続ブロックで、その場で 計算され(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