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

Excel VBA で行をグループ化する — 折りたたみ式アウトラインとレベルを使いこなし、集計行の罠を避ける

|

Excel VBA で行をグループ化する — 折りたたみ式アウトラインとレベルを使いこなし、集計行の罠を避ける

TL;DRRows("2:5").Group はその行を隠すわけでも削除するわけでもありません。折りたたみ可能な アウトライン に一つの帯を追加するだけで、行はそのまま残り、余白にある +/ ボタンの裏で畳めるよ うになるだけです。グループ化は 畳む ことであって、隠すことではありません。誰もがつまずく点は二つ。 折りたたみボタンは既定ではグループの の行に付き(Outline.SummaryRow)、そして畳むときは .Hidden を自分で設定するのではなく、ShowLevelsレベル ごとに折りたたむべきだという点です。

Sub GroupDetailRows()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Report")
    ws.Cells.ClearOutline                 ' 古いアウトラインを先に一掃し、再実行してもフラットな状態を保つ
    ws.Outline.SummaryRow = xlSummaryAbove ' +/- ボタンを詳細の上にある合計行に付ける
    ws.Rows("3:7").Group                   ' 行 3-7 を行 2 の合計の下に畳み込む
    ws.Outline.ShowLevels RowLevels:=1     ' .Hidden ではなくコードでトップレベルまで折りたたむ
End Sub

行のグループ化、列のグループ化、そしてアウトラインオブジェクト自体は、三つの衣をまとった一つの仕組みで す — .Group が帯を追加し、アウトラインは レベル ごとに折りたたみと展開を行い、シート全体の一つの 設定が折りたたみボタンをどちら側に置くかを決めます。行のグループ化で畳み方・レベル・集計側の三つを押さ えておけば、列のグループ化は同じ考え方を 90 度回転させただけのものになり、どちらも同じ アウトラインオブジェクト に支えられています。

この記事で学べること

  • 考え方の軸 — グループ化は 畳む ことであり、隠すことでも削除することでもない
  • 集計行の罠 — なぜ +/ ボタンがグループの下に付くのか、そしてどう動かすか
  • なぜ .Hidden を自分で設定するのではなく、ShowLevelsレベル ごとに折りたたむべきなのか
  • .Group を入れ子にするとアウトラインのレベルがどう深くなるか、そしてマクロを再実行すると過剰にグルー プ化されてしまう理由
  • UngroupClearOutline の違い — 一つの帯を外すか、アウトライン全体を一掃するか

考え方の軸:グループ化は畳むことであり、隠すことではない

Rows("2:5").Group は「2 行目から 5 行目を隠す」ではありません。「2 行目から 5 行目を 畳めるように する」です。Excel は左の余白にアウトラインバーを描き、そこに ボタンが付きます。クリックすると行は 視界から折りたたまれ、+ をクリックすると元に戻ります。行は .Hidden = True という意味で隠されたこと は一度もなく、必要に応じて畳んだり開いたりする方法を知っている アウトライン が管理しているのです。

この違いがこの記事のすべてです。隠す とは、自分で覚えていて元に戻さなければならない一方通行の状態で す。畳む とは、Excel が代わりに追跡してくれる可逆的な表示であり、レベルに整理され、読み手がクリック できるボタンが付いています。グループ化について人を驚かせることのすべて — ボタンがどこに現れるか、なぜ .Hidden とアウトラインの言い分が食い違うのか、なぜマクロを再実行するとデータが三段階も深く埋もれてし まうのか — は、グループ化が構造を持った畳み方であって、無造作な隠し方ではないことから生じています。

集計行の罠:ボタンはどちら側に付くのか

2 行目から 5 行目をグループ化しても、折りたたみボタンはグループ の上に 現れるわけではありません — その真下にある 6 行目 に現れます。これは Worksheet.Outline.SummaryRow の既定値が xlSummaryBelow だからです。Excel は、小計や合計が集計対象の詳細の にあるものと決めてかかり、ボタンをそこに置きま す。

この既定値は、「詳細のあとに合計」という古典的なブロックには正しいものです。しかし、ほとんどのダッシュ ボードがそうであるように、合計が詳細の にある場合には間違っています — そしてこれがグループ化に関 する不満の第一位です。

ws.Outline.SummaryRow = xlSummaryAbove    ' ボタンをグループの上にある合計に付ける
ws.Rows("3:7").Group                       ' 合計は行 2、詳細は行 3-7

逆のまま放っておくと、ボタンはみんなが実際に読んでいる数字から切り離されてしまいます。合計は行 2 にあ るのに、+ は行 8 まで下がり、最後の詳細行の下に浮いた状態になります。SummaryRowシート単位 の設定です — アウトラインを組み立てる前に一度だけ決めて、合計がある場所に合わせましょう。あとから設定 してもシート上のボタンは配置し直されますが、驚くよりも、最初の一歩として意図的に決めておくほうがきれい です。

.Hidden ではなくレベルで折りたたむ

コードでグループを折りたたむとき、つい手が伸びるのが行を隠すことです。

ws.Rows("3:7").Hidden = True               ' 誤り - アウトラインが把握しない手動の隠し方

やってはいけません。これはアウトラインがまったく関知しない 隠し方 を作ってしまうので、+/ ボタン と実際の行の状態がずれていきます — ボタンは展開されていると言っているのに行は隠れている、あるいはその 逆、ということが起こります。代わりにアウトライン経由で折りたためば、Excel がすべてを一貫させてくれます。

ws.Outline.ShowLevels RowLevels:=1         ' トップレベルだけを表示 - それより下はすべて畳まれる
ws.Outline.ShowLevels RowLevels:=2         ' 2 レベル分表示 - 一層分だけ戻して展開する

ShowLevels は一回の呼び出しで シート全体 をあるアウトラインレベルへ動かし、ボタンは嘘をつきません。 レベル全体ではなく一つのノードだけを展開・折りたたみしたいときは、その集計行に対して ShowDetail を使 います — これは アウトラインオブジェクト の他の内容とあわせて扱います。

レベル:グループの入れ子と、再実行が過剰グループ化を招く理由

ある範囲をグループ化し、その中のさらに小さな範囲をグループ化すると、二つのフラットなグループができる わけではありません — 一段深い 入れ子のアウトライン ができるのです。

ws.Rows("2:20").Group                       ' レベル 1 - セクション全体
ws.Rows("5:9").Group                        ' レベル 2 - その中のサブブロック

アウトラインは最大 8 レベル まで深くできます。本物の階層構造には強力な仕組みですが、意図せず起きる と罠になります。その意図しない事態とは、マクロの再実行です。すでに グループ化されている行に .Group を掛けると、さらに 別の 帯が上に追加されるので、2 回目の実行でレベル 2、3 回目でレベル 3 と、実行す るたびにデータがどんどん深く埋もれていきます。グループ化はべき等ではありません。

直し方は、「なければ作る」というルーチンならではの規律と同じです — 作り直す前にリセットすることです。

ws.Cells.ClearOutline                       ' アウトライン全体を取り除き、まっさらから組み立てる
ws.Rows("3:7").Group

先にクリアし、次にグループ化する — この順序を守れば、マクロは 1 回実行しても 10 回実行しても同じアウ トラインを作ります。

Ungroup と ClearOutline

グループ化を元に戻す方法は二つありますが、その規模は同じではありません。

ws.Rows("3:7").Ungroup                       ' その範囲から一つの帯・一つのレベルだけを外す
ws.Cells.ClearOutline                        ' シート上のアウトライン全体を一回の呼び出しで取り除く

Ungroup は精密な道具です — 一つの範囲から一つのレベルだけを剥がします。ClearOutline は大鎚です — アウトライン全体を一掃してまっさらから始めます。よくある間違いは、すべてを消そうとして Ungroup を ループさせることです。遅いですし、範囲を正しく指定するのも面倒で、しかもそれは ClearOutline が一文 でやってくれることそのものです。どちらも行データを一行たりとも削除しません — 消えるのは 畳み方 であ って、行ではありません。

ExcelMaster の活用

行のグループ化は一行に見えて、三つの判断を隠しています — あなたの レイアウトにとって折りたたみボタ ンをどちら側に置くべきか、レベルで折りたたむのか .Hidden に漏れ出させてしまうのか、そして再実行する たびにデータが静かに一段ずつ深く埋もれていかないか、です。どれか一つでも間違えると、エラーも出さずに失 敗します。合計から離れて浮いたボタン、行の状態について嘘をつくアウトラインボタン、あるいは三段も深く折 りたたまれてしまったレポートです。

ExcelMaster には、望むことをそ のまま伝えられます — 「それぞれの合計の下に詳細行をグループ化して、トップレベルまで折りたたんで、ボタ ンは合計行に付けて」 — すると、レイアウトに合わせて SummaryRow を設定し、再実行してもフラットな状態 を保つよう古いアウトラインをクリアし、正しい行をグループ化し、.Hidden ではなく ShowLevels で折りた たみます。ブックとコードはあなたの手元に残ります。

よくある質問

VBA で行をグループ化するには?

行全体に対して .Group を呼びます。Rows("3:7").Group は行 3 から 7 を一つのアウトラインの帯に折り たたみ、左の余白に折りたたみボタンが付きます。ThisWorkbook.Worksheets("Report").Rows("3:7").Group の ようにシートを修飾しておくと、たまたまアクティブなシートに依存しなくなります。行は隠されたり削除された りするわけではなく、畳めるようになるだけです。

なぜグループの折りたたみボタンは上ではなく下に付くのですか?

Worksheet.Outline.SummaryRow の既定値が xlSummaryBelow で、合計が詳細の下にあるものと決めてかかっ ているからです。合計が詳細行の上にある場合は、グループ化する前に ws.Outline.SummaryRow = xlSummaryAbove を設定し、+/ ボタンをみんなが読む合計行に付けましょう。

VBA でグループ化した行を折りたたんだり展開したりするには?

アウトラインのレベルを使います。ws.Outline.ShowLevels RowLevels:=1 はトップレベルまで折りたたみ、数 字を大きくするとより多くの層が展開されます。行に自分で .Hidden = True を設定してはいけません — それ はアウトラインが把握しない手動の隠し方で、ボタンと実際の行の状態がずれてしまいます。

なぜマクロを実行するたびにグループが増えていくのですか?

すでにグループ化されている行に .Group を掛けると、さらに一段レベルが追加されるからです — グループ化 はべき等ではありません。先頭で ws.Cells.ClearOutline を呼んで既存のアウトラインを一掃してから、まっ さらからグループ化しましょう。そうすれば、マクロを 1 回実行しても 10 回実行しても結果は同じになります。

Ungroup と ClearOutline の違いは何ですか?

Ungroup は特定の範囲から一つの帯・一つのレベルだけを取り除き、ClearOutline はシート上のアウトライ ン全体を一回の呼び出しで取り除きます。一つのグループを元に戻すには Rows("3:7").Ungroup を、すべてを 消すには Ungroup をループさせるのではなく ws.Cells.ClearOutline を使いましょう。どちらもデータは削 除しません — 消えるのは畳み方です。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-16。

関連ガイド: VBA 列のグループ化 · VBA アウトライン · VBA 列の非表示 · VBA 行の挿入 · VBA 行の削除