una todas tablas tabla para macro las hoja grafico dinamico dinamicas dinamica automaticamente actualizar vba excel-vba set theory range

vba - para - macro actualizar todas las tablas dinamicas de una hoja



Diferencia entre dos rangos (3)

Puedo encontrar muchas preguntas y ejemplos sobre los métodos VBA ''Union'' e ''Intersect'', pero no puedo encontrar mucho sobre el método ''Set Difference''. ¿Existe esto (que no sea mediante el uso de combinaciones de unión e intersección) ?.

Estoy tratando de encontrar una manera simple de obtener todo el rango1 sin incluir el rango1 que se superpone al rango2 sin conocer el tamaño o la forma de ninguno de los rangos.

Cualquier ayuda sería muy apreciada.

EDITAR.

Intento de solución donde rng1 es la sección roja y rng2 es la sección azul (se han depurado para comprobar si son correctos):

rng = SetDifference(rng, highlightedColumns) Function SetDifference(Rng1 As Range, Rng2 As Range) As Range On Error Resume Next If Application.Intersect(Rng1, Rng2).Address <> Rng2.Address Then Exit Function On Error GoTo 0 Dim aCell As Range For Each aCell In Rng1 Dim Result As Range If Application.Intersect(aCell, Rng2) Is Nothing Then Set Result = Union(Result, aCell) End If Next aCell Set SetDifference = Result End If End Function


^ Iterar por cada celda es muy lento para llamadas como

SetDifference (ActiveSheet.Cells, ActiveSheet.Range ("A1")) ''Todas las celdas excepto A1

Por lo tanto:

''(needed by the 2nd function) Public Function Union(ByRef rng1 As Range, _ ByRef rng2 As Range) As Range If rng1 Is Nothing Then Set Union = rng2 Exit Function End If If rng2 Is Nothing Then Set Union = rng1 Exit Function End If If Not rng1.Worksheet Is rng2.Worksheet Then Exit Function End If Set Union = Application.Union(rng1, rng2) End Function Public Function Complement(ByRef rng1 As Range, _ ByRef rng2 As Range) As Range Dim rngResult As Range Dim rngResultCopy As Range Dim rngIntersection As Range Dim rngArea1 As Range Dim rngArea2 As Range Dim lngTop As Long Dim lngLeft As Long Dim lngRight As Long Dim lngBottom As Long If rng1 Is Nothing Then Exit Function End If If rng2 Is Nothing Then Set Complement = rng1 Exit Function End If If Not rng1.Worksheet Is rng2.Worksheet Then Exit Function End If Set rngResult = rng1 For Each rngArea2 In rng2.Areas If rngResult Is Nothing Then Exit For End If Set rngResultCopy = rngResult Set rngResult = Nothing For Each rngArea1 In rngResultCopy.Areas Set rngIntersection = Application.Intersect(rngArea1, rngArea2) If rngIntersection Is Nothing Then Set rngResult = Union(rngResult, rngArea1) Else lngTop = rngIntersection.Row - rngArea1.Row lngLeft = rngIntersection.Column - rngArea1.Column lngRight = rngArea1.Column + rngArea1.Columns.Count - rngIntersection.Column - rngIntersection.Columns.Count lngBottom = rngArea1.Row + rngArea1.Rows.Count - rngIntersection.Row - rngIntersection.Rows.Count If lngTop > 0 Then Set rngResult = Union(rngResult, rngArea1.Resize(lngTop, rngArea1.Columns.Count)) End If If lngLeft > 0 Then Set rngResult = Union(rngResult, rngArea1.Resize(rngArea1.Rows.Count - lngTop - lngBottom, lngLeft).Offset(lngTop, 0)) End If If lngRight > 0 Then Set rngResult = Union(rngResult, rngArea1.Resize(rngArea1.Rows.Count - lngTop - lngBottom, lngRight).Offset(lngTop, rngArea1.Columns.Count - lngRight)) End If If lngBottom > 0 Then Set rngResult = Union(rngResult, rngArea1.Resize(lngBottom, rngArea1.Columns.Count).Offset(rngArea1.Rows.Count - lngBottom, 0)) End If End If Next rngArea1 Next rngArea2 Set Complement = rngResult End Function


Pruebe esta función después de haberla mejorado un poco:

Function SetDifference(Rng1 As Range, Rng2 As Range) As Range On Error Resume Next If Intersect(Rng1, Rng2) Is Nothing Then ''if there is no common area then we will set both areas as result Set SetDifference = Union(Rng1, Rng2) ''alternatively ''set SetDifference = Nothing Exit Function End If On Error GoTo 0 Dim aCell As Range For Each aCell In Rng1 Dim Result As Range If Application.Intersect(aCell, Rng2) Is Nothing Then If Result Is Nothing Then Set Result = aCell Else Set Result = Union(Result, aCell) End If End If Next aCell Set SetDifference = Result End Function

Recuerde llamarlo así:

Set Rng = SetDifference(Rng, highlightedColumns)


Cuando los rangos tienen ambas áreas, necesitará un enfoque diferente. No xlCellTypeConstants la idea central de este ejemplo y no recuerdo dónde encontré esta idea (usando xlCellTypeConstants ). Lo adapté para hacerlo funcionar para rangos con áreas:

'' Range operator that was missing Public Function rngDifference(rn1 As Range, rn2 As Range) As Range Dim rnAreaIntersect As Range, varFormulas As Variant Dim rnAreaS As Range, rnAreaR As Range, rnAreaDiff As Range Dim rnAreaModified As Range, rnOut As Range On Error Resume Next Set rngDifference = Nothing If rn1 Is Nothing Then Exit Function If rn2 Is Nothing Then Set rngDifference = rn1: Exit Function Set rnOut = Nothing For Each rnAreaS In rn1.Areas Set rnAreaModified = rnAreaS For Each rnAreaR In rn2.Areas Set rnAreaIntersect = Intersect(rnAreaModified, rnAreaR) If rnAreaIntersect Is Nothing Then Set rnAreaDiff = rnAreaModified Else '' there is interesection ''save varFormulas = rnAreaS.Formula rnAreaS.Value = 0: rnAreaIntersect.ClearContents If rnAreaS.Cells.Count = 1 Then Set rnAreaDiff = Intersect(rnAreaS.SpecialCells(xlCellTypeConstants), rnAreaS) Else Set rnAreaDiff = rnAreaS.SpecialCells(xlCellTypeConstants) End If ''restore rnAreaS.Formula = varFormulas End If If Not (rnAreaModified Is Nothing) Then Set rnAreaModified = Intersect(rnAreaModified, rnAreaDiff) End If Next If Not (rnAreaModified Is Nothing) Then If rnOut Is Nothing Then Set rnOut = rnAreaModified Else Set rnOut = Union(rnOut, rnAreaModified) End If End If Next Set rngDifference = rnOut End Function

Espero que esto ayude