Excel.Macros: bucle for…next

Seguimos con las instrucciones de control de flujo, ésta vez vamos a comentar la que podemos utilizar cuando conocemos a priori el número de iteraciones que debemos realizar; ya que nos ofrece un control muy sencillo del numero de pasadas por el bucle y nos facilita un contador, que normalmente podremos utilizar como índice, o para cualquier otro servicio

La estructura de la sentencia es:

For <inicializacion de contador> to valor_final_contador

…… sentencias a ejecutar

next contador

Veamos la instrucción con un ejemplo

Supongamos que queremos reflejar los 56 colores de que disponemos, en las primeras 56 celdas de la hoja (A1:A56). Haremos:

Dim a As Integer
Range("A1:A56").Select

For a = 1 To 56 ' con a=1 hasta 56
    Selection.Cells(a).Interior.Color = ActiveWorkbook.Colors(a)
Next a

El bucle For….Next va dando vueltas, cambiando el valor de a , incrementandolo en 1, en cada pasada; cuando A vale 57, sale del bucle. ¿El resultado de esta tonteria?:

2013-06-06_19h43_50
La macro anterior, nos ha generado el muestrario de colores de que dispone excel en su tabla de colores (ActiveWorkbook.Colors(a)) que hemos obtenido porque la variable a, ha estado modificándose desde 1 a 56, según le decía la instrucción for.

Si no decimos nada, este bucle va modificando la variable en incrementos de 1, si deseáramos cambiar este factor para, por ejemplo, hacer que avance de 3 en 3,  podríamos añadir la palabra step 3:

For a=1 to 56 step 3

Veamos otro ejemplo, aunque la instrucción es lo suficiente sencilla para que se haya entendido.

Vamos a recorrer las primeras 10 filas y 10 columnas, y les iremos poniendo el número de orden que les corresponde, para hacerlo, anidaremos un for dentro de otro, el primero me irá dejando en a los valores de fila (de o a 10) y el segundo, el interior, me ira dejando en b los valores de columna, también de 0 a 10; cada vez que el interior haga 10 pasadas, saldrá y el exterior hará una más, para que él vuelva a hacer 10 pasadas… aquí os dejo el código:

For a = 1 To 10
    For b = 1 To 10
        ActiveSheet.Cells(a, b).Value = "Cell( " & a & "," & b & " )"
        ActiveSheet.Cells(a, b).NumberFormat = "@"
    Next b
Next a

y aquí el resultado

Hoja excel con pruebas de macro

Aunque hemos dicho que el bucle For….next esta pensado para recorrer áreas en las que conocemos previamente su longitud, hay veces que deseamos utilizarlo, por la facilidad que representa que el nos controle el indice, y vaya realizando el incremento. Entonces, lo único que necesitamos es conocer la longitud del elemento a recorrer.

Supongamos que queremos recoger todas las celdas con contenido en la columna A, y ponerlas en la columna B, si queremos utilizar For next, necesitamos saber cuantas són, para ello, podemos hacer:

fila = Application.WorksheetFunction.CountA(Range("A:A"))

ésto, me dejará en fila el número de celdas con contenido

Ahora, podemos hace un bucle For..next para ir dejando la información, pero tendremos que tener cuidado con la recogida, ya que puede haber celdas vacias….

Empiezo guardandome el rango de destino en la variable destino y cuento el total de celdas que tendré que dejar en la salida, contando las celdas con algo que tengo en el rango Origen

Set destino = Range("b1")
fila = Application.WorksheetFunction.CountA(Range("A:A"))
If fila = 0 Then Exit Sub
Debug.Print fila

Vereis aparecer en la consola el número de celdas con contenido encontradas.

Ahora monto un bucle que irá moviendo las celdas encontradas hacia la salida, mientras que utilizo un while (lo veremos a continuacion) para esquivar las celdas vacias. (while-wend ira haciendo avanzar la seleccion hasta encontrar una no vacia)

Cuandoel For..next haya movido la cantidad prevista, se para y la macro termina. Aquí está todo el código

im r As Range
Dim fila As Long
Set destino = Range("b1")
fila = Application.WorksheetFunction.CountA(Range("A:A"))
If fila = 0 Then Exit Sub
Debug.Print fila

Application.ScreenUpdating = False
Range("A:A").Select

For a = 1 To fila

While IsEmpty(ActiveCell)
         ActiveCell.Offset(1, 0).Select
Wend
  destino.Cells(a, 1).Value = ActiveCell.Value
  ActiveCell.Offset(1, 0).Select
Next a

Application.ScreenUpdating = True

Ah!, el Application.ScreenUpdating me permite detener (false) la actualización de pantalla mientras corre la macro para ahorrar algo de tiempo.

Acerca de Miguel Garcia

Programador, Desarrollador web, Formador en distintas areas de informatica y director de equipos multidisciplinares.
Esta entrada fue publicada en Excel, Formacion y etiquetada , , , . Guarda el enlace permanente.

2 respuestas a Excel.Macros: bucle for…next

  1. Lucho dijo:

    Gracias!!!

  2. Hola que tal, excelente aporte. Me podrías orientar con los siguiente tengo dos archivos una con una base de datos y otra donde importar datos específicos de la base de datos, esta base de datos corresponde cada hoja a los días del mes actual. te adjunto el modulo que hago para copiar los datos. Lo que quiero es utilizar un bucle que me recorra todas las hojas para hacerlo mas simple. Agradezco tu ayuda. Sub MetodoAbrirLibro()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    ActiveSheet.DisplayPageBreaks = False
    Workbooks.Open “E:\Prueba\cierre inventarios ” & Format(Now, “mmmm”) & “.xls”

    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“1”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B3”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“2”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B4”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“3”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B5”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“4”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B6”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“5”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B7”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“6”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B8”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals
    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    Sheets(“7”).Select
    Range(“D18:E18”).Select
    Selection.Copy

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B9”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Windows(“Indicadores.xlsm”).Activate
    Sheets(“Hoja1”).Select
    Range(“B33”).Select
    Selection.PasteSpecial Paste:=xlPasteValues

    Application.CutCopyMode = Fals

    Asi sucesivamente hasta el ultimo día del mes actual

    Windows(“cierre inventarios ” & Format(Now, “mmmm”) & “.xls”).Activate
    ActiveWindow.Close

    End Sub

Deja un comentario