TL;DR — 挿入は削除の鏡像です。
.EntireRow.Insertは無から空白を生み出すのでは なく — 削除が行を上へ詰めるのとちょうど逆に、既存の行をすべて下へ押し下げて 隙間を開けます。つまり「グリッドが足元で動く」あの問題がそのまま当てはまります。 上から下へのループの中で挿入すると、まだ届いていない行がどんどん遠ざかっていくのです。 行全体は.EntireRow.Insertで挿入し、部分範囲ではShift:=xlDown(またはxlToRight)で向きを名指しし、新しい行がどの隣の書式をコピーするかはCopyOriginで決め、多数の行を足すときはループではなく複数行の範囲を1 回で挿入します。
' 5 行目の上に空行を 1 つ挿入し、5・6・7… を 1 行ずつ下へ押し下げる。
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
ws.Rows(5).EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
一度あの行削除の罠 — 削除がグリッドを上へずらすせいで行を飛ばす順方向ループ — に 出会っていれば、挿入に驚きはありません。同じ考え方が逆向きに走るだけだからです。挿入は グリッドを下へ押します。削除を難しくしていたすべて(番号が動く、行全体か部分か、 一度でやるかループでやるか)に、挿入側のぴったり対応する相手がいます。本記事はその 鏡像をたどるので、すでに持っている考え方が仕事のほとんどをやってくれます。
この記事で学べること
- 考え方の軸 — 挿入はグリッドを下へ押す。空いた場所を埋めるのではない
- 行全体の挿入と部分範囲の違い、そしてなぜ
Shiftが向きを決めるのか CopyOrigin— 挿入した行や列がどの隣の書式を継承するか- 自分の新しい行を再処理せずにループ内で挿入する
- 多数の行を 1 回で挿入する方法
考え方の軸:挿入はグリッドを下へ押す
行を削除するとそれが取り除かれて隙間が閉じるのとちょうど同じように、行を挿入すると
隙間が開き、場所を作るためにすべてが下へ押されます。ws.Rows(5).EntireRow.Insert は
5 行目に書き込むのではなく — 真新しい空の 5 行目を作り、古い 5 行目は 6 行目に、古い
6 行目は 7 行目に、と使用範囲の一番下まで送られます。新しい行が現れ、挿入位置より下の
既存の行はすべて 1 つ下へ動きます。
これが握っておくべき唯一の事実です。日常の挙動もループの罠も、どちらもここから生まれる
からです。「5 行目の上に挿入」とは、実は「5 で場所を空けて、残りを下へずらす」と言って
いるのです。列も横向きに同じで、Columns("C").Insert は新しい C 列を開き、D・E・F を
右へ押します。グリッドは伸縮自在で、Insert がそれを伸ばします — つまり挿入位置より下
(または右)にあるすべてのアドレスが、たった今変わったのです。
部分範囲のルール:Shift で向きを名指しする
行全体または列全体を挿入するときは、あいまいさはありません — 行全体は下へしか 行けず、列全体は右へしか行けません。しかし部分範囲を挿入すると、Excel はどちらへ 隣を押すか推測しなければならず、その推測は範囲の形に基づきます。
ws.Range("B5:D5").Insert Shift:=xlDown ' B:D を下へ押し下げ、A 列と E 列はそのまま
ws.Range("B5:B8").Insert Shift:=xlToRight ' これらのセルを右へ押し出す
部分範囲で Shift を省くと、Excel はブロックが縦より横に長いかどうかで向きを選びます —
誰も覚えていないルールで、下へ動かしたかったセルが横へ押し出される、あの結末に
つながります。範囲が行全体でも列全体でもないときは、必ず Shift を明示しましょう。
そしてたいていの場合、部分挿入自体が不要です。セルの部分ブロックをずらすと、含まれない
すべての列がずれる — 単一セルの削除が起こすのと同じ破損です。本当にブロックを動かし
たいのでない限り、.EntireRow.Insert/.EntireColumn.Insert に手を伸ばしましょう。
ws.Rows(5).EntireRow.Insert ' 行全体。すべての列がそろったまま
ws.Columns("C").EntireColumn.Insert ' 列全体。すべての行がそろったまま
意外に思われるルール:CopyOrigin が書式を決める
挿入したての行は、書式まで真っさらなわけではありません — Excel は隣の見た目をコピー
し、CopyOrigin がどちらかを選びます。既定は xlFormatFromLeftOrAbove なので、新しい
行は上の行の書式を継承します。たいていは問題ありません — 上の行が太字で網かけの
見出しで、新しいデータ行まで見出しの装いで現れるまでは。
' 新しい行は、上の見出しではなく下の行の書式をコピーする。
ws.Rows(2).EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromRightOrBelow
xlFormatFromRightOrBelow は、挿入位置の下の行から書式を取るよう Excel に指示します —
見出しのすぐ下にデータ行を挿入するときに、まさに欲しい挙動です。これは小さなフラグ
ですが結果は目に見えます。間違えれば挿入した行はすべて違う服を着せられ、正しく選べば
挿入はなじんで見えます。本当にまっさらな行が欲しいなら、まず挿入し、それから
.ClearFormats で書式を明示的に消しましょう。
ループの罠、その鏡像:逆順に挿入する、さもないと自分の行を再処理する
ループ内の挿入には、ループ内の削除と同じ危険が、逆向きに潜んでいます。下へ走査しながら、 「Total」行のたびに空の区切り行を後ろに挿入するとします。上から下へ動きながら挿入すると、 新しい行がまだ走査していない行をさらに下へ押しやり — 進め方によっては、ループは たった今作った行に突っ込んで再び挿入し、また挿入し……となりかねません。グリッドが足元で 膨らんでいくのです。
きれいな直し方は削除と同じ。下から上へループすることです。そうすれば挿入はすべて、 まだ訪れるべき行より下で起き、その番号を乱しません。
Dim i As Long, lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = lastRow To 2 Step -1
If ws.Cells(i, "A").Value = "Total" Then
ws.Rows(i + 1).EntireRow.Insert Shift:=xlDown ' 下側に挿入する。上側の行には影響しない
End If
Next i
逆順に進むと、挿入された各行は処理済みのセルの下に着地するので、まだ待っている行は
アドレスを保ちます。VBA 行の削除とまったく同じ作法です —
ループが行数を変えるなら、Step -1 で歩く。
多数の行を一度に挿入する:繰り返さず、リサイズする
100 行足すために .Insert を 100 回呼ぶのは遅い — 呼ぶたびに Excel はグリッドを組み直し、
再計算します。連続する n 行を挿入するには、n 行の範囲を 1 回の操作で挿入します。
対象行をつかみ、.Resize(n) で欲しい高さにして、それを挿入します。
' 10 行目の上に空行を 5 つ、1 回の呼び出しで挿入する。
ws.Rows(10).Resize(5).EntireRow.Insert Shift:=xlDown
Rows(10).Resize(5) は 10 行目から 14 行目です。そのブロックを挿入すると 5 行が一度に
開き、残りをまとめて下へ押します。5 回ではなく 1 回の構造変更です。大きなシートに散らばった
挿入なら、最速のパターンはたいてい、補助列を足して並べ替えかフィルターで行をまとめ、
一括で挿入することです — 一括削除を速くするのと同じ「構造の変更は一度で」の原則です。
大きな挿入を Application.ScreenUpdating = False と手動計算で包めば、一瞬で終わります。
ExcelMaster の活用
挿入のコードは、静かで見た目だけの形で失敗します。Shift を省いたせいで違う向きに
押された部分範囲、見出しの太字をまとった新しい行、自分の出力に挿入してしまう上から
下へのループ、レポートをのろのろにする 100 回の個別挿入。どれも「挿入がうまくいかなかった」
ように見え、はっきりしたエラーには見えません。
ExcelMaster なら、
望みを言うだけです — 「小計のたびに空行を後ろに足して」「サマリーの上に 3 行挿入して」
「C 列と D 列の間に新しい列を入れて」。.EntireRow.Insert(または
.EntireColumn.Insert)を正しい Shift と CopyOrigin で書き、安全な向きにループし、
複数行の挿入を 1 回にまとめ、まずシートをバックアップします。ブックもコードもあなたの
手元に残り、グリッドがどちらへ動くのかを当てる作業だけを飛ばせます。
よくある質問
VBA で行を挿入するには?
押し下げたい行に .EntireRow.Insert を使います。ws.Rows(5).EntireRow.Insert は
新しい空の 5 行目を作り、古い 5 行目とその下すべてを 1 つ下へ動かします。分かりやすさの
ために Shift:=xlDown を、新しい行がどの隣の書式を継承するかを決めるために
CopyOrigin を添えましょう。
挿入時の Shift 引数は何をする?
Shift は、部分範囲を挿入するときに既存のセルをどちらへ押すかを Excel に伝えます —
xlDown は下へ、xlToRight は右へ動かします。行全体・列全体には不要ですが
(一方向にしか行けないため)、部分ブロックでは重要です。省くと Excel が範囲の形から
向きを推測してしまうからです。
挿入した行の書式がおかしいのはなぜ?
挿入した行は隣の書式をコピーし、それを CopyOrigin が選びます。既定の
xlFormatFromLeftOrAbove は上の行をコピーします — だから見出しの下に挿入すると新しい行が
見出しのように見えます。代わりに下の行をコピーするには
CopyOrigin:=xlFormatFromRightOrBelow を渡すか、挿入後に新しい行へ .ClearFormats を
呼びましょう。
VBA で複数の行を一度に挿入するには?
対象行を必要な数にリサイズし、そのブロックを 1 回で挿入します。
ws.Rows(10).Resize(5).EntireRow.Insert は 10 行目の上に 5 行を挿入します。複数行をまとめて
1 回挿入する方が、.Insert を 5 回呼ぶよりずっと速いのです。Excel がグリッドを組み直すのが
一度で済むからです。
行を挿入するとき、順方向と逆順のどちらでループすべき?
削除と同じ理由で、逆順です。挿入はまだ走査していない行をさらに下へ押しやり、上から
下へのループはたった今作った行に挿入してしまうことがあります。
For i = lastRow To 2 Step -1 でループすれば、挿入はすべてまだ処理すべきセルより下に
収まり、その行番号がずれることはありません。
検証環境
動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-07。
関連ガイド: VBA Delete Rows · VBA Hide Columns and Rows · VBA Last Row · VBA Range · VBA For Loop
