Reputation: 161
I expected the following macro to display 6 but it displays 8. I understand that this is because Union duplicates cells that overlap as do cells b1:b2 in my example:
Sub a()
Dim myRange As Range
Set myRange = Application.Union(Range("a1:b2"), Range("b1:b4"))
MsgBox myRange.Count
End Sub
I found this solution to the problem but I'm interested to know why this is the way Union works and if there is any other way to get around this besides writing a new function as suggested by the above link.
Upvotes: 4
Views: 705
Reputation: 199
hil,
The union method creates a range with n areas.
It is interesting that this Application.Union(Range("a1:c2"), Range("a1:c2"), Range("a1:c2"))
creates a single area. And in fact for the case where one of the ranges contains all the others entirely you will only get back the 1 area. eg Application.Union(Range("a1:f2"), Range("b2:d2"))
. Another interesting example is Application.Union(Range("a1:f2"), Range("b2:d3"), Range("d2:e3"))
this merged range(b2:e3) and created 2 areas.
A point to make at this point is that contiguous ranges have to be rectangular.
So Union will create the most efficient contiguous blocks of ranges, but there may still be some overlap.
CPearson's website has been around since the dawn of time, so it is very unlikely that you will find a better source for many problems. (I am not CPearson).
Regards Gareth
Upvotes: 1
Reputation: 51998
I find it somewhat pointless to speculate much about 20-year old closed-source design decisions, although it is interesting to note that the way that Excel-VBA handles Union
meshes with the way Excel treats multiple range selections in spreadsheet functions. In this:
the sum evaluates to 12 and not 10. Thus it seems likely that VBA's approach was an attempt to come up with a Range object that corresponds to how Excel itself treats overlapping selections. This would push back the design-decision to pre-VBA Excel.
If Union
doesn't do what you want, then you need to write a different function. Chip Pearson is an extremely good VBA programmer, so I would be surprised if there is any easy work-around that he missed. Your actual question discussed the count of the union. If that is what you want, you could write a smaller function:
Function UnionCount(A As Range, B As Range) As Long
Dim adjustment As Long
If Not Intersect(A, B) Is Nothing Then
adjustment = Intersect(A, B).Cells.Count
End If
UnionCount = Union(A, B).Cells.Count - adjustment
End Function
Then UnionCount(Range("A1:B2"), Range("B1:B4"))
evaluates to 6.
Upvotes: 0
Reputation: 9461
Yes, the Union operator is really more like a UNION ALL statement in SQL. Excel's Union operator does not return the distinct set of cells.
Upvotes: 0