merge cells vertically
This code checks the cells of each row and merges cells vertically, if they have the same value (also formulas whith same resulting value!):
Sub MergeCellsVertically()
Dim ws As Worksheet
Dim currentRng As Range
Dim usedRows As Long, usedColumns As Long
Dim currentRow As Long, currentColumn As Long
Set ws = ActiveSheet
usedRows = ws.Cells.Find(What:="*", After:=ws.Cells(1), LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
usedColumns = ws.Cells.Find(What:="*", After:=ws.Cells(1), LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Application.DisplayAlerts = False
For currentColumn = 1 To usedColumns
For currentRow = usedRows To 2 Step -1
Set currentRng = ws.Cells(currentRow, currentColumn)
If currentRng.Value <> "" Then
If currentRng.Value = currentRng.Offset(-1, 0).Value Then
currentRng.Offset(-1, 0).Resize(2, 1).Merge
End If
End If
Next currentRow
Next currentColumn
Application.DisplayAlerts = True
Set currentRng = Nothing
Set ws = Nothing
End Sub
As your example shows a non-uniform structure, this may be a good solution. If you just want to decide by one row, which neighbor-cells to merge, keep in mind, that only the content of the upper left cell of a merged area "survives".
If you want to address the content of a merged area, then currentRng.MergeArea.Cells(1)
will always represent the first cell of the merged area, where the content is.
unmerge
Sub UnmergeCells()
Dim ws As Worksheet
Dim usedRows As Long, usedColumns As Long
Dim currentRng As Range, tempRng As Range
Dim currentRow As Long, currentColumn As Long
Set ws = ActiveSheet
usedRows = ws.UsedRange.Cells(1).Row + ws.UsedRange.Rows.Count - 1
usedColumns = ws.UsedRange.Cells(1).Column + ws.UsedRange.Columns.Count - 1
For currentRow = 1 To usedRows
For currentColumn = 1 To usedColumns
Set currentRng = ws.Cells(currentRow, currentColumn)
If currentRng.MergeCells Then
Set tempRng = currentRng.MergeArea
currentRng.MergeArea.UnMerge
currentRng.Copy tempRng
End If
Next currentColumn
Next currentRow
Set tempRng = Nothing
Set currentRng = Nothing
Set ws = Nothing
End Sub
As the Find
function is bad in finding the last used column or row in merged cells, I use the standard UsedRange
instead. Be aware, that unmerged (duplicated) formulas may be unexpected.