0

I have cells containing duplicate values that i want to merge quickly. The table looks like this:

Table showing duplicate cells

Sub MergeCells()
Application.DisplayAlerts = False
Dim n As Name
Dim fc As FormatCondition
Dim Rng As Range, R As Range
Dim lRow As Long
Dim I&, J&
Dim arr As Variant

ReDim arr(1 To 1) As Variant

With ThisWorkbook.Sheets("tst")
    Set Rng = .Range("A2:D11")
    lRow = Rng.End(xlDown).Row

    For J = 1 To 4
        For I = lRow To 2 Step -1   'last row to 2nd row
            If Trim(UCase(.Cells(I, J))) = Trim(UCase(.Cells(I - 1, J))) Then
                Set R = .Range(.Cells(I, J), .Cells(I - 1, J))
                arr(UBound(arr)) = R.Address
                ReDim Preserve arr(1 To UBound(arr) + 1)
            End If
        Next I
    Next J
    ReDim Preserve arr(1 To UBound(arr) - 1)

    Set R = .Range(Join(arr, ","))
    'MsgBox R.Areas.Count
    'R.Select
    'R.MergeCells = True
    With R
        .Merge
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlCenter
    End With

    Stop
End With

Application.DisplayAlerts = True
End Sub

The duplicate cells ranges could be disjointed or non-adjacent cells. I want a way to quickly identify such duplicate ranges and merge them without using a For loop. [Don't know, but think there could be a fastest innovative way without loops probably using some combination of Excel array formulae and VBA code, to select and merge duplicate cell ranges.]

BTW the above code works fine till it shoots up the following error at line .Merge.

Error Description

EDIT This is a snapshot of the Watch window showing the arr content as well as R.Address.

Watch Window

OUTPUT: Don't need any selections, this is just for demonstration purpose:

selected cells the disjointed ranges

Output should look like this:

Final Output

EDIT... Suppose the duplicate values were same across the rows? So only duplicate columns values to be merged. There has to be an quick, innovative way to do this merge.

Edited Input image

Final Output Image: Final edited output image

Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
sifar
  • 1,086
  • 1
  • 17
  • 43
  • 2
    Please show your desired outcome. What do you mean by `merge`? Merge to me means A2:D2 become one cell. – Scott Craner Aug 17 '17 at 14:13
  • What is `arr` when it errors? (Btw merging cells is bad news.) – SJR Aug 17 '17 at 14:16
  • This will require many loops. It will not be possible any other way. – Scott Craner Aug 17 '17 at 14:37
  • @ScottCraner i have edited the post and added the output image. – sifar Aug 17 '17 at 14:38
  • @SJR the error is not because of the Array 'arr' but i think because the mergings are not happening in one shot somehow on the disjointed ranges. – sifar Aug 17 '17 at 14:38
  • @ScottCraner, the 2 nested loops are sufficient if i want to merge each range within the loop. But i want to merge all these ranges in one go, once the loops end. that is why i am collecting the address of ranges. – sifar Aug 17 '17 at 14:41
  • 1
    @ScottCraner - that doesn't appear to be the case based on a quick test. – SJR Aug 17 '17 at 14:49
  • Why on earth do you care so much about loops? That's an irrational constraint that will lead you to a sub-optimal solution. – Graham Aug 17 '17 at 14:54
  • Okay with `MsgBox R.Areas.Count` I assume you got something? – Scott Craner Aug 17 '17 at 14:54
  • If range you're trying to merge is not SQUARE it will "eat" excess cell. If it isn't the issue, you can (or can you?) sort columns ascending per each column and then merge them one by one. – AntiDrondert Aug 17 '17 at 15:01
  • yes, in 1st example i think got 15 or 16 Areas. – sifar Aug 17 '17 at 15:02
  • see my updated post for new images. BTW i manually selected the different ranges and then merged it. Later when i unmerged the cells again and dran the code, it did not shoot up an error and merged the ranges in one go! STRANGE! – sifar Aug 17 '17 at 15:03
  • The error occurs if a cell is selected twice at the same time (eg. if ranges overlap) when you run `.merge`. Instead of `.merge` run a `.select` and see if some of the ranges overlap or cells are selected twice (you can see that if some of the selected cells are shaded darker than others). – Pᴇʜ Aug 17 '17 at 15:09
  • Now, i am getting "Application defined error" on **Set R = .Range(Join(arr, ","))**. – sifar Aug 17 '17 at 15:13
  • "Now" means after changing what? You need to be much more specific in your comments. – Pᴇʜ Aug 17 '17 at 15:19
  • @Peh, see the latest edits (images) in my post. This is showing up for 2nd table. The 1st table ranges somehow merge without any errors. – sifar Aug 17 '17 at 15:25
  • Here is the link [link](https://drive.google.com/open?id=0ByraEKowSDpWVk5uR19XOHVpdVE) to the sample file containing the VBA code and tables. – sifar Aug 17 '17 at 15:31

1 Answers1

1

The issue is that your code can only find 2 adjacent cells and is not looking for a third one with this code: Set R = .Range(.Cells(I, J), .Cells(I - 1, J))

After the first loop it adds these 2 cells
enter image description here

After another loop it adds the next 2 cells
enter image description here

And this results in an overlapping
enter image description here
which you can see at the darker shading of the selection.

I just edited some part of your code with comments, so you can see how it could be done. But I'm sure there is still space for improvements.

Sub MergeCellsNew()
    Application.DisplayAlerts = False
    Dim n As Name
    Dim fc As FormatCondition
    Dim Rng As Range, R As Range
    Dim lRow As Long
    Dim I&, J&
    Dim arr As Variant

    ReDim arr(1 To 1) As Variant

    With ThisWorkbook.Sheets("tst")
        Set Rng = .Range("A2:D11")
        lRow = Rng.End(xlDown).Row

        For J = 1 To 4
            I = 2 'I = Rng.Row   to automatically start at the first row of Rng
            Do While I <= lRow
                Set R = .Cells(I, J) 'remember start cell

                'run this loop as long as duplicates found next to the start cell
                Do While Trim(UCase(.Cells(I, J))) = Trim(UCase(.Cells(I + 1, J)))
                    Set R = R.Resize(R.Rows.Count + 1) 'and resize R + 1
                    I = I + 1
                Loop

                'now if R is bigger than one cell there are duplicates we want to add to the arr
                'this way single cells are not added to the arr
                If R.Rows.Count > 1 Then
                    arr(UBound(arr)) = R.Address
                    ReDim Preserve arr(1 To UBound(arr) + 1)
                End If
                I = I + 1
            Loop
        Next J
        ReDim Preserve arr(1 To UBound(arr) - 1)

        Set R = .Range(Join(arr, ","))
        With R
            .Merge
            .HorizontalAlignment = xlCenter
            .VerticalAlignment = xlCenter
        End With

        Stop
    End With

    Application.DisplayAlerts = True
End Sub
Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
  • i ran your code on both the tables. The 1st table - no errors. The 2nd table with range **.Range("A16:D29")** - I again got same **Application defined error** on **Set R =.Range(Join(arr, ","))** – sifar Aug 17 '17 at 16:06
  • of course if you change `Set Rng = .Range("A2:D11")` then `I` which is the first row of `Rng` has to be changed accordingly. You can automate this by using `I = Rng.Row` instead of `I = 2`. – Pᴇʜ Aug 18 '17 at 06:05
  • I have adjusted `Set Rng = .Range("A2:I11")` to be `Set Rng = .Range("A2:I12061")` and `I = 2` to `I = Rng.Row` but still get the same error sifar has @PEH – FreeSoftwareServers Dec 10 '19 at 19:54