Discussione:
VBA: Eliminare righe doppie (o triple o quadruple) ed incollarle in un altro foglio
(troppo vecchio per rispondere)
draleo
2016-03-28 08:57:32 UTC
Permalink
Nel foglio 1 ho un elenco di 6 colonne (Nome,Cognome,CodFiscale,articolo,Data1,data2)
Ho la necessità di eliminare da questo foglio (ed incollarle nel foglio2) tutte le righe che hanno lo stesso CodFiscale e lo stesso articolo (cioè quelle che nelle colonne CodFiscale e articolo hanno gli stessi dati)
Ho provato da solo , ma non viene bene. Qualcuno può aiutarmi ?
Grazie
draleo
Vittorio
2016-03-28 14:11:29 UTC
Permalink
<Nel foglio 1 ho un elenco di 6 colonne
(Nome,Cognome,CodFiscale,articolo,Data1,data2)
<Ho la necessità di eliminare da questo foglio (ed incollarle nel foglio2)
tutte le righe che hanno lo stesso CodFiscale e lo stesso articolo (cioè
quelle che nelle colonne CodFiscale e articolo hanno gli stessi <dati)

Prova questa sub, da copiare nel codice del foglio1 (clic dx nella sua
linguetta e scegliere Visualizza Codice ) :

Sub FindCpy()
Dim lw As Long
Dim i As Integer
Dim sh As Worksheet
Set sh = Sheets("Foglio1")
lw = sh.Range("A" & Rows.Count).End(xlUp).Row
Sheets("Foglio2").Cells.ClearContents
For i = 2 To lw
If Application.CountIfs(Range("C" & i & ":C" & lw), Range("C" &
i).Text, Range("D" & i & ":D" & lw), Range("D" & i).Text) > 1 Then
sh.Rows(i).EntireRow.Copy
Sheets("Foglio2").Range("A65536").End(xlUp).Offset(1,
0).PasteSpecial xlPasteValuesAndNumberFormats
End If
Next i
Sheets("Foglio1").Columns("A:F").RemoveDuplicates Columns:=Array(3, 4)

End Sub
casanmaner
2016-03-28 18:55:16 UTC
Permalink
Se ho interpretato bene quello che hai scritto e le successive integrazioni prova questa procedura (non lo dici ma suppongo che i "record" siano consecutivi o almento per ogni riga di record ci sia almeno un campo con un dato):

Sub Test()
Dim Wb As Workbook: Set Wb = ThisWorkbook
Dim WsO As Worksheet: Set WsO = Wb.Worksheets("Foglio1")
Dim rngO As Range: Set rngO = WsO.Range("A5")
Dim WsD As Worksheet: Set WsD = Wb.Worksheets("Foglio2")
Dim rngD As Range: Set rngD = WsD.Range("A5")
rngD.CurrentRegion.ClearContents
With rngO.CurrentRegion
.Copy rngD
.RemoveDuplicates Columns:=Array(3, 4), Header:=xlYes
End With
End Sub
draleo
2016-03-28 19:52:53 UTC
Permalink
Post by casanmaner
Sub Test()
Dim Wb As Workbook: Set Wb = ThisWorkbook
Dim WsO As Worksheet: Set WsO = Wb.Worksheets("Foglio1")
Dim rngO As Range: Set rngO = WsO.Range("A5")
Dim WsD As Worksheet: Set WsD = Wb.Worksheets("Foglio2")
Dim rngD As Range: Set rngD = WsD.Range("A5")
rngD.CurrentRegion.ClearContents
With rngO.CurrentRegion
.Copy rngD
.RemoveDuplicates Columns:=Array(3, 4), Header:=xlYes
End With
End Sub
grazie, ma anche questa funziona diversamente da come vorrei.
Nel foglio2 (destinazione) vengono copiate tutte le righe del foglio1(origine)(mentre io vorrei che fossero copiate SOLO le righe in cui si ripete la stessa accoppiata (codfiscale e articolo)più di una volta. Inoltre al termine della procedura , 1 riga per ciascuna coppia multipla (o terzina o quartina), rimane nel Foglio1 (mentre io vorrei che fossero tutte trasferite al foglio2.
Evidentemente L'istruzione
.RemoveDuplicates Columns:=Array(3, 4), Header:=xlYes
fa rimanere in situ una riga
draleo
draleo
2016-03-28 20:02:59 UTC
Permalink
Mi spiego meglio, Per es
se la riga
Mario Rossi MRORSSI61C12216C articolo225412
è presente 3 volte nel foglio1, tutte 3 le righe devono essere inviate al foglio2 ed eliminate dal foglio1.
Mentre se è presente 1 sola volta , non viene toccato niente
draleo
Post by draleo
Post by casanmaner
Sub Test()
Dim Wb As Workbook: Set Wb = ThisWorkbook
Dim WsO As Worksheet: Set WsO = Wb.Worksheets("Foglio1")
Dim rngO As Range: Set rngO = WsO.Range("A5")
Dim WsD As Worksheet: Set WsD = Wb.Worksheets("Foglio2")
Dim rngD As Range: Set rngD = WsD.Range("A5")
rngD.CurrentRegion.ClearContents
With rngO.CurrentRegion
.Copy rngD
.RemoveDuplicates Columns:=Array(3, 4), Header:=xlYes
End With
End Sub
grazie, ma anche questa funziona diversamente da come vorrei.
Nel foglio2 (destinazione) vengono copiate tutte le righe del foglio1(origine)(mentre io vorrei che fossero copiate SOLO le righe in cui si ripete la stessa accoppiata (codfiscale e articolo)più di una volta. Inoltre al termine della procedura , 1 riga per ciascuna coppia multipla (o terzina o quartina), rimane nel Foglio1 (mentre io vorrei che fossero tutte trasferite al foglio2.
Evidentemente L'istruzione
.RemoveDuplicates Columns:=Array(3, 4), Header:=xlYes
fa rimanere in situ una riga
draleo
Norman Jones
2016-03-28 15:13:42 UTC
Permalink
Ciao Draleo,
Post by draleo
Nel foglio 1 ho un elenco di 6 colonne (Nome,Cognome,CodFiscale,
Post by draleo
articolo,Data1,data2)
Ho la necessità di eliminare da questo foglio (ed incollarle nel
foglio2) tutte le righe che hanno lo stesso CodFiscale e lo stesso
articolo (cioè quelle che nelle colonne CodFiscale e articolo hanno
gli stessi dati)
Ho provato da solo , ma non viene bene. Qualcuno può aiutarmi ?
Io ho interpretato la tua domanda in modo diverso di Vittorio.

Pertanto, a patto che la mia interpretazione sia giusta, in un modulo
standard prova qualcosa del genere:
'=========>>
Option Explicit

'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant
Dim LRow As Long, UB As Long
Dim i As Long, j As Long, k As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica

Set WB = ThisWorkbook

With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With

With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A2:F" & LRow)
End With

arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 2)

For i = LBound(arrIn, 1) To UBound(arrIn, 1)
If UCase(arrIn(i, 3)) = UCase(arrIn(i, 4)) Then
k = k + 1
ReDim Preserve arrOut(1 To UB, 1 To k)
For j = 1 To UB
arrOut(j, k) = arrIn(i, j)
Next j
End If
Next i

If CBool(k) Then
On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With

With destSH
.UsedRange.Offset(1).ClearContents
.Range("A1").Resize(1, UB).Value = arrHeaders
.Range("A2").Resize(k, UB).Value =
Application.Transpose(arrOut)
End With
End If

XIT:
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub

'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If

On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========

Potresti scaricare il mio file di prova, Draleo20160328.xlsm a:
https://www.dropbox.com/s/ybfo0teqbsd2rer/Draleo20160328.xlsm?dl=0





===
Regards,
Norman
Norman Jones
2016-03-28 15:51:51 UTC
Permalink
Ciao Draleo,

Nel mio codice, avevo dimenticato la cancellazione delle righe di
interesse sul Foglio1!

Quindi, sostituisci il codice precedente vcon la seguente versione:

'=========>>
Option Explicit

'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant, arrDelete() As Variant
Dim sRows As String
Dim LRow As Long, UB As Long
Dim i As Long, j As Long, k As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica

Set WB = ThisWorkbook

With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With

With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A2:F" & LRow)
End With

arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 2)

For i = LBound(arrIn, 1) To UBound(arrIn, 1)
If UCase(arrIn(i, 3)) = UCase(arrIn(i, 4)) Then
k = k + 1
ReDim Preserve arrOut(1 To UB, 1 To k)
For j = 1 To UB
arrOut(j, k) = arrIn(i, j)
Next j
ReDim Preserve arrDelete(1 To k)
arrDelete(k) = i + 1 & ":" & i + 1
End If
Next i

If CBool(k) Then
On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With

With destSH
.UsedRange.Offset(1).ClearContents
.Range("A1").Resize(1, UB).Value = arrHeaders
.Range("A2").Resize(k, UB).Value = _
Application.Transpose(arrOut)
End With

sRows = Join(arrDelete, ",")
Intersect(srcRng, srcSH.Range(sRows)).Delete Shift:=xlUp
End If

XIT:
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub

'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If

On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========

Ho aggiornato il mio file di prova, Draleo20160328.xlsm a:
https://www.dropbox.com/s/ybfo0teqbsd2rer/Draleo20160328.xlsm?dl=0




===
Regards,
Norman
draleo
2016-03-28 16:13:16 UTC
Permalink
1) Soluzione di Norman. Chiedo scusa,ma Sicuramente mi sono espresso male: dovrebbero essere copiate sul foglio2(e poi eliminate dall'elenco del foglio1) TUTTE le righe in cui la coppia (codice fiscale e l'articolo) si ripetono 2-3 o più volte. La procedura di Norman invece copia ed elimina le righe in cui il codice fiscale è uguale all'articolo. Ma questo non si verifica mai (infatti la procedura di Norman non esegue alcuna azione).
2)Procedura di Vittorio: funziona , ma ha 2 problemi: Non tutte le righe doppie o triple vengono copiate: le copia tutte meno una (cioè se erano presenti 3 doppioni, ne copia solo 2;una rimane sempre nel foglio origine).Inoltre l'ulytima istruzione:
Sheets("Foglio1").Columns("A:F").RemoveDuplicates Columns:=Array(3, 4)
non va bene: scompagina i dati. Per colpa mia , che mi ero dimenticato di dire che i miei dati nel foglio1 di origine partono dalla riga 6 (nella riga 5 ci sono le intestazioni)
draleo
Vittorio
2016-03-28 20:14:28 UTC
Permalink
<2)Procedura di Vittorio: funziona , ma ha 2 problemi: Non tutte le righe
doppie o triple vengono copiate:


prova questa :


Sub FindCpy()
Dim lw As Long
Dim i As Integer
Dim SH As Worksheet
Dim ult As Long


Set SH = Sheets("Foglio1")
lw = SH.Range("A" & Rows.Count).End(xlUp).Row
Sheets("Foglio2").Cells.ClearContents
For i = 6 To lw
If Application.CountIfs(Range("C" & i & ":C" & lw), Range("C" &
i).Text, Range("D" & i & ":D" & lw), Range("D" & i).Text) > 1 Then

SH.Rows(i).EntireRow.Copy
Sheets("Foglio2").Range("A65536").End(xlUp).Offset(1,
0).PasteSpecial xlPasteValuesAndNumberFormats

End If
Next i
Sheets("Foglio1").Range("A6:F10000").RemoveDuplicates Columns:=Array(3,
4)

ult = Sheets("Foglio2").Range("A" & Rows.Count).End(xlUp).Row
For j = 6 To lw
For k = 2 To ult
If (Worksheets("Foglio1").Cells(j, 3).Value =
Worksheets("Foglio2").Cells(k, 3).Value And _
Worksheets("Foglio1").Cells(j, 4).Value =
Worksheets("Foglio2").Cells(k, 4).Value) Then
Worksheets("Foglio1").Rows(j).Delete

End If
Next k
Next j

End Sub
Norman Jones
2016-03-28 20:29:03 UTC
Permalink
Ciao Draleo,

Come hai notato, avevo capito male la tua domanda. Ora che credo di aver
meglio capito iltuo obiettivo, prova qualcosa del genere:

'=========>>
Option Explicit

'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant, arrDelete() As Variant
Dim oDic As Object
Dim sStr As String, bStsr As String, sRows As String
Dim LRow As Long, UB As Long, UB2 As Long
Dim iCtr As Long
Dim i As Long, j As Long, k As Long
Dim p As Long, q As Long, r As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica

Set WB = ThisWorkbook
Set oDic = CreateObject("Scripting.Dictionary")
oDic.CompareMode = 1 '\\ TextCompare

With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With

With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A2:F" & LRow)
End With

arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 1)
UB2 = UBound(arrIn, 2)

For i = LBound(arrIn, 1) To UB
For j = i + 1 To UB
If UCase(arrIn(i, 3)) = UCase(arrIn(j, 3)) _
And UCase(arrIn(j, 4)) = UCase(arrIn(i, 4)) Then
With oDic
If Not .exists(i + 1) Then
.Add Key:=i + 1, Item:=vbNullString
End If
If Not .exists(j + 1) Then
.Add Key:=j + 1, Item:=vbNullString
End If
End With
End If
Next j
Next i
iCtr = oDic.Count
If CBool(iCtr) Then
ReDim arrOut(1 To iCtr, 1 To UB2)
arrDelete = SortedList(oDic.keys)

For k = 1 To iCtr
For p = 1 To UB2
arrOut(k, p) = arrIn(arrDelete(k) - 1, p)
Next p
Next k
' On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With

With destSH
.UsedRange.Offset(1).ClearContents
.Range("A1").Resize(1, UB2).Value = arrHeaders
.Range("A2").Resize(k - 1, UB2).Value = arrOut
End With

Dim myUnion As Range
For q = LBound(arrDelete) To UBound(arrDelete)
If myUnion Is Nothing Then
Set myUnion = srcSH.Rows(arrDelete(q))
Else
Set myUnion = Union(myUnion, srcSH.Rows(arrDelete(q)))
End If
Next q

Set myUnion = Intersect(myUnion, srcRng)
myUnion.Delete Shift:=xlUp
End If

XIT:
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub

'--------->>
Public Function SortedList(V As Variant)
Dim oSortedList As Object
Dim arrOut() As Variant
Dim vVal As Variant
Dim i As Long

Set oSortedList = CreateObject("System.Collections.Sortedlist")
With oSortedList
For i = LBound(V) To UBound(V)
vVal = V(i)
If Not vVal = vbNullString Then
If Not .ContainsKey(vVal) Then
.Add Key:=CLng(vVal), Value:=i
End If
End If
Next i

ReDim arrOut(1 To .Count)
For i = 0 To .Count - 1
arrOut(i + 1) = .GetKey(i)
Next i
End With
SortedList = arrOut
End Function

'--------->>
'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If

On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========

Troverai il mio file di prova Draleo#2_20160328.xlsm a:
https://www.dropbox.com/s/djnjb833y27lbfl/Draleo%232_20160328.xlsm?dl=0




===
Regards,
Norman
Norman Jones
2016-03-28 21:09:42 UTC
Permalink
Ciao Draleo,

Rileggendo il tuo ultimo post, se la tua intenzione fosse che solo la
seconda e le succesive istanze dovrebbero essere copiate sul Foglio2 e
cancellate sul Foglio1, basterebbe commentare le seguente righe del mio
codice con un apostrofo iniziale:

' If Not .exists(i + 1) Then
' .Add Key:=i + 1, Item:=vbNullString
' End If




===
Regards,
Norman
draleo
2016-03-28 21:57:13 UTC
Permalink
Sia la soluzione di Vittorio che quella di Norman funzionano a metà:
1) Quella di Norman copia perfettamente nel foglio2 Tutte le righe che riportano la stessa accoppiata codFiscale-articolo. Ma le stesse non vengono eliminate nel Foglio1 (cosa che invece per me è indispensabile)
2)all'inverso quella di Vittorio, elimina dal foglio1 TUTTE le righe che riportano la stessa accoppiata codFiscale-articolo; ma NON le copia TUTTE nel foglio2 (ne copia solo alcune; per es : se nel foglio1,le righe da cancellare di Mario Rossi sono 3,queste vengono tutte cancellate nel foglio1, ma nel foglio2 ne viene copiata una sola riga con Mario rossi)
draleo
Norman Jones
2016-03-28 22:24:25 UTC
Permalink
Post by draleo
1) Quella di Norman copia perfettamente nel foglio2 Tutte le righe
che riportano la stessa accoppiata codFiscale-articolo. Ma le stesse
non vengono eliminate nel Foglio1 (cosa che invece per me è
indispensabile)
Secondo le mie prove, le righe di interesse venono cancellate sul
Foglio1 con il mio codice. Quindi, ti consiglio di riprovare il mio file
di prova:
Draleo#2_20160328.xlsm a:
https://www.dropbox.com/s/djnjb833y27lbfl/Draleo%232_20160328.xlsm?dl=0




===
Regards,
Norman
Norman Jones
2016-03-29 03:19:12 UTC
Permalink
Post by Norman Jones
Secondo le mie prove, le righe di interesse venono cancellate
Secondo le mie prove, le righe di interesse vengono cancellate





===
Regards,
Norman
draleo
2016-03-29 14:19:12 UTC
Permalink
Post by Norman Jones
Post by Norman Jones
Secondo le mie prove, le righe di interesse venono cancellate
Secondo le mie prove, le righe di interesse vengono cancellate
===
Regards,
Norman
In effetti sul tuo file scaricato da dropbox, tutto funziona alla perfezione. Ma poiché nel mio file i dati, sia nel foglio1 che nel foglio2,iniziano dalla riga 5 (intestazioni) ho cambiato i riferimenti in questo modo
With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
'Set srcRng = .Range("A2:F" & LRow)'modificata in
Set srcRng = .Range("A6:F" & LRow)
End With
.............
With destSH
.UsedRange.Offset(1).ClearContents
'.Range("A1").Resize(1, UB2).Value = arrHeaders 'modificata in
.Range("A5").Resize(1, UB2).Value = arrHeaders
'.Range("A2").Resize(k - 1, UB2).Value = arrOut 'modificata in
.Range("A6").Resize(1, UB2).Value = arrHeaders
End With

Evidentemente ho sbagliato-o dimenticato- qualcosa.... Ma Cosa ho sbagliato ?
Chiedo venia, ma il tuo codice non è proprio per principianti...
draleo
Norman Jones
2016-03-29 14:59:03 UTC
Permalink
Ciao Draleo,
Post by draleo
Post by Norman Jones
Post by Norman Jones
Secondo le mie prove, le righe di interesse venono cancellate
Secondo le mie prove, le righe di interesse vengono cancellate
===
Regards,
Norman
In effetti sul tuo file scaricato da dropbox, tutto funziona alla perfezione.
Ma poiché nel mio file i dati, sia nel foglio1 che nel foglio2,iniziano dalla
? riga 5 (intestazioni) ho cambiato i riferimenti in questo modo
Post by draleo
With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
'Set srcRng = .Range("A2:F" & LRow)'modificata in
Set srcRng = .Range("A6:F" & LRow)
End With
.............
With destSH
.UsedRange.Offset(1).ClearContents
'.Range("A1").Resize(1, UB2).Value = arrHeaders 'modificata in
.Range("A5").Resize(1, UB2).Value = arrHeaders
'.Range("A2").Resize(k - 1, UB2).Value = arrOut 'modificata in
.Range("A6").Resize(1, UB2).Value = arrHeaders
End With
Evidentemente ho sbagliato-o dimenticato- qualcosa.... Ma Cosa ho sbagliato ?
Chiedo venia, ma il tuo codice non è proprio per principianti...
Per quanto riguarda il tuo file nel quale la prima riga dei dati e' la
riga 6, prova la seguente modifica molto leggera del mio codice:
'=========>>
Option Explicit

'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant, arrDelete() As Variant
Dim oDic As Object
Dim sStr As String, bStsr As String, sRows As String
Dim LRow As Long, UB As Long, UB2 As Long
Dim iCtr As Long
Dim I As Long, j As Long, k As Long
Dim p As Long, q As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica
Const iPrimaRiga As Long = 6 '<<=== Modifica

Set WB = ThisWorkbook
Set oDic = CreateObject("Scripting.Dictionary")
oDic.CompareMode = 1 '\\ TextCompare

With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With

With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A" & iPrimaRiga & ":F" & LRow)
End With

arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 1)
UB2 = UBound(arrIn, 2)

For I = LBound(arrIn, 1) To UB
For j = I + 1 To UB
If UCase(arrIn(I, 3)) = UCase(arrIn(j, 3)) _
And UCase(arrIn(j, 4)) = UCase(arrIn(I, 4)) Then
With oDic
If Not .exists(I + 1) Then
.Add Key:=I + 1, Item:=vbNullString
End If
If Not .exists(j + 1) Then
.Add Key:=j + 1, Item:=vbNullString
End If
End With
End If
Next j
Next I
iCtr = oDic.Count
If CBool(iCtr) Then
ReDim arrOut(1 To iCtr, 1 To UB2)
arrDelete = SortedList(oDic.keys)

For k = 1 To iCtr
For p = 1 To UB2
arrOut(k, p) = arrIn(arrDelete(k) - 1, p)
Next p
Next k

On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With

With destSH
.UsedRange.Offset(1).ClearContents
.Range("A" & iPrimaRiga).Resize(1, UB2).Value = arrHeaders
.Range("A" & iPrimaRiga + 1).Resize(k - 1, UB2).Value = arrOut
End With

Dim myUnion As Range
For q = LBound(arrDelete) To UBound(arrDelete)
If myUnion Is Nothing Then
Set myUnion = srcSH.Rows(arrDelete(q))
Else
Set myUnion = Union(myUnion, srcSH.Rows(arrDelete(q)))
End If
Next q

Set myUnion = Intersect(myUnion, srcRng)
myUnion.Delete Shift:=xlUp
End If

XIT:
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub

'--------->>
Public Function SortedList(V As Variant)
Dim oSortedList As Object
Dim arrOut() As Variant
Dim vVal As Variant
Dim I As Long

Set oSortedList = CreateObject("System.Collections.Sortedlist")
With oSortedList
For I = LBound(V) To UBound(V)
vVal = V(I)
If Not vVal = vbNullString Then
If Not .ContainsKey(vVal) Then
.Add Key:=CLng(vVal), Value:=I
End If
End If
Next I

ReDim arrOut(1 To .Count)
For I = 0 To .Count - 1
arrOut(I + 1) = .GetKey(I)
Next I
End With
SortedList = arrOut
End Function

'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If

On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========


Potresti scaricare il tuo file aggiornato Draleo20160329.xlsm a:
https://www.dropbox.com/s/vxodt81ejtetnyn/Draleo20160329.xlsm?dl=0





===
Regards,
Norman
Vittorio
2016-03-29 19:03:52 UTC
Permalink
<<2)all'inverso quella di Vittorio, elimina dal foglio1 TUTTE le righe che
riportano la stessa accoppiata codFiscale-articolo; ma NON le copia TUTTE
nel foglio2

prova quest'altra(ho aggiunto solo due riga dopo il then ):


Sub FindCpy()
Dim lw As Long
Dim i As Integer
Dim SH As Worksheet
Dim ult As Long


Set SH = Sheets("Foglio1")
lw = SH.Range("A" & Rows.Count).End(xlUp).Row
Sheets("Foglio2").Cells.ClearContents
For i = 6 To lw
If Application.CountIfs(Range("C" & i & ":C" & lw), Range("C" &
i).Text, Range("D" & i & ":D" & lw), Range("D" & i).Text) > 1 Then

SH.Rows(i).EntireRow.Copy
Sheets("Foglio2").Range("A65536").End(xlUp).Offset(1,
0).PasteSpecial xlPasteValuesAndNumberFormats

End If
Next i
Sheets("Foglio1").Range("A6:F10000").RemoveDuplicates Columns:=Array(3,
4)

ult = Sheets("Foglio2").Range("A" & Rows.Count).End(xlUp).Row
For j = 6 To lw
For k = 2 To ult
If (Worksheets("Foglio1").Cells(j, 3).Value =
Worksheets("Foglio2").Cells(k, 3).Value And _
Worksheets("Foglio1").Cells(j, 4).Value =
Worksheets("Foglio2").Cells(k, 4).Value) Then

Worksheets("Foglio1").Rows(j).EntireRow.Copy
Sheets("Foglio2").Range("A65536").End(xlUp).Offset(1,
0).PasteSpecial xlPasteValuesAndNumberFormats
Worksheets("Foglio1").Rows(j).Delete

End If
Next k
Next j

End Sub
draleo
2016-03-29 20:36:13 UTC
Permalink
Si. Ora la procedura di Vittorio funziona bene in tutte le sue parti. Purtroppo invece la procedura di Norman, anche dopo la sua ultima modifica, continua a presentare lo stesso problema: non elimina sul foglio1(o ne elimina solo alcune), le righe che sono uguali nell' accoppiata codFiscale-articolo. Queste vengono perfettamente copiate nel foglio2, ma NON vengono eliminate dal foglio sorgente. Se i dati partono dalla riga 2, tutto funziona alla perfezione; ma se sposto i dati alla riga 6, il problema si verifica. Probabilmente trattasi di una banalità da correggere,ma le mie competenze in materia sono così scarse, che non mi permettono di provare a mettere le mani in argomenti così complessi come gli array ,le matrici o Scripting dictionary ecc.
Grazie mille ad entrambi
draleo
Norman Jones
2016-03-30 08:49:44 UTC
Permalink
Ciao Draleo,
Post by draleo
Purtroppo invece la procedura di Norman, anche dopo la sua ultima modifica,
continua a presentare lo stesso problema: non elimina sul foglio1(o ne elimina
solo alcune), le righe che sono uguali nell' accoppiata codFiscale-articolo..
Queste vengono perfettamente copiate nel foglio2, ma NON vengono eliminate dal
foglio sorgente. Se i dati partono dalla riga 2, tutto funziona alla perfezione;
ma se sposto i dati alla riga 6, il problema si verifica. Probabilmente trattasi
di una banalità da correggere,ma le mie competenze in materia sono così scarse,
che non mi permettono di provare a mettere le mani in argomenti così complessi
come gli array ,le matrici o Scripting dictionary ecc.
Per quanto riguarda l'eliminazione delle righe sul Foglio1, il codice,
quando addattato per i tuoi dati, mancava l'inserimento della costante
iPrimaRiga nella parte del codice interessata. Ho aggiornato il file e
il codice diventa:

'=========>>
Option Explicit

'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant, arrDelete() As Variant
Dim oDic As Object
Dim sStr As String, bStsr As String, sRows As String
Dim LRow As Long, UB As Long, UB2 As Long
Dim iCtr As Long
Dim i As Long, j As Long, k As Long
Dim p As Long, q As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica
Const iPrimaRiga As Long = 6 '<<==== Modifica

Set WB = ThisWorkbook
Set oDic = CreateObject("Scripting.Dictionary")
oDic.CompareMode = 1 '\\ TextCompare

With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With

With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A" & iPrimaRiga & ":F" & LRow)
End With

arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 1)
UB2 = UBound(arrIn, 2)

For i = LBound(arrIn, 1) To UB
For j = i + 1 To UB
If UCase(arrIn(i, 3)) = UCase(arrIn(j, 3)) _
And UCase(arrIn(j, 4)) = UCase(arrIn(i, 4)) Then
With oDic
If Not .exists(j + iPrimaRiga - 1) Then
.Add Key:=j + iPrimaRiga - 1, Item:=vbNullString
End If
End With
End If
Next j
Next i
iCtr = oDic.Count
If CBool(iCtr) Then
ReDim arrOut(1 To iCtr, 1 To UB2)
arrDelete = SortedList(oDic.keys)

For k = 1 To iCtr
For p = 1 To UB2
arrOut(k, p) = arrIn(arrDelete(k) - iPrimaRiga + 1, p)
Next p
Next k

On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With

With destSH
.UsedRange.Offset(1).ClearContents
.Range("A" & iPrimaRiga).Resize(1, UB2).Value = arrHeaders
.Range("A" & iPrimaRiga + 1). _
Resize(k - 1, UB2).Value = arrOut
End With

Dim myUnion As Range
For q = LBound(arrDelete) To UBound(arrDelete)
If myUnion Is Nothing Then
Set myUnion = srcSH.Rows(arrDelete(q))
Else
Set myUnion = Union(myUnion, srcSH.Rows(arrDelete(q)))
End If
Next q

Set myUnion = Intersect(myUnion, srcRng)
myUnion.Delete Shift:=xlUp
End If

XIT:
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub

'--------->>
Public Function SortedList(V As Variant)
Dim oSortedList As Object
Dim arrOut() As Variant
Dim vVal As Variant
Dim i As Long

Set oSortedList = CreateObject("System.Collections.Sortedlist")
With oSortedList
For i = LBound(V) To UBound(V)
vVal = V(i)
If Not vVal = vbNullString Then
If Not .ContainsKey(vVal) Then
.Add Key:=CLng(vVal), Value:=i
End If
End If
Next i

ReDim arrOut(1 To .Count)
For i = 0 To .Count - 1
arrOut(i + 1) = .GetKey(i)
Next i
End With
SortedList = arrOut
End Function

'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If

On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========

Ho aggiornato il mio file di prova su DropBox.

Per quanto riguarda i tuoi commenti a proposito della complessità del
codice, ciò è dovuto principalmente al fatto che io ho intenzionalmente
scelto di eseguire tutte manipolazione dei dati in memoria anziché
sfruttare strumenti speciali di Excel. La mia scelta è stata dettata da
una predilezione personale e il desiderio di accrescere l'efficienza di
esecuzione del codice.




===
Regards,
Norman
draleo
2016-03-30 13:12:00 UTC
Permalink
OK ! Ho aggiunto un paio di righe-riportate sotto- delle quali probabilmente ti eri scordato e senza le quali funzionava male. Ma Ora funziona molto bene. Per quanto riguarda i miei commenti alla tua procedura, non devono essere intesi in senso negativo . Anzi, è il contrario: I tuoi metodi sono sempre estremamenti veloci ed efficienti. Purtroppo , se occorre fare qualche modifica per adattarli a situazioni personali,i principianti come me faticano MOLTO a capirci qualcosa. Non dare perle ai porci (come dice il proverbio)! (e tra i porci mi ci metto in prima fila!)
Ancora grazie
draleo

For i = LBound(arrIn, 1) To UB
For j = i + 1 To UB
If UCase(arrIn(i, 3)) = UCase(arrIn(j, 3)) _
And UCase(arrIn(j, 4)) = UCase(arrIn(i, 4)) Then
With oDic
If Not .exists(i + iPrimaRiga - 1) Then 'AGGIUNTA
.Add Key:=i + iPrimaRiga - 1, Item:=vbNullString 'AGGIUNTA
End If 'AGGIUNTA
If Not .exists(j + iPrimaRiga - 1) Then
.Add Key:=j + iPrimaRiga - 1, Item:=vbNullString

End If
End With
End If
Next j

Next i
Post by Norman Jones
Per quanto riguarda l'eliminazione delle righe sul Foglio1, il codice,
quando addattato per i tuoi dati, mancava l'inserimento della costante
iPrimaRiga nella parte del codice interessata. Ho aggiornato il file e
'=========>>
Option Explicit
'--------->>
Public Sub Tester()
Dim WB As Workbook
Dim srcSH As Worksheet, destSH As Worksheet
Dim srcRng As Range, destRng As Range
Dim arrIn As Variant, arrOut() As Variant
Dim arrHeaders() As Variant, arrDelete() As Variant
Dim oDic As Object
Dim sStr As String, bStsr As String, sRows As String
Dim LRow As Long, UB As Long, UB2 As Long
Dim iCtr As Long
Dim i As Long, j As Long, k As Long
Dim p As Long, q As Long
Dim CalcMode As Long
Const sNomeFoglioDati As String = "Foglio1" '<<==== Modifica
Const sNomeFoglioDiCopia As String = "Foglio2" '<<==== Modifica
Const iPrimaRiga As Long = 6 '<<==== Modifica
Set WB = ThisWorkbook
Set oDic = CreateObject("Scripting.Dictionary")
oDic.CompareMode = 1 '\\ TextCompare
With WB
Set srcSH = WB.Sheets(sNomeFoglioDati)
Set destSH = .Sheets(sNomeFoglioDiCopia)
End With
With srcSH
LRow = LastRow(srcSH, .Columns("A:A"))
Set srcRng = .Range("A" & iPrimaRiga & ":F" & LRow)
End With
arrHeaders = srcRng.Rows(0).Value
arrIn = srcRng.Value
UB = UBound(arrIn, 1)
UB2 = UBound(arrIn, 2)
For i = LBound(arrIn, 1) To UB
For j = i + 1 To UB
If UCase(arrIn(i, 3)) = UCase(arrIn(j, 3)) _
And UCase(arrIn(j, 4)) = UCase(arrIn(i, 4)) Then
With oDic
If Not .exists(j + iPrimaRiga - 1) Then
.Add Key:=j + iPrimaRiga - 1, Item:=vbNullString
End If
End With
End If
Next j
Next i
iCtr = oDic.Count
If CBool(iCtr) Then
ReDim arrOut(1 To iCtr, 1 To UB2)
arrDelete = SortedList(oDic.keys)
For k = 1 To iCtr
For p = 1 To UB2
arrOut(k, p) = arrIn(arrDelete(k) - iPrimaRiga + 1, p)
Next p
Next k
On Error GoTo XIT
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
With destSH
.UsedRange.Offset(1).ClearContents
.Range("A" & iPrimaRiga).Resize(1, UB2).Value = arrHeaders
.Range("A" & iPrimaRiga + 1). _
Resize(k - 1, UB2).Value = arrOut
End With
Dim myUnion As Range
For q = LBound(arrDelete) To UBound(arrDelete)
If myUnion Is Nothing Then
Set myUnion = srcSH.Rows(arrDelete(q))
Else
Set myUnion = Union(myUnion, srcSH.Rows(arrDelete(q)))
End If
Next q
Set myUnion = Intersect(myUnion, srcRng)
myUnion.Delete Shift:=xlUp
End If
With Application
.Calculation = CalcMode
.ScreenUpdating = True
End With
End Sub
'--------->>
Public Function SortedList(V As Variant)
Dim oSortedList As Object
Dim arrOut() As Variant
Dim vVal As Variant
Dim i As Long
Set oSortedList = CreateObject("System.Collections.Sortedlist")
With oSortedList
For i = LBound(V) To UBound(V)
vVal = V(i)
If Not vVal = vbNullString Then
If Not .ContainsKey(vVal) Then
.Add Key:=CLng(vVal), Value:=i
End If
End If
Next i
ReDim arrOut(1 To .Count)
For i = 0 To .Count - 1
arrOut(i + 1) = .GetKey(i)
Next i
End With
SortedList = arrOut
End Function
'--------->>
Public Function LastRow(SH As Worksheet, _
Optional Rng As Range, _
Optional minRow As Long = 1)
If Rng Is Nothing Then
Set Rng = SH.Cells
End If
On Error Resume Next
LastRow = Rng.Find(What:="*", _
after:=Rng.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
If LastRow < minRow Then
LastRow = minRow
End If
End Function
'<<=========
Ho aggiornato il mio file di prova su DropBox.
Per quanto riguarda i tuoi commenti a proposito della complessità del
codice, ciò è dovuto principalmente al fatto che io ho intenzionalmente
scelto di eseguire tutte manipolazione dei dati in memoria anziché
sfruttare strumenti speciali di Excel. La mia scelta è stata dettata da
una predilezione personale e il desiderio di accrescere l'efficienza di
esecuzione del codice.
===
Regards,
Norman
Loading...