Eliminar filas con una condición excel vba

[*****Dante buenos días

Una consulta como eliminar filas si no tiene notas desaprobadas por ejemplo en sus respectivas celdas tengo esto.

Carlos  15 /18/ 13 / 16/ 15/ 19/ 12 ------------------------>Fila a eliminar

Hunter 16 / 15 /08/ 16/ 19/ 18 / 10 ----------------> no elminar

Hunter 16 / 15 /11/ 16/ 19/ 18 / 10 ----------------> no elminar

intenté con esto 

Sub borrarcell()
Set r = Range("D7:O71")
'
For Each c In r.Rows
   If c > 10 Then
    '
    Rows(c).EntireRow.Delete
    End If
Next c
End Sub

2 Respuestas

Respuesta
1

No entendí que son "notas desaprobadas".

Según tu ejemplo, si en alguna de las celdas de cada fila tiene un número menor o igual a 10 entonces esa fila no se elimina, de lo contrario, es decir, si todos los números son mayores a 10, entonces esa fila se elimina.

Si es correcto, entonces la macro sería así:

Sub borrarcell()
'Por.Dante Amor
    Set rango = Range("D7:O71")
    f_ini = rango.Cells(1, 1).Row
    f_fin = rango.Rows.Count + f_ini - 1
    c_ini = rango.Cells(1, 1).Column
    c_fin = rango.Columns.Count + c_ini - 1
    For i = f_fin To f_ini Step -1
        existe = False
        For j = c_ini To c_fin
            If Cells(i, j) <= 10 Then
                existe = True
                Exit For
            End If
        Next
        If existe = False Then
            Rows(i).Delete
        End If
    Next
End Sub

Nota: Recuerda que cuando borras filas, debes hacerlo de abajo hacia arriba, de lo contrario deberás controlar el contador, ya que si borras la fila donde va tu contador se va a brincar una fila sin analizar. Para que te quede más claro, si vas en la fila 11 y eliminas la fila 11, entonces la fila 12 ahora es la fila 11, pero tu contador en el siguiente ciclo pasa a 12, entonces en el siguiente ciclo revisa la fila 12, eso significa que ahora revisará la fila 13, porque la fila 11 fue eliminada, entonces tendrías que retroceder en 1 tu contador. Mejor realiza la validación de abajo hacia arriba y de esa forma no te preocupas por el contador del ciclo. Utilizando el contador tal y como debe hacerse, de manera lineal.


.

'S aludos. Dante Amor. Recuerda valorar la respuesta. G racias

.

Avísame cualquier duda

.

¡Wao Dante! me diste una explicación magistral gracias 

En una hoja nueva con los siguientes datos:

Prueba la siguiente macro:

Sub borrarcell3()
    Dim r As Range, c As Range
    Set r = Range("D7:D12")
    For Each c In r
        If c.Value > 10 Then
            c.EntireRow.Delete
        End If
    Next
End Sub

Lo que hace la macro es revisar el dato de las celdas D7 a D12, si el dato es mayor a 10 entonces elimina la fila.

En teoría la macro debería eliminar las filas 8, 10 y 11. Pero si ejecutas la macro, solamente elimina las filas 8 y 10. No borra la fila 11, porque el control está brincando a la siguiente fila (esto ya lo expliqué)

Es por eso que se debe llevar el control de la fila eliminada.

No hay que revisar celda por celda de cada fila, también se puede revisar el número menor de la fila, si el número menor de la fila es mayor a 10 entonces eliminamos la fila, quedaría así:

Sub EliminaFila()
'Por.Dante Amor
    Set rango = Range("D7:O12")
    f_ini = rango.Cells(1, 1).Row
    f_fin = rango.Rows.Count + f_ini - 1
    c_ini = rango.Cells(1, 1).Column
    c_fin = rango.Columns.Count + c_ini - 1
    For i = f_fin To f_ini Step -1
        wmin = WorksheetFunction.Min(Range(Cells(i, c_ini), Cells(i, c_fin)))
        If wmin > 10 Then Rows(i).Delete
    Next
End Sub

sal u dos

¡Gracias! algo así había pensado a un principio a base de esta macro 

Cambiar color a los valores máximos 

Ya decía yo que había hecho algo similar con el manejo de for-each (imposible recordar más de 10 mil macros), pero en este caso quieres eliminar la fila, en el otro caso se quiere iluminar la fila, es por eso que la opción era recorrer de otra forma las filas.

Respuesta
1

Manteniendo tu misma idea:

Sub borrarcell ()
Dim r As Range, c As Range
Set r = Range("D7:O71")
For Each c In r
   If c.Value > 10 Then
    c.EntireRow.Delete
    End If
Next c
End Sub

Comentas

Abraham Valencia

no funca 

¿No será que tienes esos valores como texto?

Abraham Valencia

[Hola Abrahan buenas tardes.

La macro se ejecuta pero no cumple con esta descripción 

'

"Si en alguna de las celdas de cada fila tiene un número menor o igual a 10 entonces esa fila no se elimina, de lo contrario, es decir, si todos los números son mayores a 10, entonces esa fila se elimina."

¿Hay cómo ver esos datos? ¿Podrías colocar en alguna "nube" para verlo?

Abraham Valencia

Disculpa por meter temas insulsos a tu post. A partir de este momento me abocaré a ver solo tu dilema, aunque sigo sospechando que es cuestión de formatos. Un abrazo.

Abraham Valencia

[Buenas noches abraham tienes un email para envía mi ejemplo ?

¿Cuál es el tuyo?

Abraham Valencia

[Buenos días te paso mi ejemplo. 

https://www.dropbox.com/s/kfaokypaqkxaz0b/PRUEBA.xlsx?dl=0 


[Me interesa el for each también  saludos!

Ya vi tus datos, ahora sí puedo estar seguro de que te ayudaría y en realidad hay varias formas de hacerlo, con "For Next" como ya te propusieron, con otras instrucciones y también con "For Each" pero "jugando" con colecciones. Dado que no son "tantos" datos, en términos de velocidad casi te será imperceptible la diferencia entre cualquier forma pero, programáticamente hablando, siempre es más eficiente una instrucción que otra.

Yo hoy ando con tiempo, si deseas probamos algo usando For Each y "colecciones" ¿te parece? Quizá, a la vista, podría parecer medio enredado, pero sería lo más "rápido" y que use menos memoria.

Comentas

Abraham Valencia

[si de acuerdo con la propuesta saludos!

Te paso mi ejemplo que aproximadamente trabajaré con 1000 datos

https://www.dropbox.com/s/i78f3ez9qu88lil/PRUEBA%20v2.xlsx?dl=0 

Buenas tardes Abraham, es probable que trabaje aprox. con 1000 datos (consolidado de notas)

Probemos con este ejemplo

https://www.dropbox.com/s/i78f3ez9qu88lil/PRUEBA%20v2.xlsx?dl=0 

Al final se me presentaron 1000 cosas pero bueno, así es la vida.

Vi tu segundo archivo y usando For-Each y colecciones, con casi 1000 registros se logra eliminar lo deseado en 17.07 segundos (4 GB RAM, 3 GHZ de velocidad). Otras opciones lo hacen en 17.4 y 18 segundos. Aquí una alternativa para que veas lo de las "colecciones":

https://1drv.ms/x/s!ApkTgtnWCTgAiAnPKlvO_CMe9p-0

Aunque para ser sincero yo creo que para disminuir el tipo lo idóneo sería una columna auxiliar con algo así:

=CONTAR.SI(D7:O7,"<=10")

Entonces en lugar de recorrer todas las celdas, solo se recorre esa columna auxiliar y las que tienes cero se borran. Eso disminuirá el tiempo en más de 90%

Comentas

Abraham Valencia

[Hola Abraham buenos días, de hecho que la macro es lenta, será por que los datos tienen que pasar por varios bucles, probaré con la segunda opción que indicas Gracias saludos.

Fuera de los bucles y las comparaciones, en general cuando a la propiedad "EntireRow" le aplicas el método "Delete", tiende a ser lento, por si acaso, y siendo en este caso cientos de filas, se entiende un poco al menos esa lentitud.

Examinando/tabajando solo la columna auxiliar, que recomiendo, se baja el tiempo a 13 segundos, pero como comento, es el "Delete".

Podría intentarse con algo como

Range("P3, P34, P45, P56").EntireRow.Delete

Y en lugar de los rangos se usa una variable con todos los rangos necesarios:

Range(variable).EntireRow.Delete

Pero el objeto Range tiene un límite de 255 caracteres en su argumento y los rangos a borrar suman... 3572 solo en este caso :(

Quizá dividiendo cada 255 caracteres y borrando en partes, pero, serían, en ese caso como 14 veces, no sé que tanto tiempo se ahorre con eso, aunque siempre sera mejor que borrar 300 veces (una por una). El dilema en ese caso es que es algo un poco "trabajoso".

Así vamos hasta el momento

Un abrazo

Abraham Valencia

Por cierto, por la noche puse 90% de mejora, error de interpretación, la mejora con columna auxiliar, y borrando fila por fila, es de solo 25%

Abraham Valencia

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas