1
votes

Rechercher les valeurs en double dans la colonne et déplacer la ou les lignes entières vers une nouvelle feuille

J'ai de l'expérience avec JS et Python, mais je suis encore relativement nouveau dans mon parcours VBA. J'ai écrit quelques scripts réussis jusqu'à présent, mais j'ai vraiment du mal avec ça.

Voici un exemple simplifié de mon problème:

J'en ai besoin pour que chacune de mes feuilles ait une valeur unique pour colonne C.Cependant, je ne veux pas supprimer les extras, je veux les conserver, les copier / coller dans une nouvelle feuille, puis j'espère pouvoir réexécuter la macro, dans cette feuille, jusqu'à ce que j'aie un certain nombre de feuilles, chacune avec uniquement des valeurs uniques dans la colonne C.

So:

Feuille 1

+-----------+------------------------+---------+
| Name (A)  |         Email  (B)     |Animal(C)|
+-----------+------------------------+---------+
| Katelynn  | Katelynn@barnyard.com  | Pig     |
| Antonette | Antonette@barnyard.com | Cat     |
| Kristian  | Kristian@barnyard.com  | Horse   |
| Ellamae   | Ellamae@barnyard.com   | Spider  |
+-----------+------------------------+---------+

ressemblerait à quelque chose comme ceci:

Feuille 1

+-----------+------------------------+---------+
| Name (A)  |         Email  (B)     |Animal(C)|
+-----------+------------------------+---------+
| Kanisha   | Kanisha@barnyard.com   | Pig     |
| Renea     | Renea@barnyard.com     | Cat     |
| Jamika    | Jamika@barnyard.com    | Horse   |
| Catherina | Catherina@barnyard.com | Spider  |
+-----------+------------------------+---------+

Feuille 2 p >

+-----------+------------------------+---------+
| Name (A)  |         Email  (B)     |Animal(C)|
+-----------+------------------------+---------+
| Kanisha   | Kanisha@barnyard.com   | Pig     |
| Katelynn  | Katelynn@barnyard.com  | Pig     |
| Renea     | Renea@barnyard.com     | Cat     |
| Antonette | Antonette@barnyard.com | Cat     |
| Jamika    | Jamika@barnyard.com    | Horse   |
| Kristian  | Kristian@barnyard.com  | Horse   |
| Catherina | Catherina@barnyard.com | Spider  |
| Ellamae   | Ellamae@barnyard.com   | Spider  |
+-----------+------------------------+---------+

à quel point je pourrais, espérons-le, exécuter la même macro sur Sheet 2 , générant ainsi:

Sheet 2

+-----------+------------------------+---------+
| Name (A)  |         Email  (B)     |Animal(C)|
+-----------+------------------------+---------+
| Lauretta  | Lauretta@barnyard.com  | Pig     |
| Irwin     | Irwin@barnyard.com     | Cat     |
| Leigh     | Leigh@barnyard.com     | Donkey  |
| Eloy      | Eloy@barnyard.com      | Horse   |
| Elaina    | Elaina@barnyard.com    | Spider  |
+-----------+------------------------+---------+

Feuille 3

+-----------+------------------------+---------+
| Name (A)  |         Email  (B)     |Animal(C)|
+-----------+------------------------+---------+
| Lauretta  | Lauretta@barnyard.com  | Pig     |
| Kanisha   | Kanisha@barnyard.com   | Pig     |
| Katelynn  | Katelynn@barnyard.com  | Pig     |
| Irwin     | Irwin@barnyard.com     | Cat     |
| Renea     | Renea@barnyard.com     | Cat     |
| Antonette | Antonette@barnyard.com | Cat     |
| Leigh     | Leigh@barnyard.com     | Donkey  |
| Eloy      | Eloy@barnyard.com      | Horse   |
| Jamika    | Jamika@barnyard.com    | Horse   |
| Kristian  | Kristian@barnyard.com  | Horse   |
| Elaina    | Elaina@barnyard.com    | Spider  |
| Catherina | Catherina@barnyard.com | Spider  |
| Ellamae   | Ellamae@barnyard.com   | Spider  |
+-----------+------------------------+---------+

J'espère que cela a du sens. J'ai passé des semaines dessus, pour gagner de la place, je soumettrai ci-dessous certaines de mes abominations chimériques que j'ai récoltées à divers endroits, qui ne fonctionnent pas: (J'ai vraiment essayé!

Aucune aide du tout serait très apprécié! :)


2 commentaires

La colonne C est-elle triée / groupée par ordre de nom de l'animal (comme indiqué dans la question)? Sinon, pourrait-il être trié de cette façon?


Faites une boucle sur les lignes et utilisez (par exemple) un dictionnaire de script pour suivre le nombre d'instances de chaque animal que vous avez vu jusqu'à présent - lorsque vous traitez chaque ligne si ce nombre est> 1, coupez la ligne de la feuille suivante de n- 1 (la deuxième instance va à la feuille2, la troisième à la feuille3, etc.) Ajoutez des feuilles si nécessaire.


3 Réponses :


0
votes

abominations chimériques (ne posez pas de questions sur les noms de macro lol facepalm

Option Explicit
Sub Brian()
Dim lw As Long
Dim i As Integer
Dim sh As Worksheet

Set sh = Sheets("Dup")
lw = Range("A" & Rows.Count).End(xlUp).Row

    For i = 1 To lw 'Find duplicates from the list.
       If Application.CountIf(Range("A" & i & ":A" & lw), Range("A" & i).Text) > 1 Then
            Range("B" & i).Value = 1
        End If
    Next i

    Range("A1:B10000").AutoFilter , Field:=2, Criteria1:=1
    Range("C2", Range("C65536").End(xlUp)).EntireRow.Copy
    sh.Range("C65536").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
    Selection.AutoFilter
End Sub

autre:

Sub bowietwo()
'Updateby Extendoffice
    Dim xRgS As Range
    Dim xRgD As Range
    Dim i As Long, J As Long
    On Error Resume Next
    Set xRgS = Application.InputBox("Please select the column:", "Hi! John says:", Selection.Address, , , , , 8)
    If xRgS Is Nothing Then Exit Sub
    Set xRgD = Application.InputBox("Please select a desitination cell:", "Hi! John says:", , , , , , 8)
    If xRgD Is Nothing Then Exit Sub
    xRows = xRgS.Rows.Count
    J = 0
    For i = xRows To 1 Step -1
        If Application.WorksheetFunction.CountIf(xRgS, xRgS(i)) > 1 Then
            xRgS(i).EntireRow.Copy xRgD.Offset(J, 0)
            xRgS(i).EntireRow.Delete
            J = J + 1
        End If
    Next
End Sub
un autre:
Sub bowie()
    Dim xRgS As Range
    Dim xRgD As Range
    Dim i As Long, J As Long
    On Error Resume Next
    Set xRgS = Range("C:C")
    If xRgS Is Nothing Then Exit Sub
    Set xRgD = Worksheets(2)
    If xRgD Is Nothing Then Exit Sub
    xRows = xRgS.Rows.Count
    J = 0
    For i = xRows To 1 Step -1
        If Application.WorksheetFunction.CountIf(xRgS, xRgS(i)) > 1 Then
            xRgS(i).EntireRow.Copy xRgD.Offset(J, 0)
            xRgS(i).EntireRow.Delete
            J = J + 1
        End If
    Next
End Sub

celui-ci ^^ sorta fonctionne mais plante tout de suite, ma liste d'animaux est dans les dizaines de milliers

Option Explicit
Sub pinky()
Dim lw As Long
Dim i As Integer
Dim sh As Worksheet

Set sh = Sheets("Sheet1")`
lw = Range("A" & Rows.Count).End(xlUp).Row`

For i = 1 To lw 'Find duplicates from the list.
       If Application.CountIf(Range("C" & i & ":C" & lw), Range("C" & i).Text) > 1 Then
       Range("C2", Range("C65536").End(xlUp)).EntireRow.Copy
       sh.Range(Worksheets(2)).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
    Selection.AutoFilter

           ' Range("C" & i).Value = 1
        End If
    Next i    

End Sub

donc, pinky, bowie, bowietwo et brian se sont révélés inutiles. Je sais qu'il doit y avoir une manière simple et élégante de le faire.


1 commentaires

Ce serait mieux dans le cadre de votre question - n'hésitez pas à la modifier à nouveau dans la question. Sinon, c'est un peu trompeur - on dirait que vous avez répondu à votre propre question, ce qui ne semble pas être votre intention. L'espace de réponse est vraiment juste pour les réponses.



0
votes

Unique Magic

Téléchargement du classeur (Dropbox)

Le code

Sub UniqueMagic()

    Const cFR As Long = 1             ' Header Row Number
    Const cFC As Variant = "A"        ' First Column Letter/Number
    Const cColU As Variant = "C"      ' Unique Column Letter/Number
    Const cSheet As String = "Sheet"  ' Worksheet Pattern

    Dim ws As Worksheet   ' Source (Unique) Worksheet
    Dim wsK As Worksheet  ' Keep Worksheet
    Dim rng As Range      ' LucH - Last Used Cell (Range) in Header Row
                          ' LucU - Last Used Cell (Range) in Unique Column
    Dim dict As Object    ' Dictionary
    Dim key As Variant    ' Dictionary Key (For Each Control Variable)
    Dim vntS As Variant   ' Source Array
    Dim vntR As Variant   ' Row Array
    Dim vntU As Variant   ' Unique Array
    Dim vntK As Variant   ' Keep Array
    Dim NorS As Long      ' Source Number of Rows
    Dim NorU As Long      ' Unique Number of Rows
    Dim NorK As Long      ' Keep Number of Rows
    Dim Noc As Long       ' Number of Columns
    Dim FC As Long        ' First Column Number
    Dim ColU As Long      ' Source Array Unique Column Number
    Dim i As Long         ' Source/Keep Array Row Counter
    Dim j As Long         ' Column Counter
    Dim k As Long         ' Row/Unique Array Row Counter
    Dim strSh As String   ' Keep Worksheet Name Concatenator

    ' Speed up.
    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With
    ' Handle unexpected error.
    On Error GoTo ErrorHandler

    ' Task: Write values from Source Worksheet (ws) to Source Array (vntS).

    ' Create a reference to Source Worksheet.
    Set ws = ThisWorkbook.ActiveSheet
    ' In Source Worksheet
    With ws
        ' Calculate and create a reference to LucH.
        Set rng = .Columns(cColU).Find("*", , xlFormulas, , , xlPrevious)
        ' Write row number of LucH to Number of Rows.
        NorS = rng.Row - cFR + 1
        ' Calculate and create a reference to LucU.
        Set rng = .Rows(cFR).Find("*", , xlFormulas, , , xlPrevious)
        ' Calculate First Column Number.
        FC = .Columns(cFC).Column
        ' Write row number of LucU to Number of Columns.
        Noc = rng.Column - FC + 1
        ' Calculate Source Array Unique Column Number.
        ColU = .Columns(cColU).Column - FC + 1
        ' Calculate Source Range.
        ' Copy Source Range to Source Array.
        vntS = .Cells(cFR, cFC).Resize(NorS, Noc)
    End With

    ' Task: Write Source Array row numbers (i) for first found ('unique')
    '       values to Dictionary (dict) and row numbers (i) for again found
    '       values to Row Array (vntR).

    ' Resize 1D 1-based Row Array to Source Number of Rows.
    ReDim vntR(1 To NorS)
    ' Create a reference to Dictionary.
    Set dict = CreateObject("Scripting.Dictionary")
    ' Loop through Rows of Source Array (first row are headers).
    For i = 2 To NorS
        ' Check if current value in Source Array does not exists in Dictionary.
        If Not dict.Exists(vntS(i, ColU)) Then ' Does NOT exist in Dictionary.
            ' Add current value in Source Array to Key and current Source
            ' Row Number in Source Array to Value of Dictionary.
            dict.Add vntS(i, ColU), i
          Else ' Does EXIST in Dictionary.
            ' Count number of elements in Row Array.
            k = k + 1
            ' Write current Source Row Number to current row in Row Array.
            vntR(k) = i
        End If
    Next

    ' Task: Write from Source Array (vntS) to Keep Array (vntK).

    ' Check if any 'non-unique' values have been found.
    If k = 0 Then GoTo UniqueMessage ' Inform user.
    ' Resize Row Array to current row count of Row Array (k) i.e.
    ' remove empty values.
    ReDim Preserve vntR(1 To k)
    ' Write size (rows) of Row Array to Keep Number of Rows.
    NorK = k + 1 ' + 1 for Headers
    ' Resize Keep Array to Keep Number of Rows and Number of Columns.
    ReDim vntK(1 To NorK, 1 To Noc)
    ' Write Headers from Source Array to Keep Array.
    For j = 1 To Noc
        vntK(1, j) = vntS(1, j)
    Next
    ' Write Body Keep Values from Source array to Keep Array.
    For i = 2 To NorK
        For j = 1 To Noc
            vntK(i, j) = vntS(vntR(i - 1), j)
        Next
    Next
    Erase vntR ' No longer needed. Data is in Keep Array.

    ' Task: Copy Keep Array (vntK) to Keep Range (rng) in newly created
    '       Keep Worksheet(wsK).

    ' Write Source Worksheet Name to Keep Worksheet Name Concatenator.
    strSh = ws.Name
    ' Apply numbering to Worksheet Name Concatenator.
    strSh = cSheet & CStr(Right(strSh, Len(strSh) - Len(cSheet)) + 1)
    ' Delete possible existing Keep Worksheet.
    Application.DisplayAlerts = False
        On Error Resume Next
            ThisWorkbook.Worksheets(strSh).Delete
        On Error GoTo 0
    Application.DisplayAlerts = True
    ' Handle unexpected error.
    On Error GoTo ErrorHandler
    ' Copy Source Worksheet after itself.
    ws.Copy After:=ws
    ' Create a reference to the newly created Keep Worksheet, which is
    ' the ActiveSheet now.
    Set wsK = ActiveSheet
    ' In Keep Worksheet
    With wsK
        ' Rename Keep Worksheet to value (string) of Keep Worksheet Name
        ' Concatenator.
        .Name = strSh
        ' Calculate and clear rows below Keep Range.
        .Rows(NorK + cFR).Resize(.Rows.Count - NorK - cFR + 1).Clear
        ' Calculate and create a reference to Keep Range.
        Set rng = .Cells(cFR, FC).Resize(NorK, Noc)
        ' Copy Keep Array to Keep Range.
        rng = vntK
    End With
    Erase vntK ' No longer needed. Data in Keep Range.

    ' Task: Write from Source Array (vntS) to Unique Array (vntU).

    ' Caclulate Unique Number of Rows.
    NorU = dict.Count + 1 ' + 1 for Headers
    ' Resize Unique Array to Unique Number of Rows and Number of Columns.
    ReDim vntU(1 To NorU, 1 To Noc)
    ' Reset Unique Array Row Counter.
    k = 1
    ' Write Headers from Source Array to Unique Array.
    For j = 1 To Noc
        vntU(1, j) = vntS(1, j)
    Next
    ' Write Body Unique Values from Source array to Unique Array.
    For Each key In dict
        k = k + 1
        For j = 1 To Noc
            vntU(k, j) = vntS(dict(key), j)
        Next
    Next
    Erase vntS ' No longer needed. Data in Keep Range and Unique Array.
    dict.RemoveAll ' No longer needed. Data in Unique Array.

    ' Task: Copy Unique Array (vntU) to Unique Range (rng) in
    '       Source Worksheet (ws).

    ' In Source Worksheet
    With ws
        ' Calculate and clear rows below Unique Range.
        .Rows(NorU + cFR).Resize(.Rows.Count - NorU - cFR + 1).Clear
        ' Calculate and create a reference to Unique Range.
        Set rng = .Cells(cFR, FC).Resize(NorU, Noc)
        ' Copy Unique Array to Unique Range.
        rng = vntU
    End With
    Erase vntU ' No longer needed. Data is in Unique Range.

ProcedureExit:

    ' Speed Down.
    With Application
        .Calculation = xlCalculationAutomatic
        .ScreenUpdating = True
    End With

Exit Sub

UniqueMessage:
    MsgBox "All values are unique.", vbInformation, "Unique"
    GoTo ProcedureExit

ErrorHandler:
    MsgBox "An unexpected error occurred. Error '" & Err.Number & "': " _
            & Err.Description, vbCritical, "Error"
    GoTo ProcedureExit

End Sub

3 commentaires

Salut! Merci beaucoup pour cela, c'est incroyable. Cependant, je reçois toujours l'erreur: Une erreur inattendue s'est produite. Erreur '5': Appel de procédure ou argument non valide " J'ai recherché ceci sur Google et il est indiqué: " Erreur d'exécution '5': Appel de procédure ou argument non valide "Cette erreur se produit lorsque vous essayez de modifier l'emplacement de le répertoire sysdata vers un répertoire partagé sur le réseau à partir de la boîte de dialogue Modifier le répertoire SYSDATA de Microsoft FRx. Je ne sais pas comment résoudre ce problème? Merci encore d'avoir partagé votre temps et votre expertise.


@alexlovesquadrupeds: Avez-vous téléchargé le classeur? Faites-le et voyez comment cela fonctionne là-bas. Je n'ai que Sheet1 et Backup dans le classeur.


oh mon Dieu, merci beaucoup, je pense que j'ai réussi à faire fonctionner ça! Merci mille fois. Cela me tue depuis des semaines. Et j'ai appris beaucoup de choses aussi!



0
votes

J'ai essayé sur la ligne de votre travail et essayé de rester simple

Sub test2()
Dim SrcRw As Long, SrclastRow As Long, SrcWs As Worksheet, TrgWs As Worksheet
Dim TrgRw As Long, TrglastRow As Long, LoopNo As Long
Dim Animal As String, Rng As Range, C As Range, firstAddress As String
Dim AnimalCol As String, Dummy As Variant, Lcnt() As Long


Dummy = InputBox("Enter Column Letter,Source Sheet Name And Target Sheet Name seperated by Comma", "Input Source & targets", "C,Sheet1,Sheet2")
If Len(Dummy) <= 0 Then
MsgBox " Invalid input"
Exit Sub
Else
Dummy = Split(Dummy, ",")
    If UBound(Dummy) < 2 Then
    MsgBox " Invalid input, All parameters are not entered"
    Exit Sub
    End If
End If


AnimalCol = Dummy(0)
Set SrcWs = ThisWorkbook.Sheets(Dummy(1))
Set TrgWs = ThisWorkbook.Sheets(Dummy(2))
TrgRw = 1
LoopNo = 1
SrclastRow = SrcWs.Range("A" & SrcWs.Rows.Count).End(xlUp).Row + 1
ReDim Lcnt(1 To SrclastRow)

    For SrcRw = 1 To SrclastRow
    Lcnt(SrcRw) = 1
    Next

    Do
    Set Rng = Nothing
    SrcRw = 1
        Do While SrcWs.Cells(SrcRw, AnimalCol).Value <> ""
        If Lcnt(SrcRw) = LoopNo Then
        Animal = SrcWs.Cells(SrcRw, AnimalCol).Value

            If Rng Is Nothing Then
            Set Rng = SrcWs.Cells(SrcRw, 1)
            Else
            Set Rng = Union(Rng, SrcWs.Cells(SrcRw, 1))
            End If

        With SrcWs.Range(AnimalCol & SrcRw + 1 & ":" & AnimalCol & SrclastRow)
        Set C = .Find(Animal, LookIn:=xlValues)
            If Not C Is Nothing Then
            firstAddress = C.Address
                Do
                Lcnt(C.Row) = LoopNo + 1
                Set C = .FindNext(C)
            Loop While Not C Is Nothing And C.Address <> firstAddress
            End If
       End With

       End If
       SrcRw = SrcRw + 1
       Loop

       If Not Rng Is Nothing Then
       Rng.EntireRow.Copy TrgWs.Range("A" & TrgRw)
       TrgRw = TrgWs.Range("A" & TrgWs.Rows.Count).End(xlUp).Row + 2
       Else
       Exit Do
       End If
    Set Rng = Nothing
    LoopNo = LoopNo + 1
    Loop

End Sub

le code peut être facilement exécuté une fois comme vous le souhaitiez, mais s'il est essayé de boucler pour les nouvelles feuilles générées, il peut planter comme votre liste d'animaux peut dépasser des milliers de rangées et en conservant un ensemble de 10 animaux, elle peut ajouter 100 feuilles. Ainsi, même après l'ajout de la mise à jour de l'écran d'événement de calcul standard, il avait tendance à se bloquer sur environ 700 lignes si la boucle externe est activée.

Une autre solution de contournement simple a donc été essayée où la liste d'origine des animaux était conservée intacte et chaque les listes uniques sont sorties sur la 2ème feuille avec une ligne vide entre elles. ici, une autre colonne dit que D est utilisée ici pour garder une trace de la liste déjà utilisée. Le code comme suit

Sub test()
Dim SrcRw As Long, SrclastRow As Long, SrcWs As Worksheet, TrgWs As Worksheet
Dim TrgRw As Long, TrglastRow As Long
Dim Animal As String, Rng As Range, C As Range, firstAddress As String

'Do
Set SrcWs = ThisWorkbook.Sheets(1)
SrcRw = 1
TrgRw = 1


Do While SrcWs.Cells(SrcRw, 3).Value <> ""
Animal = SrcWs.Cells(SrcRw, 3).Value
    With SrcWs.Range("C" & SrcRw + 1 & ":C" & Rows.Count)
    Set C = .Find(Animal, LookIn:=xlValues)

        If Not C Is Nothing Then
        firstAddress = C.Address
            Do
                If Rng Is Nothing Then
                Set Rng = C
                Else
                Set Rng = Union(Rng, C)
                End If
            'Debug.Print C.Address
            Set C = .FindNext(C)
            Loop While Not C Is Nothing And C.Address <> firstAddress
        End If
    End With


    If Not Rng Is Nothing Then
    If TrgWs Is Nothing Then Set TrgWs = ThisWorkbook.Worksheets.Add(ThisWorkbook.Sheets(1))
    Rng.EntireRow.Copy TrgWs.Range("A" & TrgRw)
    TrgRw = TrgWs.Range("A" & TrgWs.Rows.Count).End(xlUp).Row + 1
    Rng.EntireRow.Delete
    End If
Set Rng = Nothing
SrcRw = SrcRw + 1
Loop

'    If TrgWs Is Nothing Then
'    Exit Sub
'    End If
'Set TrgWs = Nothing
'Loop

End Sub

Résultat du code 2

 entrez la description de l'image ici


3 commentaires

Je ne peux pas faire fonctionner l'un ou l'autre de ces éléments! Sur ma feuille réelle (non simplifiée), la colonne est G, pas C, j'ai donc changé tous les «C» en «G». Dois-je aussi changer des nombres? Quant à: "votre liste d'animaux peut dépasser des milliers de lignes" - tout à fait correct! "et garder comme ensemble de 10 animaux cela peut ajouter 100 feuilles" - il est en fait peu probable que j'aie plus de 3 de chaque espèce. Mais, 10 de chaque espèce ne généreraient-ils que 9 feuilles supplémentaires? Merci beaucoup de partager vos connaissances, votre temps et votre patience avec moi, je l'apprécie énormément.


Désolé, cela n'a pas fonctionné pour vous. 2ème code modifié pour la lettre de colonne d'entrée, le nom de la feuille source et le nom de la feuille cible de votre choix. Peut essayer


Je n'ai pas pu le faire fonctionner, mais merci beaucoup, quand même. Intéressant de voir que vous utilisez une ancienne version de Windows et Opera aussi! Vieille école!