dudas con autofiltro

20/12/2006 - 03:47 por Ivan | Informe spam
hola a todos

he estado practicando un poco con los autofiltros por codigo, y me han
surgido un par (mas) de dudas sobre su manejo ->

1.- ¿es posible usar como criterio de filtrado varias celdas de una
misma fila en una sola pasada? me da la impresion de que no, o al menos
en la ayuda no consigo aclararlo, pero ¿quizas se pueda utilizar algo
como CurrentArray, o alguna propiedad o metodo que desconozco?

en las practicas que he estado realizando he usado una serie de bucles
celda a celda 'achicando' el rango filtrado, pero se hace un poco lento
(creo, igual se ralentiza en otra parte del codigo)

esta es la parte del codigo que realiza el filtrado, y que quizas sea
muy optimizable (filtra los registros que sean iguales en el rango
'a:e' )->

With Worksheets("testTransponer")
If .[a2] = "" Then Exit Sub
If .AutoFilterMode Then .AutoFilterMode = False
f = .[a65536].End(xlUp).Row
For Each celda In .Range("a2:a" & f)
criterio = celda.Value
celda.CurrentRegion.AutoFilter _
field:=1, _
Criteria1:=criterio
For cc = 2 To 5
criterio = celda.Cells(1, cc)
With .Cells.SpecialCells(xlCellTypeVisible)
If .Rows.Count > 1 Then
.AutoFilter _
field:=cc, _
Criteria1:=criterio
End If
End With
Next

2.- esta duda quizas incluso ya me la hayais respondido en alguna
ocasion, pero la verdad es que no lo recuerdo. ¿el rango filtrado
(.autofilter.range) incluye entre sus filas (la cuenta como tal) la de
encabezado (titulos de campo)?

creo entender que si, de ahi el uso normalmente de .resize.offfset(1)
para trabalar con los registros, pero hoy, en mis experimentos, me ha
surgido alguna duda, y de ahi la consulta.

bueno, si podeis echarme una mano de nuevo, os lo agradezco

un saludo y hasta pronto
Ivan

Preguntas similare

Leer las respuestas

#1 Héctor Miguel
20/12/2006 - 08:08 | Informe spam
hola, Ivan !

1) no comentas/expones/... cual seria al uso [o el siguiente paso] una vez 'auto-filtrados' -todos- los campos en el rango
[en caso de existir 'datos que filtrar'... -> cual seria la utilidad de tal 'tarea'] -?-

2) el proceso esta -realmente- haciendo un 'barrido/escaneo/bucle/...' por todas y cada una de las celdas [cada vez] -???-
[seguramente] esa es la razon del tiempo que le toma al codigo terminar su tarea [al menos, la parte que expones] ;)

3) [probablemente] si te sirve 'la inversa'... prueba:
a) ordenando primero las columnas C, D y E y al ultimo las columnas A y B [en ese orden]
b) luego aplica filtros avanzados [SIN la opcion de criterios] con la opcion de solo registros unicos ;)
-> obtendras un listado de los elementos 'unicos' en el rango [los 5 campos distintos] y se ocultaran los duplicados -?-

4) otra alternativa pudiera ser 'evaluar' una formula con sumaproducto(...) [conociendo que datos 'coincidentes' se buscarian] -?-

5) [fialmente] los autofiltros SI contemplan la fila de encabezados [en su propiedad 'autofilter.range'] ;)

si cualquier duda [o informacion adicional]... comentas ?
saludos,
hector.

__ la consulta original __
he estado practicando un poco con los autofiltros por codigo, y me han surgido un par (mas) de dudas sobre su manejo ->
1.- es posible usar como criterio de filtrado varias celdas de una misma fila en una sola pasada?
me da la impresion de que no, o al menos en la ayuda no consigo aclararlo, pero
quizas se pueda utilizar algo como CurrentArray, o alguna propiedad o metodo que desconozco?
en las practicas que he estado realizando he usado una serie de bucles celda a celda 'achicando' el rango filtrado
pero se hace un poco lento (creo, igual se ralentiza en otra parte del codigo)
esta es la parte del codigo que realiza el filtrado, y que quizas sea muy optimizable (filtra los registros que sean iguales en el rango 'a:e' )->
With Worksheets("testTransponer")
If .[a2] = "" Then Exit Sub
If .AutoFilterMode Then .AutoFilterMode = False
f = .[a65536].End(xlUp).Row
For Each celda In .Range("a2:a" & f)
criterio = celda.Value
celda.CurrentRegion.AutoFilter _
field:=1, _
Criteria1:=criterio
For cc = 2 To 5
criterio = celda.Cells(1, cc)
With .Cells.SpecialCells(xlCellTypeVisible)
If .Rows.Count > 1 Then
.AutoFilter _
field:=cc, _
Criteria1:=criterio
End If
End With
Next

2.- esta duda quizas incluso ya me la hayais respondido en alguna ocasion, pero la verdad es que no lo recuerdo.
el rango filtrado (.autofilter.range) incluye entre sus filas (la cuenta como tal) la de encabezado (titulos de campo)?
creo entender que si, de ahi el uso normalmente de .resize.offfset(1) para trabalar con los registros
pero hoy, en mis experimentos, me ha surgido alguna duda, y de ahi la consulta...
Respuesta Responder a este mensaje
#2 Ivan
21/12/2006 - 03:54 | Informe spam
hola Hector Miguel, y una vez mas muchas gracias por tu ayuda

te comento:

1) no comentas/expones/... cual seria al uso [o el siguiente paso] una vez 'auto-filtrados' ..[ ]... -> cual seria la utilidad de tal 'tarea'] -?-

en realidad se trataria de transponer la ultima columna de cada


rango (de una lista) formado por los registros en los que todos los
campos anteriores sean iguales (puede haber unicos tambien) previa
busqueda, ycolocarla (transponerla) a partir del ultimo campo del
primer registro 'coincidente', y eliminar el resto de registros
'coincidentes'.

aunque la excusa inicial ha sido intentar contestar a una consulta del
foro ( http://tinyurl.com/yhafur ), la verdad es que estoy intentando
retomar el aprendizaje de los filtros ( avanzados y autofiltros ), con
los que no acabo de manejarme

de todas formas si quieres echarle un ojo a dicho dialogo, en el, a
partir del 5º post y en especial en el 8º (creo) esta mejor esplicado
lo que busco con la macro, y en el ultimo esta el codigo que incluye el
fragmento expuesto en la consulta (el del penultimo post casi mejor que
ni lo mires), que aparte de ser una chapuza sigue teniendo varias
carencias (entre ellas, si no me equivoco, que no traspasa (a otra hoja
en la que copio las celdas visibles del filtrado) los registros unicos
ni el ultimo coincidente, y no consigo encontrar donde falla

2) el proceso esta -realmente- haciendo un 'barrido/escaneo/bucle/...' por todas y cada una de las celdas [cada vez]

de ahi el intento de usar un criterio 'compuesto' por todos los


campos a comparar en una sola pasada. Tras tu respuesta he estado
tanteando los filtros avanzados, y parece que estos si lo hacen, pero
de momento no he conseguido aplicar al resultado del filtro el resto de
la macro (el copiar a otra hoja no es imprescindible, si es posible,
podria hacerse todo el proceso en la misma )

3) [probablemente] si te sirve 'la inversa'... prueba:
a) ordenando primero las columnas C, D y E y al ultimo las columnas A y B [en ese orden]
b) luego aplica filtros avanzados



-> lo dicho, estoy tanteandolo

4) otra alternativa pudiera ser 'evaluar' una formula con sumaproducto(...) [conociendo que datos 'coincidentes' se buscarian] -?-



-> aqui, por lo que creo entender en la consulta original, mas que
los datos en si lo que se conoceria serian los campos en los que buscar
las coincidencias y, en cuanto a 'sums producto', me temo que entramos
en el (para mi) farragoso mundo de las formulas ¿nativas?

5) [fialmente] los autofiltros SI contemplan la fila de encabezados [en su propiedad 'autofilter.range'] ;)



-> gracias de nuevo. Eso creia entender, pero hay veces con los
filtros que empiezo a dudar de lo poco que se

bueno, si puedes echarle un vistazo al dialogo de marras, sera mas
claro que mi rollo de turno.

un saludo y hasta pronto
Ivan
Respuesta Responder a este mensaje
#3 Ivan
22/12/2006 - 04:52 | Informe spam
hola de nuevo Hector Miguel

he estado haciendo pruebas con los filtros avanzados, y me ha surgido
un nuevo problema (aunque creo que ya me ocurria con los autofiltros),
no se como hacer con el ultimo rango (creo que) filtrado, bien sea un
solo registro o sea el ultimo grupo de registros coicidentes.

cuando solo queda este, la macro no parece reconocerlo, quizas por que
ya no hay 'filtrado', dado que o es unico o el criterio es valido para
todos, y entra en un bucle infinito

¿como puedo indicarle al procedimiento que si llega ese momento haga x
cosa ( en este caso lo mismo que con el resto)?

a continuacion te expongo el ultimo codigo (todavia no se lo que
tardara), ahora ampliado al rango 'a:k'

un saludo y hasta pronto
ivan

Sub testTransponer4()
Dim f As Long, ff As Long, colN As Byte, tarda
Application.ScreenUpdating = False
tarda = Timer
With Worksheets("testTransponer")
If .[a2] = "" Then Exit Sub
On Error Resume Next
.ShowAllData
On Error GoTo 0
With .Range("a1:k" & .[a65536].End(xlUp).Row)
.Sort key1:=.Columns("j"), key2:=.Columns("k"), _
Header:=xlYes
.Sort key1:=.Columns("g"), key2:=.Columns("h"), _
key3:=.Columns("i"), Header:=xlYes
.Sort key1:=.Columns("d"), key2:=.Columns("e"), _
key3:=.Columns("f"), Header:=xlYes
.Sort key1:=.Columns("a"), key2:=.Columns("b"), _
key3:=.Columns("c"), Header:=xlYes
End With
Do
.[a1].CurrentRegion.AdvancedFilter _
Action:=xlFilterInPlace, _
CriteriaRange:=.Range("A1:j2")
With .Cells.SpecialCells(xlCellTypeVisible)
f = .Rows.Count
If f = 1 Then Exit Do
If f = 2 Then
With .Cells(2, 1).EntireRow
.Copy Worksheets("ocuTrans").[a65536] _
.End(xlUp).Offset(1, 0)
.Delete
End With
Else
colN = 12
For ff = 3 To f - 1
If .Cells(ff, 11) <> "" Then
.Cells(2, colN) = .Cells(ff, 11)
colN = colN + 1
End If
Next
.Cells(2, 1).EntireRow.Copy _
Worksheets("ocuTrans").[a65536] _
.End(xlUp).Offset(1, 0)
For ff = f To 2 Step -1
.Cells(ff, 1).EntireRow.Delete
Next
End If
End With
.ShowAllData
Loop Until .[a2] = ""
.Columns.AutoFit
End With
tarda = Timer - tarda
MsgBox "Tarda con filtro avanzado -> " & tarda
End Sub
Respuesta Responder a este mensaje
#4 Héctor Miguel
22/12/2006 - 06:14 | Informe spam
hola, Ivan !

he estado haciendo pruebas con los filtros avanzados, y me ha surgido un nuevo problema
(aunque creo que ya me ocurria con los autofiltros), no se como hacer con el ultimo rango (creo que) filtrado
bien sea un solo registro o sea el ultimo grupo de registros coicidentes.
cuando solo queda este, la macro no parece reconocerlo, quizas por que ya no hay 'filtrado'
dado que o es unico o el criterio es valido para todos, y entra en un bucle infinito
como puedo indicarle al procedimiento que si llega ese momento haga x cosa (en este caso lo mismo que con el resto)?
a continuacion te expongo el ultimo codigo (todavia no se lo que tardara), ahora ampliado al rango 'a:k' [...]



no tengo los 'elementos' para correr pruebas con la 'similitud/exactitud/...' de los datos reales de tu trabajo :D pero...
la 'omision' que hace el codigo se debe [segun parece] a las condiciones 'If... Else... End If' que tienes dentro del 'Do... Loop'

-> despues de asignar el numero de filas visibles [luego del filtrado] con la instruccion: -> f = .Rows.Count
a) tienes una salida cuando solo hay una celda visible [los titulos] con la instruccion: -> If f = 1 Then Exit Do
b) tienes una condicionante cuando solo hay 2 celdas visibles [un solo registro] con: -> If f = 2 Then
c) tienes un 'Else' donde se asume que NO son -solo- 2 registros filtrados... sino -> DOS O MAS [sin embargo]
-> el 'avance' que haces por las filas lo estas iniciando -solo- a partir de la fila 3... -> For ff = 3 To f - 1
-> 'que paso' con la fila 2... cuando hay mas de 2 celdas visibles ??? ;)

si cualquier duda [o informacion adicional]... comentas ?
saludos,
hector.
Respuesta Responder a este mensaje
#5 Ivan
25/12/2006 - 18:33 | Informe spam
"Como los erizos, ya sabeis, los hombres un dia sintieron su frio,
y decidieron compartirlo.
Entonces, inventaron la programación.
El resultado fue, ya sabeis, como los erizos ...
..
Y menos mal cuando no lo punza la sombra de aquellas espinas, de
aquellas espinas, ya sabeis"

[aunque solo sea por las fechas, espero que se me disculpe esta
licencia poetica (lo que no tengo claro es si Cernuda me lo
perdonaria..)]

hola de nuevo Hector Miguel, otra vez gracias y feliz navidad
!!!.

disculpa la tardanza, pero entre las fechas que son y que queria
trabajarlo un poco antes de responderte, hemos llegado hasta hoy. Te
comento un poco tu respuesta y, si tienes tiempo, te vuelvo a exponer
¿un par? de dudas ->

lo primero, intento explicarte el objetivo y el archivo de ej usado (lo
pongo en plan esquema, porque sino, con lo que me enrrollo,..., espero
se me entienda, y no aburrirte demasiado)

1.->el archivo:

1.1.-se trata de una hoja con 13000 registros con campos de la 'a' a la
'k'
1.2.-puede haber registros repetidos
1.3.-las columnas 'a:j' tienen datos en todos los registros, en 'k'
puede no haberlos

2.->el objetivo:

2.1.-se trata de dejar solo los registros unicos para los campos de la
'a' a la 'j', transponiendo a continuacion de estos las posibles
entradas de la columna 'k'
2.2.-ej(con solo 5 campos <la columna 'e' equivaldria a la 'k'>):

colA colB colC colD colE
f1 titulo titulo titulo titulo titulo
f2 coche casa mesa cama x1
f3 coche casa mesa cama
f4 coche casa mesa cama x2
f5 coche casa mesa silla x3
f6 coche casa mesa silla x1
f7 coche casa manta silla x6
f8 cosa casa mesa cama x1
f9 coche casa mesa silla x8
f10 coche casa mesa mantel

tendria que quedar +o- asi:

colA colB colC colD colE colF colG
f1 titulo titulo titulo titulo titulo titulo titulo
f2 coche casa mesa cama x1 x2
f3 coche casa mesa silla x3 x1 x8
f4 coche casa manta silla x6
f5 cosa casa mesa cama x1
f6 coche casa mesa mantel

como te comentaba, aunque en un principio se trataba de echar una mano
en una consulta del foro, al final se ha convertido en un intento de
arrancarme alguna 'de aquellas espinas, [de aquellas espinas, ya
sabeis,'] sobre los autofiltros y filtros avanzados

en cuanto a tu respuesta: ->

no tengo los 'elementos' para correr pruebas con la 'similitud/exactitud/...' de los


datos reales de tu trabajo :D pero...
la 'omision' que hace el codigo se debe [segun parece] a las condiciones 'If... Else...


End If' que tienes dentro del 'Do... Loop'



espero que la explicacion anterior te de una idea mas aproximada de
lo que busco.

-> despues de asignar el numero de filas visibles [luego del filtrado] con la


instruccion: -> f = .Rows.Count
a) tienes una salida cuando solo hay una celda visible [los titulos] con la


instruccion: -> If f = 1 Then Exit Do
b) tienes una condicionante cuando solo hay 2 celdas visibles [un solo registro]


con: -> If f = 2 Then
c) tienes un 'Else' donde se asume que NO son -solo- 2 registros filtrados... sino


-> DOS O MAS [sin embargo]
-> el 'avance' que haces por las filas lo estas iniciando -solo- a partir de la


fila 3... -> For ff = 3 To f - 1
-> 'que paso' con la fila 2... cuando hay mas de 2 celdas visibles ??? ;)





En lo que se refiere a los condicionales, aunque tienes razon en cuanto
a que posiblemente eran un maremagnun un tanto contradictorio, todos
ellos tenian sentido vistos desde mi neurona.

de hecho, seguramente, tras ver las explicaciones y el codigo expuesto
al final, creo que comprenderas su sentido sin problemas (otra cosa es
que sean necesarios, adecuados, etc..)

de nuevo gracias a tus consejos/ayudas (actuales, anteriores y
ajenas..) me he animado a correr unas cuantas pruebas con los filtros,
consiguiendo arrancarme alguna que otra espina (me temo que aun queden
muchas),

aunque al final, para el caso que nos ocupa, he acabado por no
aplicarlos (seguramente las 1001 vueltas que les he dado no han sido
las correctas, pues en todos los casos el resultado era mas lento que
el que te expongo al final)

estas son (algunas de) las dudas que me han surgido:

a).-con 'AdvancedFilter' -> me ha dado la impresion de que no busca la
coincidencia completa de CriteriaRange

(pej:-> si el criterio es '10', (creo que) tambien me filtraba al menos
los '101', '1010', y quizas alguno mas <creo que ademas considerandolos
iguales>)

¿esto es asi, o es que hay que especificar algun parametro o de alguna
forma que desconozco?

te pongo un ej de uso;->

.[a1].CurrentRegion.AdvancedFilter _
Action:=xlFilterInPlace, _
CriteriaRange:=.Range("A1:j2")

b).-con 'Action:=xlFilterCopy':-> sigo sin conseguir copiar en otra
hoja el rango filtrado mediante este parametro, no se muy bien a que se
debe

c).- (y ya son tres dudas) con 'With
.Cells.SpecialCells(xlCellTypeVisible)': -> ¿como seria la forma
idonea de referirse(/trabajar) a un rango de varias celdas y/o varias
filas/columnas del rango visible?¿es imprescindible el uso de Resize
(otra de mis espinas)?

he probado pej:-> .Range(.cells(2,1),.cells(x,y)) y aunque a veces
parece funcionar, creo que algunos de los inconvenientes que me han
surgido se pueden deber a su uso

bueno, no quiero enrrollarme mas, pues podria llenar unos cuantos foros
con mis dudas..

paso a exponerte los codigos usados finalmente para la tarea, por si
ves la forma de mejorarlos y hacerlos mas rapidos (a mi realmente no me
sirve mas que para practicar, pero se lo mandare al consultante para
que lo pruebe)

Datos en mis pruebas
.-archivo: lista con 13000 registros
.-registros unicos(para los valores de [a:j]: aprox 4100
.-registros con transposicion detras: aprox 2000
.-maximo nº de campos transpuestos: aprox 32
.-tiempo aprox. con esta prueba: 32 sg

''********devuelve la referencia de un rango de celdas
'en el que coincidan todos los campos seguidos hasta
'una columna especificada. Para que sea efectivo hay que ordenar
'todos los campos de manera adecuada*************************

Function RangoIguales(ByVal hj As String, _
ByVal nFila As Long, _
ByVal colFin As String) As String
Dim sigF As Long, sigC As Integer
Dim finF As Long, finC As Integer
Dim col As String
With Worksheets(hj)
finF = .[a65536].End(xlUp).Row
finC = Asc(UCase(colFin)) - 65
sigC = 0
Do
sigC = sigC + 1
col = Chr(64 + sigC)
For sigF = nFila + 1 To finF
If .Range(col & sigF) <> .Range(col & sigF - 1) Then
finF = sigF - 1: Exit For
End If
Next
Loop Until sigC = finC
If finF = 1 Then finF = nFila
RangoIguales = .Range("a" & nFila & ":" & colFin & finF) _
.Address(0, 0)
End With
End Function
'*************25/12/2006 15:28:44**********OK de momento
Sub TransSinFiltroOK()
Dim nroF As Long, fInicio As Long
Dim Rango As String
Application.ScreenUpdating = False
tarda = Timer
With Worksheets("testTransponer")
If .[a2] = "" Then Exit Sub
With .Range("a1:k" & .[a65536].End(xlUp).Row)
.Sort key1:=.Columns("j"), key2:=.Columns("k"), _
Header:=xlYes
.Sort key1:=.Columns("g"), key2:=.Columns("h"), _
key3:=.Columns("i"), Header:=xlYes
.Sort key1:=.Columns("d"), key2:=.Columns("e"), _
key3:=.Columns("f"), Header:=xlYes
.Sort key1:=.Columns("a"), key2:=.Columns("b"), _
key3:=.Columns("c"), Header:=xlYes
End With
fInicio = 2
Do While .Range("a" & fInicio) <> ""
Rango = RangoIguales("testTransponer", fInicio, "j")
nroF = .Range(Rango).Rows.Count
If nroF > 1 Then
If nroF = 2 Then
.Range("k" & fInicio + 1).Copy .Range("l" & fInicio)
Else
.Range("k" & fInicio + 1 & ":k" & fInicio + nroF - 1).Copy
.Range("l" & fInicio).PasteSpecial SkipBlanks:=True, _
Transpose:=True
End If
End If
If nroF > 1 Then .Range("a" & fInicio + 1 & ":a" & _
fInicio + nroF - 1).EntireRow.Delete
fInicio = fInicio + 1
Loop
Application.CutCopyMode = False
End With
tarda = Timer - tarda
MsgBox "Tarda con funcion RangoIguales -> " & tarda
End Sub

un saludo y hasta pronto
Ivan

PD: espero se vea algo entre los berridos de blanquita and company
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida