Ciao Rob,
ho studiato :-) e fatto un po' di test sul solito archivio:
creare 25 file dal foglio di 21.760 righe con 25 valori di chiave
univoca, il file è depositato qui:
http://groups.google.it/group/excel_vba_free/web/SpacchettaInFile5.xls?hl=it
E' un po' cicciotto perche contiene i dati per la prova.
Le prove le ho ripetute per 3 volte per ogni function utilizzata ed i
tempi si sono sempre ripetuti uguali:
con la tua function UnionB()
che restituisce un range ma usa un ciclo for:
test in 36 secondi
con la mia function: Not_Intersect()
che restituisce un array di 2 stringhe:
test in 16 secondi
con la mia function: Not_IntersectR() che restituisce un range
ma non usa un ciclo for:
test in 17 secondi
Come temevo, il ciclo "for each cella" su un range esteso rallenta
decisamente l'esecuzione del programma (impiega il doppio delle
altre).
A proposito, hai dichiarato la variabile bol come statica, forse
perchè pensavi ad un uso ricorsivo della function, giusto?
Comunque nel file per il test lo dichiarata local.
Queste la parte di codice di SpacchettaInFile che contiene le uniche
differenze per le 3 chiamate alle function (deccomnetando quella da
testare e commentando le altre):
''**************************************
''UnionB -> excel.range
''**************************************
' ws.Range(aOrigine(j)(2)).EntireRow.Copy
Destination:=.Range(aOrigine(j)(2)).EntireRow
' unionB(.Range(srngDati), .Range(aOrigine(j)
(2))).EntireRow.Delete
''*****************************************
'**************************************
'Not_Intersect -> array() di 2 stringhe
'**************************************
' srngDif() = Not_Intersect(.Range(srngDati), .Range(aOrigine(j)
(2)))
' If srngDif(1) <> "" Then
' .Range(srngDif(1)).EntireRow.Delete
' End If
' If srngDif(0) <> "" Then
' .Range(srngDif(0)).EntireRow.Delete
' End If
' If (srngDif(0) & srngDif(1)) <> "" Then
' ws.Range(aOrigine(j)(2)).EntireRow.Copy
Destination:=.Range(sFirst)
' End If
'*****************************************
''**************************************
'' Not_intersectR -> excel.range
''**************************************
' ws.Range(aOrigine(j)(2)).EntireRow.Copy
Destination:=.Range(aOrigine(j)(2)).EntireRow
' Not_IntersectR(.Range(srngDati), .Range(aOrigine(j)
(2))).EntireRow.Delete
''**************************************
Queste le 3 function:
'***************
Function unionB(rng As Excel.Range, Brng As Excel.Range) _
As Excel.Range
'***************
Dim cella As Excel.Range
Dim irng As Excel.Range
Dim bol As Boolean
Set irng = Application.Intersect(rng, Brng)
If irng Is Nothing Then
Set unionB = Union(rng, Brng)
Exit Function
End If
If rng.Address = Brng.Address Then
Set unionB = Nothing
Set irng = Nothing
Exit Function
End If
For Each cella In Union(rng, Brng)
If Application.Intersect(irng, cella) Is Nothing Then
If bol = False Then
Set unionB = cella
bol = True
Else
Set unionB = Union(unionB, cella)
End If
End If
Next
Set irng = Nothing
End Function
'***************
Function Not_Intersect(RngBig As Range, RngSmall As Range) _
As String()
'***************
'***************
Function Not_IntersectR(RngBig As Range, RngSmall As Range) _
As Excel.Range
'***************
Dim srngBTop As String
Dim srngSTop As String
Dim srngBBtm As String
Dim srngSBtm As String
Dim sRng1Top As String
Dim sRng1Btm As String
Dim sRng2Top As String
Dim sRng2Btm As String
Dim nRowsB As Long
Dim nRowsS As Long
Dim nColsB As Long
Dim nColsS As Long
Dim sRet As String
nColsB = RngBig.Columns.Count
nColsS = RngSmall.Columns.Count
nRowsB = RngBig.Rows.Count
nRowsS = RngSmall.Rows.Count
srngBTop = RngBig.Cells(1, 1).Address
srngSTop = RngSmall.Cells(1, 1).Address
srngBBtm = RngBig.Cells(nRowsB, nColsB).Address
srngSBtm = RngSmall.Cells(nRowsS, nColsS).Address
If (RngBig.Column = RngSmall.Column) And _
(nRowsB >= nRowsS) And _
(nColsB = nColsS) And _
Not RngBig.Address = RngSmall.Address Then
sRng1Top = RngBig.Cells(1, 1).Address
sRng1Btm = RngSmall.Cells(1, nColsS).Offset(-1).Address
sRng2Top = RngSmall.Cells(nRowsS, 1).Offset(1).Address
sRng2Btm = RngBig.Cells(nRowsB, nColsB).Address
If srngBTop = srngSTop Then
sRet = sRng2Top & ":" & sRng2Btm
ElseIf srngBBtm = srngSBtm Then
sRet = sRng1Top & ":" & sRng1Btm
Else
sRet = sRng1Top & ":" & sRng1Btm & "," & sRng2Top & ":" &
sRng2Btm
End If
Set Not_IntersectR = Range(sRet)
Else
Set Not_IntersectR = Nothing
End If
End Function
'--------------------------
Bye!
Scossa