【VBAリファレンス】【Excel VBA】連なる同じ値を自動結合!作業効率を劇的に改善するマクロ術

スポンサーリンク

こんにちは!Excel VBA講師の○○です。日々の業務でExcelを使っていると、「あ、また同じデータが連続してる…」なんて場面に遭遇しませんか?例えば、請求書や名簿、集計表などで、担当者名や部署名、商品名などが何行も同じ値で埋まっていること、ありますよね。

このような場合、手作業で一つ一つセルを結合していくのは、非常に手間がかかり、ミスも誘発しがちです。特にデータ量が多い場合は、その作業だけでかなりの時間を浪費してしまうことも。

そこで今回は、そんな悩みを解決するExcel VBAマクロをご紹介します!このマクロを使えば、連続して同じデータが入力されたセルを自動的に結合することができます。一度作成してしまえば、あとはワンクリックで効率化が図れるので、ぜひマスターしてあなたのExcel作業を劇的に改善しましょう!

### なぜ連続する同じデータを結合したいのか?

そもそも、なぜ私たちは連続する同じデータを結合したいのでしょうか?その理由はいくつか考えられます。

* **視覚的な分かりやすさの向上:** セルが結合されることで、同じデータが続いている範囲が塊として認識しやすくなります。これにより、表全体の構造が把握しやすくなり、データの意味合いを理解する助けとなります。
* **印刷時のレイアウト改善:** 印刷プレビューで確認すると、同じデータが繰り返されることで無駄なスペースができ、見栄えが悪くなることがあります。セル結合によって、よりスッキリとした印刷結果を得られます。
* **データ入力・編集作業の効率化:** 例えば、結合されたセルにデータを入力する際、最初のセルに入力すれば、結合されている範囲全体に適用されるため、入力の手間が省けます。また、後でデータを修正する際も、結合されたセルを一度編集すれば済むため、効率的です。
* **他のアプリケーションへのデータ転送:** 特定のフォーマットでデータをエクスポートする際、連続した同じデータを結合して出力する必要がある場合があります。VBAマクロを使えば、こうした作業も自動化できます。

もちろん、セル結合にはデメリットも存在します。例えば、並べ替えやフィルター処理が複雑になる場合があるため、データの利用目的に応じて適切に判断することが重要です。しかし、今回ご紹介するVBAマクロは、あくまで「連続して同じデータが入力されている」という限定的な状況で、視覚的な整理や印刷レイアウトの改善を目的とする場合に非常に有効です。

### VBAで連続する同じデータを結合する基本的な考え方

VBAで連続する同じデータを結合するには、基本的には以下のステップを踏みます。

1. **対象範囲の特定:** 結合したいデータが入力されている範囲を特定します。これは、特定の列を指定したり、現在選択されている範囲を対象としたり、あるいはシート全体を対象としたりすることができます。
2. **データの走査:** 特定した範囲の各セルを一行ずつ、あるいは一列ずつ順番に見ていきます。
3. **隣接セルとの比較:** 現在見ているセルと、その一つ下のセル(または隣のセル)の値を比較します。
4. **条件分岐と結合処理:**
* もし、現在のセルの値と一つ下のセルの値が同じであれば、一つ下のセルを結合対象とします。
* もし、値が異なる、または範囲の終端に達した場合は、それまで連続していた同じ値の範囲を結合します。
5. **繰り返し:** 上記の処理を範囲の最後まで繰り返します。

この基本的な考え方を元に、具体的なVBAコードを作成していきます。

### VBAコードの作成:初心者でもわかるステップ・バイ・ステップ解説

それでは、実際にVBAコードを作成していきましょう。今回は、特定の列(例えばA列)について、連続する同じデータを結合するマクロを作成します。

まず、ExcelでVBAエディタを開きます。`Alt` + `F11` キーを押すか、「開発」タブから「Visual Basic」をクリックして開いてください。
VBAエディタが開いたら、「挿入」メニューから「標準モジュール」を選択し、新しいモジュールを作成します。ここにコードを記述していきます。

Sub MergeSameDataInColumn()

Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim startRow As Long

‘ ★対象シートを設定します。必要に応じてシート名「Sheet1」を変更してください。
Set ws = ThisWorkbook.Sheets(“Sheet1”)

‘ ★対象列を設定します。ここではA列を対象とします。必要に応じて列番号を変更してください。(A=1, B=2, …)
Const TARGET_COLUMN As Long = 1

‘ 対象列の最終行を取得します。
‘ 終端から逆方向に検索することで、データが途中から詰まっていても正確に最終行を取得できます。
lastRow = ws.Cells(ws.Rows.Count, TARGET_COLUMN).End(xlUp).Row

‘ 最終行が1行しかない場合は、結合するデータがないため処理を終了します。
If lastRow < 2 Then MsgBox "結合対象となるデータがありません。", vbInformation Exit Sub End If ' 最初の行から最終行までループ処理を行います。 ' startRow は、結合を開始する行番号を保持します。 startRow = 1 For i = 1 To lastRow ' 現在の行と次の行の値を比較します。 ' もし、現在の行の値が次の行の値と異なる場合、または最終行に到達した場合、 ' その時点まで連続していた同じ値の範囲を結合します。 If ws.Cells(i, TARGET_COLUMN).Value <> ws.Cells(i + 1, TARGET_COLUMN).Value Or i = lastRow Then

‘ 結合する範囲を定義します。
‘ startRow から i 行目までが、同じ値が連続していた範囲です。
‘ ただし、結合する行数が1行の場合は結合処理は行いません。
If i > startRow Then
‘ 結合処理を実行します。
‘ ws.Range(ws.Cells(startRow, TARGET_COLUMN), ws.Cells(i, TARGET_COLUMN)).Merge
‘ Mergeメソッドは、結合後にセルの値が左上に集約されるため、
‘ 今回は、結合せずに、結合されるべき範囲の最初のセルにのみ値を残す、
‘ という操作(OffsetプロパティとClearContentsメソッドの組み合わせ)を行います。
‘ Mergeメソッドを使うと、後続の処理でエラーが発生しやすいため、
‘Mergeメソッドを使わずに、見た目上結合されたかのように見せる手法が一般的です。
‘ここでは、結合される範囲の2行目以降をクリアすることで、
‘あたかも結合されたかのように見せる処理を行います。
‘もし、本当にセルを結合したい場合は、上記のコメントアウトを解除してください。
ws.Range(ws.Cells(startRow + 1, TARGET_COLUMN), ws.Cells(i, TARGET_COLUMN)).ClearContents
End If

‘ 次の結合範囲の開始行を現在の行の次の行に設定します。
startRow = i + 1
End If

Next i

MsgBox “連続する同じデータの結合処理が完了しました。”, vbInformation

End Sub

#### コードの解説

1. **変数の宣言:**
* `ws As Worksheet`: 対象となるワークシートを格納する変数です。
* `lastRow As Long`: 対象列の最終行番号を格納する変数です。
* `i As Long`: ループ処理で使用するカウンタ変数です。
* `startRow As Long`: 連続する同じデータが始まる行番号を記録する変数です。

2. **対象シートの設定:**
* `Set ws = ThisWorkbook.Sheets(“Sheet1”)`: ここで、処理対象となるシート名を指定します。`”Sheet1″` の部分を、実際に操作したいシートの名前に変更してください。

3. **対象列の設定:**
* `Const TARGET_COLUMN As Long = 1`: ここで、処理対象の列を指定します。`1` はA列、`2` はB列、といった具合に列番号で指定します。必要に応じて変更してください。

4. **最終行の取得:**
* `lastRow = ws.Cells(ws.Rows.Count, TARGET_COLUMN).End(xlUp).Row`: 対象列のデータが入っている最終行を正確に取得します。`ws.Rows.Count` でシートの最大行数を取得し、そこから `End(xlUp)` でデータのある一番下のセルまで逆方向に移動して行番号を取得しています。これにより、データが途中で空欄になっている場合でも、正しく最終行を特定できます。

5. **データがない場合の処理:**
* `If lastRow < 2 Then ... Exit Sub`: 最終行が1行しかない場合、結合するデータがないため、メッセージを表示して処理を終了します。 6. **ループ処理:** * `startRow = 1`: 処理を開始する前に、最初の行を結合開始行として設定します。 * `For i = 1 To lastRow`: 1行目から最終行まで順番に処理を繰り返します。 * `If ws.Cells(i, TARGET_COLUMN).Value <> ws.Cells(i + 1, TARGET_COLUMN).Value Or i = lastRow Then`: ここが処理の核心部分です。
* `ws.Cells(i, TARGET_COLUMN).Value <> ws.Cells(i + 1, TARGET_COLUMN).Value`: 現在の行 (`i` 行目) の値と、一つ下の行 (`i + 1` 行目) の値を比較しています。
* `Or i = lastRow`: もし、現在の行が最終行 (`lastRow`) であれば、それまでの連続が終了したとみなします。
* この条件が真(値が異なる、または最終行)になった場合、`startRow` から `i` 行目までが同じ値の連続だったと判断し、結合処理を行います。

7. **結合処理(見た目上の結合):**
* `If i > startRow Then …`: `i` が `startRow` より大きい場合、つまり、結合する行が2行以上ある場合にのみ結合処理を実行します。
* `ws.Range(ws.Cells(startRow + 1, TARGET_COLUMN), ws.Cells(i, TARGET_COLUMN)).ClearContents`: この部分が、**実際のセル結合ではなく、見た目上結合されたように見せる処理**です。`Merge` メソッドを使って実際にセルを結合すると、後続の処理(例えば並べ替えやコピー&ペースト)で予期せぬエラーが発生することがあります。そのため、ここでは、結合されるべき範囲の2行目以降のセルの値をクリアすることで、あたかも結合されたかのように見せています。これにより、データが整理され、視覚的に分かりやすくなります。
* **もし、本当にセルを結合したい場合**は、`Merge` メソッドを使った行のコメントアウトを解除し、`ClearContents` の行をコメントアウトしてください。(ただし、`Merge` メソッドの使用は慎重に行うことをお勧めします。)

8. **次の結合開始行の設定:**
* `startRow = i + 1`: 次の連続するデータの開始行を、現在の行の次の行に設定します。

9. **完了メッセージ:**
* `MsgBox “連続する同じデータの結合処理が完了しました。”, vbInformation`: 処理が正常に完了したことをユーザーに通知します。

### マクロの実行方法

1. 作成したVBAコードを保存します。
2. Excelに戻り、`Alt` + `F8` キーを押して「マクロ」ダイアログボックスを開きます。
3. 実行したいマクロ名(ここでは `MergeSameDataInColumn`)を選択し、「実行」ボタンをクリックします。
4. 対象シートと対象列が正しく設定されていれば、指定した列で連続する同じデータが、見た目上結合された状態になります。

### より高度なカスタマイズ:応用編

今回ご紹介したマクロは基本的なものですが、さらに応用することで、より柔軟な処理が可能になります。

#### 1. 複数列を対象にする

もし、複数の列で連続する同じデータを結合したい場合は、ループ処理をネストさせるか、あるいは別々のマクロとして作成する方法が考えられます。例えば、A列とB列の値が両方とも同じ場合に結合したい、といったケースです。

Sub MergeSameDataInMultiColumn()

Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim startRow As Long

Set ws = ThisWorkbook.Sheets(“Sheet1”)
Const TARGET_COLUMN_A As Long = 1 ‘ A列
Const TARGET_COLUMN_B As Long = 2 ‘ B列

lastRow = ws.Cells(ws.Rows.Count, TARGET_COLUMN_A).End(xlUp).Row

If lastRow < 2 Then MsgBox "結合対象となるデータがありません。", vbInformation Exit Sub End If startRow = 1 For i = 1 To lastRow ' A列とB列の値が両方とも同じかどうかをチェック If ws.Cells(i, TARGET_COLUMN_A).Value <> ws.Cells(i + 1, TARGET_COLUMN_A).Value Or _
ws.Cells(i, TARGET_COLUMN_B).Value <> ws.Cells(i + 1, TARGET_COLUMN_B).Value Or _
i = lastRow Then

If i > startRow Then
‘ A列とB列の範囲をクリア(見た目上の結合)
ws.Range(ws.Cells(startRow + 1, TARGET_COLUMN_A), ws.Cells(i, TARGET_COLUMN_A)).ClearContents
ws.Range(ws.Cells(startRow + 1, TARGET_COLUMN_B), ws.Cells(i, TARGET_COLUMN_B)).ClearContents
End If
startRow = i + 1
End If

Next i

MsgBox “複数列の連続する同じデータの結合処理が完了しました。”, vbInformation

End Sub

この例では、A列とB列の値が**両方とも**同じ場合に連続していると判断し、両方の列で見た目上の結合を行います。条件を `Or` でつなげば、どちらかの列の値が異なれば結合を終了する、という処理になります。

#### 2. 選択範囲を対象にする

常に特定の列を対象とするのではなく、ユーザーが選択した範囲を対象にしたい場合もあります。その場合は、`Selection` オブジェクトを使用します。

Sub MergeSameDataInSelection()

Dim selectedRange As Range
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim startRow As Long
Dim col As Long

‘ 選択されている範囲を取得します。
On Error Resume Next ‘ 範囲が選択されていない場合のエラーを回避
Set selectedRange = Selection
On Error GoTo 0

‘ 範囲が選択されていない、または複数のシートにまたがっている場合は処理を終了します。
If selectedRange Is Nothing Then
MsgBox “結合したい範囲を選択してください。”, vbExclamation
Exit Sub
End If
If selectedRange.Areas.Count > 1 Then
MsgBox “連続した単一の範囲を選択してください。”, vbExclamation
Exit Sub
End If
If selectedRange.Worksheet.Name <> ThisWorkbook.ActiveSheet.Name Then
MsgBox “同じシート内の範囲を選択してください。”, vbExclamation
Exit Sub
End If

Set ws = selectedRange.Worksheet

‘ 選択範囲の最終行を取得します。
lastRow = selectedRange.Rows.Count + selectedRange.Row – 1

‘ 選択範囲の各列に対して処理を行います。
For col = 1 To selectedRange.Columns.Count
startRow = selectedRange.Row ‘ 各列の開始行をセット
For i = selectedRange.Row To lastRow
‘ 現在の行と次の行の値を比較します。
If ws.Cells(i, selectedRange.Column + col – 1).Value <> ws.Cells(i + 1, selectedRange.Column + col – 1).Value Or i = lastRow Then
If i > startRow Then
‘ 結合する範囲の2行目以降をクリア(見た目上の結合)
ws.Range(ws.Cells(startRow + 1, selectedRange.Column + col – 1), ws.Cells(i, selectedRange.Column + col – 1)).ClearContents
End If
startRow = i + 1
End If
Next i
Next col

MsgBox “選択範囲の連続する同じデータの結合処理が完了しました。”, vbInformation

End Sub

このマクロでは、ユーザーが選択した範囲全体を対象に、各列ごとに連続する同じデータを結合します。`Selection` オブジェクトや `Areas` プロパティ、`Column` プロパティなどを活用しています。

#### 3. Mergeメソッドを実際に使用する場合の注意点

もし、どうしても実際のセル結合を行いたい場合は、`Range.Merge` メソッドを使用します。ただし、前述の通り、MergeメソッドはExcelの内部的なデータ構造を変更するため、後続の処理に影響を与える可能性があります。

* **並べ替えやフィルター:** Mergeされたセルは、単一のセルとして扱われにくくなるため、並べ替えやフィルターが期待通りに動作しないことがあります。
* **コピー&ペースト:** Mergeされたセルをコピーして別の場所に貼り付ける際、意図しない結果になることがあります。
* **VBAでの参照:** MergeされたセルをVBAで参照する際に、値が左上のセルに集約されるため、注意が必要です。

もしMergeメソッドを使用する場合は、以下のコードのように記述します。

‘ 結合処理を実行する例(Mergeメソッドを使用)
‘ If i > startRow Then
‘ ws.Range(ws.Cells(startRow, TARGET_COLUMN), ws.Cells(i, TARGET_COLUMN)).Merge
‘ End If

この場合、`ClearContents` の処理は不要になります。しかし、多くの場合、**見た目上の結合(ClearContentsで空白にする)で十分なケースが多い**ため、まずはそちらの方法を試すことをお勧めします。

### まとめ:VBAで作業効率を劇的にアップ!

今回は、Excel VBAを使って、連続して同じデータが入力されたセルを自動的に結合(または見た目上結合)する方法について解説しました。

* **手作業の煩雑さからの解放:** 大量のデータを手作業で処理する時間を大幅に削減できます。
* **ミスの削減:** 人為的なミスを防ぎ、データの正確性を高めます。
* **視覚的な分かりやすさの向上:** 表の見栄えを整え、データの理解を助けます。

今回ご紹介したコードは、基本的なものですが、これをベースに応用することで、あなたのExcel作業はさらに効率化されるはずです。ぜひ、ご自身の業務に合わせてカスタマイズし、活用してみてください。

Excel VBAは、ちょっとしたコードで日々の作業を劇的に改善できる、非常に強力なツールです。これからも、皆さんのExcel作業がより快適になるような情報をお届けしていきますので、どうぞお楽しみに!

もし、コードの解説や、さらに具体的なカスタマイズについてご不明な点がありましたら、お気軽にコメントやお問い合わせください。

それでは、次回のブログでお会いしましょう!

タイトルとURLをコピーしました