2012-08-08 73 views
6

Por favor alguien puede darme algunos consejos sobre la manera de resolver el siguiente problema:VBA, eliminar duplicados de la matriz

Supongamos que tengo un bloque de datos en Excel 2010, 100 filas por 3 columnas.

columna C contiene algunos duplicados, dicen que comienza como 1,1,1 2,3,4,5, ....., 97,98

El uso de VBA, me gustaría quitar el duplique las filas, de acuerdo con la columna C, de modo que me quedo con 1,2,3, ....., 97, 98, es decir, solo 98 filas y 3 columnas.

Sé que hay un botón en el que puedo hacer clic en Excel 2010 para hacerlo, pero quiero hacerlo en VBA (porque lo he intentado y, por algún motivo, intero con el resto de mi código posteriormente y da error resultados).

Por otra parte, me gustaría hacerlo en matrices, a continuación, pegar los resultados en la hoja de trabajo, en lugar de métodos tales como Application.Worksheetfunction.countif (.....

Así que algo como:

.
Dim myarray() as Variant 
myarray=cells(1,1).Currentregion.value 

Dim a as Long 

For a=1 to Ubound(myarray,1) 

    'something here to 

Next a 

Respuesta

5

I answered a similar question Aquí está el código que utilicé:

Dim dict As Object 
Dim rowCount As Long 
Dim strVal As String 

Set dict = CreateObject("Scripting.Dictionary") 

rowCount = Sheet1.Range("A1").CurrentRegion.Rows.Count 

'you can change the loop condition to iterate through the array rows instead 
Do While rowCount > 1 
    strVal = Sheet1.Cells(rowCount, 1).Value2 

    If dict.exists(strVal) Then 
    Sheet1.Rows(rowCount).EntireRow.Delete 
    Else 
    'if doing this with an array, then add code in the Else block 
    ' to assign values from this row to the array of unique values 
    dict.Add strVal, 0 
    End If 

    rowCount = rowCount - 1 
Loop 

Set dict = Nothing 

Si desea utilizar una matriz, a continuación, recorrer los elementos con el mismo condicional (if/else) st atements. Si el elemento no existe en el diccionario, puede agregarlo al diccionario y agregar los valores de fila a otra matriz.

Honestamente, creo que la forma más eficiente es adaptar el código que obtendría de la grabadora de macros. Puede realizar la función anterior en una línea:

Sheet1.UsedRange.RemoveDuplicates Columns:=3, Header:=xlYes 
+2

Esta eliminar filas reales de la hoja, mientras que la cuestión era eliminar duplicados en VBA.Además, cualquier eliminación de fila siempre debería ocurrir yendo de abajo hacia arriba, para evitar omitir filas – brettdj

+0

@brettdj Ambos bits de código funcionarán para eliminar duplicados. El asker quería hacerlo en VBA, preferiblemente con matrices (en cuyo caso puede modificar fácilmente el ciclo para iterar a través de filas de la matriz en lugar de un rango, y luego agregar solo elementos únicos a una matriz separada). Si miras el código, verás que la eliminación de fila va de abajo hacia arriba ('rowCount' se reduce). :) – Zairja

+0

Bueno, la pregunta se titula * VBA, eliminar duplicados de la matriz *. Señala que el código desciende de la misma forma que usa '.Count', aunque en este caso el asker puede necesitar especificar si la primera ocurrencia debe mantenerse en la parte superior o inferior. – brettdj

0

Diccionarios tienen un máximo de 255 elementos, por lo que si usted tiene más valores que necesite usar una colección. Por desgracia, el objeto de cobro no tiene un (a) o .Exists (a) Método .Contains, pero esta función asas (falsificaciones de ella) que muy bien mediante el uso de los números de error:

CORRECCIÓN: Los diccionarios no cuenten con dicha una límite (gracias Zairja). Pude haber estado usando un Entero para iterar a través de mi Diccionario. En cualquier caso, esta función le permite comprobar las colecciones para la existencia artículo, así que lo voy a dejar aquí si es útil para cualquier persona:

CollContainsItem(col As Collection, val As Variant) As Boolean 

Dim itm As Variant 
On Error Resume Next 

    itm = col.Item(val) 
    CollContainsItem = Not (Err.Number = 5 Or Err.Number = 9) 

On Error GoTo 0 

End Function 

Así que si usted no necesita una colección, que probablemente podría simplemente reemplazar

dict.Exists(strVal) 

con

CollContainsItem(coll, strVal) 

y reemplazar

Set dict = CreateObject("Scripting.Dictionary") 

con

Set coll = CreateObject("Scripting.Collection") 

y utilizar el resto del código de zairja. (Que en realidad no probarlo pero debe estar cerca)

+2

En realidad, el objeto 'Diccionario' no está limitado a 255 elementos. Esa es solo la cantidad máxima de elementos que muestra el depurador. Creo que solo está limitado por la memoria (estoy usando Excel 2010, pero en la versión de 2003 pude tener diccionarios con algunos cientos de miles de elementos). Además, querrá asegurarse de que si está utilizando algún tipo de variable de incremento, asegúrese de que sea 'Largo' y no' Entero' (que se detendría en 256). – Zairja

+0

Oh, ¿el entero de Excel solo va a 256? Tal vez ese fue mi problema desde el principio. –

3
Function eliminateDuplicate(poArr As Variant) As Variant 
Dim poArrNoDup() 

    dupArrIndex = -1 
For i = LBound(poArr) To UBound(poArr) 
     dupBool = False 

     For j = LBound(poArr) To i 
      If poArr(i) = poArr(j) And Not i = j Then 
       dupBool = True 
      End If 
     Next j 

     If dupBool = False Then 
      dupArrIndex = dupArrIndex + 1 
      ReDim Preserve poArrNoDup(dupArrIndex) 
      poArrNoDup(dupArrIndex) = poArr(i) 
     End If 
Next i 

eliminateDuplicate = poArrNoDup 
End Function 
+0

No edite las respuestas de otros usuarios de SO como lo hizo en [esta revisión] (http://stackoverflow.com/revisions/19693896/2) si hay un problema con el código, coméntelo y hágales saber. – Lankymart

+0

Necesita configurar dupBool en falso para cada ciclo de i – 99moorem

Cuestiones relacionadas