この記事でできること
- VBAでシート内のセル結合を一括解除できる
- 結合解除後の空白セルに、元の値を下方向にフィルできる
- 結合だらけの帳票を、フィルターやVLOOKUPが使えるデータベース形式に変換できる
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
—
完成イメージ(Before / After)
Before(結合セルだらけの帳票)
| A(部署) | B(氏名) | C(売上) | |
|---|---|---|---|
| 1 | 部署 | 氏名 | 売上 |
| 2 | 営業(結合:2-4行) | 田中 | 50,000 |
| 3 | 鈴木 | 30,000 | |
| 4 | 佐藤 | 45,000 | |
| 5 | 経理(結合:5-6行) | 高橋 | 60,000 |
| 6 | 伊藤 | 35,000 |
A列の「営業」「経理」がセル結合されている。この状態ではフィルターで「営業」を絞り込めない。VLOOKUPも正しく動かない。
After(結合解除+値フィル後)
| A(部署) | B(氏名) | C(売上) | |
|---|---|---|---|
| 1 | 部署 | 氏名 | 売上 |
| 2 | 営業 | 田中 | 50,000 |
| 3 | 営業 | 鈴木 | 30,000 |
| 4 | 営業 | 佐藤 | 45,000 |
| 5 | 経理 | 高橋 | 60,000 |
| 6 | 経理 | 伊藤 | 35,000 |
全行にデータが入っている。フィルターで「営業」を絞り込める。VLOOKUPもピボットテーブルも正常に使える。
—
他部署から届く月次報告書が、セル結合だらけだった。「営業」が3行結合、「経理」が2行結合。見た目はきれいだけど、フィルターをかけると「営業」で絞り込んでも1行しか表示されない。VLOOKUPで部署を引こうとしても、結合の2行目以降は空白扱いでエラーになる。
手作業で結合を1つずつ解除して、空白セルに値をコピペしていた。30行ぐらいならまだいいけど、500行の帳票が来たときは心が折れかけた。
VBAで一括解除+値フィルを覚えてからは、500行でも3秒で終わる。結合セルに毎月苦しめられている人に、この方法を知ってほしい。
セル結合は「見た目のための機能」であって「データのための機能」ではない。VBAで解除してデータベース形式に戻せば、Excelの本来の力を引き出せる。
なお、結合解除後に不要な空白行が残る場合は 空白行・空白セルを一括で削除する方法 で一括削除できる。書式が崩れた場合は セルの書式を一括変更する方法 で整えるとよい。
—
どんな場面で使う?
- 他部署から届く帳票がセル結合だらけで、フィルターやVLOOKUPが使えない
- ピボットテーブルの元データにセル結合が含まれていて集計が正しくできない
- 結合を手動で1つずつ解除して値を埋め直す作業に毎回時間を取られている
- 結合だらけのExcelを「データベース形式」に変換してデータ分析に使いたい
—
事前準備
バックアップを取る
結合解除は元に戻せないことがある。 VBAで実行した操作はCtrl+Zで戻せない場合が多い。実行前に必ずファイルのコピーを別フォルダに保存しておくこと。
Excelをマクロ有効ブック(.xlsm)で保存する
- Excelを開く(新規でも既存でもOK)
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を 「Excel マクロ有効ブック (*.xlsm)」 に変更して保存
.xlsx のままだとマクロが保存されない。必ず .xlsm にすること。
VBE(コードを書く画面)を開く
Alt + F11 キーを押すとVBE(Visual Basic Editor)が開く。
標準モジュールを挿入する
- VBEのメニューで「挿入」→「標準モジュール」をクリック
- 右側にコードウィンドウが開く → ここにコードを貼り付ける
—
手順(コピペ → 動作確認まで約5分)
- 上の「事前準備」でVBEを開き、標準モジュールを挿入する
- 下の「コード(基本版)」をコピーして、コードウィンドウに貼り付ける
- Alt + F8 を押してマクロ一覧を表示
- マクロ名を選択して「実行」をクリック
- セル結合が解除されていれば成功
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。
—
コード(基本版)– セル結合を一括解除する
まずはこれだけで動く。アクティブシートのすべてのセル結合を一括解除する。
'============================================================
' ■ セル結合を一括解除する(基本版)
' → シート全体の結合を UnMerge で一括解除
' → 結合解除後、左上セル以外は空白になる
'============================================================
Sub セル結合を一括解除する()
Dim ws As Worksheet
Set ws = ActiveSheet
'--- 結合セルがあるか確認
' UsedRange全体をチェックするため、シートが大きい場合は
' 数秒かかることがある
Dim cell As Range
Dim hasMerge As Boolean
hasMerge = False
For Each cell In ws.UsedRange
If cell.MergeCells Then
hasMerge = True
Exit For
End If
Next cell
If Not hasMerge Then
MsgBox "結合セルはありませんでした。", vbInformation
Exit Sub
End If
'--- 確認ダイアログ
If MsgBox("セル結合を一括解除します。" & vbCrLf & _
"解除後、結合の2行目以降は空白になります。" & vbCrLf & _
"よろしいですか?", vbYesNo + vbQuestion) = vbNo Then
Exit Sub
End If
'--- 一括解除
ws.Cells.UnMerge
MsgBox "セル結合を一括解除しました。", vbInformation
End Sub
コードの動作:
- アクティブシートを取得する
- UsedRange内に結合セルがあるか確認する(
MergeCellsプロパティで判定) - 結合セルがなければメッセージを出して終了する
- 確認ダイアログで Yes/No を選択する
Cells.UnMergeでシート全体の結合を一括解除する
重要: UnMerge で結合を解除すると、結合範囲の左上セルにのみ値が残り、他のセルは空白になる。値を保持したい場合は応用版を使う。
—
コード(応用版)– 結合解除後に値を下方向にフィル
基本版では結合を解除すると左上セル以外が空白になってしまう。応用版では、結合セルの値を保持してから解除し、空白セルに値を下方向にフィルする。
自分もこの「値フィル」を入れてからは、結合解除後の手作業がゼロになった。基本版だけだと空白セルを1つずつ埋める手間が発生する。応用版なら解除と同時に値が埋まる。
'============================================================
' ■ 結合解除+値を下方向にフィル(応用版)
' → 結合セルの値を保持してから解除
' → 空白セルに上のセルの値をコピー(下方向フィル)
'============================================================
Sub 結合解除して値をフィルする()
Dim ws As Worksheet
Set ws = ActiveSheet
'--- ★書き換えポイント ---
Dim targetCol As String
targetCol = "A" '← 結合を解除する列
Dim startRow As Long
startRow = 2 '← データ開始行(ヘッダーの次)
'--- ★ここまで ---
'--- 最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, targetCol).End(xlUp).Row
If lastRow < startRow Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
Application.ScreenUpdating = False
'--- 結合セルを検出 → 値を保持 → 解除 → フィル
Dim r As Long
Dim mergeVal As Variant
r = startRow
Do While r <= lastRow
Dim targetCell As Range
Set targetCell = ws.Range(targetCol & r)
If targetCell.MergeCells Then
'--- 結合セルの値を保持
mergeVal = targetCell.MergeArea.Cells(1, 1).Value
'--- 結合範囲の行数を取得
Dim mergeRows As Long
mergeRows = targetCell.MergeArea.Rows.Count
'--- 結合を解除
targetCell.MergeArea.UnMerge
'--- 解除後の空白セルに値をフィル
Dim fillRow As Long
For fillRow = r To r + mergeRows - 1
ws.Range(targetCol & fillRow).Value = mergeVal
Next fillRow
'--- 次の結合セルの位置へ移動
r = r + mergeRows
Else
r = r + 1
End If
Loop
Application.ScreenUpdating = True
MsgBox targetCol & "列の結合を解除し、値をフィルしました。", vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
targetCol |
結合を解除する列 | "A" |
startRow |
データ開始行(ヘッダーの次) | 2 |
コードの流れ
- 対象列と開始行を設定:
targetColとstartRowで処理範囲を指定する - 最終行の取得:
Cells.End(xlUp).Rowでデータの最終行を特定する - Do Whileループで結合セルを検出:
MergeCellsがTrueのセルを見つける - 値を保持:
MergeArea.Cells(1, 1).Valueで結合範囲の左上セルの値を取得する - 結合解除:
MergeArea.UnMergeで結合を解除する - 値フィル: 解除後の空白セルすべてに保持した値を代入する
- 位置を移動: 結合範囲の分だけスキップして次のセルへ進む
ポイント: MergeArea は結合されたセル範囲を返すプロパティ。結合の左上セルの値(Cells(1, 1).Value)を取得してから解除し、空白セルにフィルする。この順番が重要。
—
コード(実務版)– 結合だらけの帳票をデータベース形式に変換
実務では複数列が結合されている帳票が多い。A列の「部署」が3行結合、B列の「課」が2行結合、のように列ごとに結合範囲が異なる。実務版では、指定した複数列の結合を一括で解除し、すべての空白セルに値をフィルする。
以前、取引先から届く月次報告書が「部署」「課」「担当者区分」の3列で結合されていた。A列だけ解除しても、B列とC列の結合が残っていてフィルターが使えない。3列を1つずつ処理するのは面倒だったので、配列で対象列を管理するようにした。これで何列結合されていても1回の実行で済む。
文字列の表記ゆれ(全角半角、株式会社と(株)など)も同時に直したい場合は、セルの文字列を一括置換する方法 と組み合わせるとよい。
'============================================================
' ■ 結合だらけの帳票をデータベース形式に変換(実務版)
' → 複数列の結合を一括解除
' → 解除後の空白セルに値を下方向フィル
' → 処理前の確認+件数報告
'============================================================
Sub 結合帳票をDB形式に変換する()
'--- ★書き換えポイント ---
Dim targetSheet As String
targetSheet = "報告" '← 対象シート名
Dim startRow As Long
startRow = 2 '← データ開始行(ヘッダーの次)
'--- 結合を解除する列の配列(必要に応じて追加)
Dim targetCols As Variant
targetCols = Array("A", "B") '← 結合されている列を指定
'--- ★ここまで ---
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(targetSheet)
On Error GoTo 0
If ws Is Nothing Then
MsgBox "シート「" & targetSheet & "」が見つかりません。", vbExclamation
Exit Sub
End If
'--- 最終行を取得(A列基準)
' 結合列と異なる列(データが1行ずつ入っている列)を
' 基準にするとより正確に取得できる
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
If lastRow < startRow Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- 確認ダイアログ
If MsgBox("シート「" & targetSheet & "」の結合を解除し、" & vbCrLf & _
"データベース形式に変換します。" & vbCrLf & _
"対象列: " & Join(targetCols, ", ") & vbCrLf & _
"対象行: " & startRow & " 〜 " & lastRow & " 行" & vbCrLf & vbCrLf & _
"よろしいですか?", vbYesNo + vbQuestion) = vbNo Then
Exit Sub
End If
'--- 高速化設定
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
On Error GoTo ErrHandler
Dim colIdx As Long
Dim r As Long
Dim mergeVal As Variant
Dim mergeCount As Long
mergeCount = 0
'--- 列ごとにループ
For colIdx = LBound(targetCols) To UBound(targetCols)
Dim col As String
col = targetCols(colIdx)
r = startRow
Do While r <= lastRow
Dim targetCell As Range
Set targetCell = ws.Range(col & r)
If targetCell.MergeCells Then
'--- 結合セルの値を保持
mergeVal = targetCell.MergeArea.Cells(1, 1).Value
'--- 結合範囲の行数を取得
Dim mergeRows As Long
mergeRows = targetCell.MergeArea.Rows.Count
'--- 結合を解除
targetCell.MergeArea.UnMerge
'--- 空白セルに値をフィル
Dim fillRow As Long
For fillRow = r To r + mergeRows - 1
If ws.Range(col & fillRow).Value = "" Then
ws.Range(col & fillRow).Value = mergeVal
End If
Next fillRow
mergeCount = mergeCount + 1
r = r + mergeRows
Else
r = r + 1
End If
Loop
Next colIdx
CleanUp:
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox mergeCount & " 箇所の結合を解除し、値をフィルしました。" & vbCrLf & _
"対象シート: " & targetSheet, vbInformation
Exit Sub
ErrHandler:
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "エラーが発生しました: " & Err.Description, vbExclamation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
targetSheet |
対象シート名 | "報告" |
startRow |
データ開始行 | 2 |
targetCols |
結合を解除する列の配列 | Array("A", "B") |
列を追加する場合: targetCols = Array("A", "B", "C") のように配列に列名を追加するだけ。
コードの流れ
- 対象シート・列・開始行を設定: シート名と対象列を配列で管理する
- シートの存在確認: 指定シートが見つからない場合はエラーメッセージで終了する
- 最終行取得とデータ有無チェック: データがない場合は処理しない
- 確認ダイアログ: 対象列・行数を表示し、Yes/Noで確認してから実行する
- 高速化設定:
ScreenUpdatingとCalculationを制御して処理速度を上げる - 列ごとにループ: 外側のループで列、内側のDo Whileループで行を処理する
- 結合検出→値保持→解除→フィル:
MergeAreaで結合範囲を取得し、値を保持してから解除、空白セルに値をフィルする - エラーハンドリング: エラー発生時も
ScreenUpdatingとCalculationを確実に復帰する - 完了報告: 解除した結合の箇所数を表示する
全シートの結合を一括解除したい場合は 複数シートに同じ処理を一括実行 と組み合わせる。For Each ws In ThisWorkbook.Worksheets でシートをループすればOK。
—
よくある落とし穴5選
1. 結合を解除したらデータが消えた
原因: 結合セルの値は左上セルにのみ保持されている。UnMerge で解除すると、2行目以降は空白になる。これはExcelの仕様。
自分も最初は基本版のコードだけ使って、結合解除後に空白だらけになって焦った。報告書のA列「部署」が全部空白になって、上司に提出する直前に気づいた。
対策: 応用版または実務版のコードを使い、解除前に値を保持して空白セルにフィルする。基本版は「結合をなくすだけ」の用途に限定する。
2. 特定の列だけ解除したのに他の列の結合が残っている
原因: A列だけ解除しても、B列やC列の結合は別に管理されている。セル結合は範囲ごとに独立しているため、列を個別に指定する必要がある。
対策: 実務版のように targetCols = Array("A", "B", "C") で対象列をすべて指定する。シート全体を解除したい場合は ws.Cells.UnMerge を使う。
3. 結合解除後にフィルターで正しく絞り込めない
原因: 値フィルをせずに結合を解除しただけだと、2行目以降が空白のまま。フィルターで「営業」を選んでも1行しか表示されない。
対策: 応用版または実務版で値フィルまでセットで処理する。結合解除だけでは不十分。
4. 処理が遅い(結合が数百箇所ある)
原因: 結合セル1つずつをループで検出・解除しているため、結合箇所が多いシートでは時間がかかる。画面の再描画と数式の再計算が都度走ると、さらに遅くなる。
対策: 実務版のように Application.ScreenUpdating = False と Application.Calculation = xlCalculationManual で高速化する。数千箇所の結合でも数秒で完了する。
5. 横方向の結合(列方向)が解除されない
原因: 応用版・実務版のコードは縦方向(行方向)の結合と値フィルに対応している。横方向の結合(例: B2:D2が結合)は UnMerge で解除されるが、値の横方向フィルは含まれていない。
対策: 横方向のフィルが必要な場合は、行と列を入れ替えてループするコードに書き換える。または、基本版でシート全体の結合を解除してから、手動で値を横方向にコピーする。
VBAでセル結合を解除したら値が消えるときの対処法
「結合を解除したら2行目以降のセルが空白になった」という場合、これはExcelの仕様で正常な動作だ。結合セルは左上のセルにだけ値が入っており、解除すると残りのセルは空白になる。解除後に空白セルを上方向のセル値でフィルする処理をコードに入れれば、全行にデータが入った状態にできる。
VBAで結合解除のマクロが途中でエラーになるときの対処法
「一部の結合セルでエラーが出て止まる」という場合、原因はシート保護がかかっているか、結合範囲の一部が非表示行にかかっていることだ。ws.Unprotect でシート保護を解除し、ws.Rows.Hidden = False で全行を表示してからマクロを実行すれば安定する。
—
FAQ
Q1: 結合を解除した後、元に戻せるか?
VBAで実行した操作はCtrl+Zで戻せないことがある。必ずバックアップを取ってから実行する。バックアップの取り方は「事前準備」セクションを参照。
Q2: 特定の列だけ結合を解除したい場合は?
応用版の targetCol = "A" を変更するか、実務版の targetCols = Array("B", "C") で対象列を指定する。シート全体ではなく列単位で制御できる。
Q3: 結合セルがどこにあるか事前に確認したい
手動で確認する場合は、Excelの「ホーム」→「検索と選択」→「検索」→「オプション」→「書式」→「配置」タブの「セルを結合する」にチェック →「すべて検索」で一覧表示できる。VBAでは MergeCells プロパティでループして判定する。
Q4: 結合解除後に空白行を削除したい
空白行・空白セルを一括で削除する方法 を参照。結合解除 → 値フィル → 空白行削除の順番で処理するのがおすすめ。
Q5: 複数ファイルの結合を一括解除したい
ファイルをループで開いて処理する方法を使う。複数Excelファイルを1つに統合 のファイルループ部分を応用し、各ファイルに対して結合解除マクロを実行する。
Q6: 結合セルがあると最終行の取得がおかしくなることはある?
結合セルがA列にある場合、Cells.End(xlUp).Row は結合範囲の先頭行を返す場合がある。実務版ではA列基準で最終行を取得しているが、結合列と異なる列(データが1行ずつ入っている列)を基準にするとより正確。
—
まとめ
この記事で、セル結合を一括解除してデータを整形する方法がわかった。
- 基本版:
Cells.UnMergeでシート全体の結合を一括解除(値フィルなし) - 応用版: 結合解除+空白セルに値を下方向フィル(1列対応)
- 実務版: 複数列の結合を一括解除+値フィル+確認ダイアログ+高速化
重要なのは以下の3点:
- バックアップを取ってから実行する(結合解除はCtrl+Zで戻せないことがある)
- 解除だけでは不十分、値フィルまでセットで処理する(空白セルが残るとフィルターやVLOOKUPが使えない)
- 対象列を正しく指定する(列ごとに結合が独立しているため、すべての結合列を指定する)
関連記事
- セルの書式を一括変更する方法 — 結合解除後に書式が崩れた場合の整形に
- 空白行・空白セルを一括で削除する方法 — 結合解除後に不要な空白行を削除する
- セルの文字列を一括置換する方法 — 結合解除後のデータの表記ゆれを修正する
—
次にやりたくなること
- 空白行・空白セルを一括で削除する方法: 結合解除後に残った空白行を一括削除してデータをさらに整理する
- セルの文字列を一括置換する方法: 結合解除後のデータで全角半角や表記ゆれを一括修正する
- セルの書式を一括変更する方法: 結合解除で崩れた書式を一括で整え直したい場合に
- 重複データを一括削除して一意のリストを作る方法: 結合解除+値フィル後に重複を除去してクリーンなリストを作りたい場合に
- 複数条件でデータを抽出してまとめる方法: 結合解除でデータベース形式になった表をAutoFilterで自由に抽出したい場合に
—
セル結合の解除は、受け取ったExcelを「使えるデータ」に変える第一歩。まずは基本版でUnMergeの動きを確認して、応用版で値フィルの威力を体験してみてほしい。


コメント