TL;DR — 列の移動は、行の移動 を別の軸で行ったものです。列全体 を切り 取って Insert します — 貼り付けてはいけません。
Columns("C").Cut Destination:=Columns("F")は F 列 の上に貼り付けて消し去ります。Columns("C").CutのあとColumns("F").Insertなら、F の前にすき間を空 けて列を差し込み、C の穴を閉じます — 何も失われません。きれいに保つルールは二つ。EntireColumnを切 り取ること(部分的な範囲は決して使わない)、そして移動はシフトだと忘れないこと — 対象より左の列を切り 取ると、対象は一列左へ引き寄せられます。
Sub MoveColumn()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Report")
ws.Columns("C").Cut ' 列全体を持ち上げる
ws.Columns("F").Insert Shift:=xlToRight ' 列 F の前に INSERT し、残りを右へずらす
Application.CutCopyMode = False
End Sub
列の移動は、行の移動の水平方向の双子であり、同じ Range.Cut で動きます。行のケースで 知っていることはすべてそのまま通用します — 貼り付けではなく挿入、シフトに気をつける、ブロックは一回の 呼び出しで移動する — ただ切り取るのが列で、下ではなく横にずれるだけです。
この記事で学べること
- なぜ EntireColumn を切り取るのか、そして誤って部分的な範囲を切り取ると何が起きるのか
- 第一の罠 —
Cut Destination:=は対象の列に上書きし、そのデータを失う - 列を右へ動かすと対象の列が一つ左へずれる理由(同じシフトの罠を横にしたもの)
- 複数の列を間違った順序で着地させずに、決まったレイアウトへ並べ替える方法
- なぜ参照は
#REF!に砕けず、移動した列に追従するのか
考え方の軸:列全体を切り取ってから挿入する
列の移動は、行の移動とまったく同じく、二つの動作です。Columns("C").Cut で 列を持ち上げ、それから
置く — そして 貼り付け と 挿入 のどちらを選ぶかがすべてです。
- 貼り付け(
Cut Destination:=Columns("F"))は、C 列のセルを F 列の上に落とし、F が持っていたすべ てを上書きします。 - 挿入(
Columns("C").CutのあとColumns("F").Insert)は、F 列の前にすき間を空け、切り取った列を 差し込み、C にできた穴を閉じます。他の列は場所を空けるために右へずれます。
列をレイアウトの中へ 移動する には、常に挿入します。貼り付けは空の列を上書きするためのもので、並べ替 えのためのものではありません。これは 行の移動 を 90 度回転させたものです。グ リッドが水平に開いて閉じ、右側の列が番号を振り直されます。
EntireColumn を切り取る、部分的な範囲では行わない
列の移動が意味を持つのは、列全体に対してだけです。部分的な範囲を切り取ってそれを列として挿入しようとす ると、グリッドが裂けるか、役に立たない結果になるかのどちらかです。
ws.Range("C1:C50").Cut ' 誤り - 列ではなく部分的な範囲
ws.Range("F1:F50").Insert Shift:=xlToRight ' 50 行分しかずれず、51 行目以降がずれてしまう
これは 50 個のセルを横にずらすだけで、F 列の残りはその場に留めます — 50 行目より下のデータは、本来属す る行と揃わなくなります。すべての行が一緒に動くよう、列全体 を移動しましょう。
ws.Columns("C").Cut ' 正しい - 列全体、すべての行が足並みを揃える
ws.Columns("F").Insert Shift:=xlToRight
列を列文字ではなく見出しで見つけるときも、.EntireColumn で列全体まで広げておきましょう。
Dim col As Range
Set col = ws.Rows(1).Find("Region", LookAt:=xlWhole) ' 見出しセルを見つける
col.EntireColumn.Cut ' それがある列全体を切り取る
ws.Columns("B").Insert Shift:=xlToRight
これは 列の挿入 のルールの鏡像です。構造的な列操作は Columns /
.EntireColumn に対して行い、部分的な範囲には決して行いません。
シフトの罠を横に:右へ動かすと対象が左へずれる
行の番号を振り直すのと同じシフトが、列の番号も振り直します。C 列を切り取って F 列に挿入すると、C のすき 間は移動の一部として閉じるので、D から F の列はそれぞれ 一つずつ左へずれ — F だった列は今 E にいて、 切り取った列はずれたあとのグリッドを基準に着地します。
列文字ではなく見出しの検索で移動すれば、シフトに噛みつかれません。Find は、すべてが落ち着いたあとに
列が どこにあるか を突き止めるからです。
ws.Columns("C").Cut
ws.Rows(1).Find("Total", LookAt:=xlWhole).EntireColumn.Insert Shift:=xlToRight
Application.CutCopyMode = False
どうしても列文字を使うなら、列を 左へ 動かす(元が対象の右)と対象の文字はそのまま、右へ 動かす (元が対象の左)と対象は一列手前へずれます。
複数の列を決まったレイアウトへ並べ替える
Cut/Insert を一つずつ繰り返して列を並べ替えると、レイアウトが乱れます。移動のたびに、まだ配置してい
ない列の文字がかき混ぜられるからです。信頼できるやり方は、動く文字を追いかけるのをやめて、各列を望む順
序に対して 見出し名で 配置し、左から右へ進めて、配置済みの列が次の列の安定した錨になるようにすること
です。
Dim wanted As Variant, k As Long
wanted = Array("Date", "Region", "Product", "Amount") ' 望む順序、左から右へ
For k = LBound(wanted) To UBound(wanted)
Dim src As Range
Set src = ws.Rows(1).Find(wanted(k), LookAt:=xlWhole)
If Not src Is Nothing Then
src.EntireColumn.Cut
ws.Columns(k + 1).Insert Shift:=xlToRight ' 枠 k+1 に配置して、次へ進む
End If
Next k
Application.CutCopyMode = False
各ステップが固定した枠番号を狙い、元を名前で見つけるので、ずれていく文字がレイアウトを狂わせることは決 してありません。
Cut は参照を運ぶ、削除は壊す
行と同じく、Cut + Insert が安全なのは Excel がそれに追従するからです。=Report!C2 という数式は、C
列を新しい位置まで追いかけるよう書き換えられ、移動後も同じデータを読み続けます。これは
列を削除する ときの逆です。取り除かれた列を指していた数式は =#REF! に
潰れます。移動はデータを引っ越しさせ、その参照も連れていきます。削除はデータを壊し、参照を宙ぶらりんに
します。
ExcelMaster の活用
列の並べ替えは、行と同じ三つの罠を横にして隠しています — 挿入か貼り付けか(データを保つか壊すか)、ま だ配置していない列の番号を振り直すシフト、そして部分的な範囲ではなく列全体を切り取ること — そしてどれも エラーを出さずに失敗します。対象の列が黙って上書きされる、レイアウトが一文字ずれて乱れる、あるいは列の 半分が 50 行目より下でずれたまま残る、といった具合です。
ExcelMaster には、望むレイアウ トをそのまま伝えられます — 「列を Date, Region, Product, Amount の順に並べて」 — すると、各列を列全体と して切り取り、ずれていく文字に惑わされないよう見出しで見つけ、そこにあるものの上に貼り付けるのではなく 所定の位置へ 挿入 します。ブックとコードはあなたの手元に残ります。
よくある質問
VBA で列をデータを失わずに移動するには?
列全体を切り取って Insert します。ws.Columns("C").Cut のあと ws.Columns("F").Insert Shift:=xlToRight。
Insert はすき間を空けて他の列を右へずらすので、何も上書きされません。Columns("C").Cut Destination:=Columns("F")
は F 列の上に貼り付けて壊します — 使うのは F が空のときだけにしましょう。
一つ移動すると、なぜ列がずれるのですか?
移動がシフトだからです。C 列を切り取るとそれが取り除かれてすき間が閉じるので、切り取った列が挿入される
前に、右側の列が一つ左へずれます — 文字で指定した対象は今、一列手前にいます。べた書きの文字ではなく、
Find で見つけた見出しを基準に挿入すれば、シフトは問題でなくなります。
VBA で列を特定の順序に並べ替えるには?
各列を見出し名で見つけ、固定した枠へ挿入します。左から右へ進めて、Rows(1).Find("Region").EntireColumn.Cut
のあと Columns(2).Insert、という具合です。安定した枠番号を狙いつつ元を名前で見つけるので、ずれていく
文字がレイアウトを乱すことはありません。
列全体ではなく、部分的な列範囲を移動できますか?
できますが、データがずれます。Range("C1:C50") を切り取って挿入すると、その 50 個のセルだけが横にずれ、
グリッドの残りは取り残されるので、50 行目より下が揃わなくなります。本物の列の移動には、すべての行が一緒
に動くよう Columns("C") か .EntireColumn を切り取りましょう。
列を移動するには Cut と Copy のどちらを使うべきですか?
Cut を使いましょう。列が着地すると元の列を空にするので、新しい位置に一つだけ残ります。Copy は元をそ
の場に残すので、自分で削除しなければならず — 間違えやすい余分な一手間です。移動と複製の詳しい仕組みは
VBA 切り取り を参照してください。
検証環境
動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-17.
関連ガイド: VBA 行の移動 · VBA 切り取り · VBA 列の挿入 · VBA 列の削除 · VBA コピー&貼り付け
