Bucles
En ocasiones necesitamos repetir un determinado proceso un determinado número de veces, o hasta que se cumpla una condición, o mientras se cumpla una condición.
OOo Basic incorpora dos estructuras para crear bucles o repeticiones:
- For...Next
- Do...Loop
Veamos ejemplos de cada una de ellas:
Estructura For...Next
La sintaxis de esta estructura es:
For Variable = Inicio To Fin [Step Salto]
'codigo
[Exit For]
Next [Variable]
Lo indicado entre corchetes es opcional.
Empecemos con un ejemplo sencillo:
Option Explicit
Sub PortarseBien
Dim Contador As Integer
'Inicia el contador con los limites especificados
For Contador = 1 To 2
'Este es el código que se ejecuta el numero de veces
'especificado con los limites en nuestro caso 2 veces
MsgBox "Tengo que portarme bien"
Next
End Sub
Para hacer uso de la estructura For...Next, es necesaria una variable de apoyo; en nuestro caso escogimos la variable Contador; con frecuencia encontraras que algunos programadores usan la letra I, J, K, L, N y siguientes como contadores, pero tu eres libres de elegir y usar la variable que más te plazca.
El código anterior solo mostrará el mensaje dos veces, que son las indicadas por el límite inferior y superior del contador especificadas con 1 To 2.
Veamos otro ejemplo para establecer valores más grandes y de paso, aprovecharemos para ver como “sumar” cadenas de texto. En programación, la “suma” de cadenas de texto se conoce como “concatenar” y no es otra cosa que pegar cadenas de texto una tras la otra:
Sub TuNombre
Dim Nombre As String
Dim Apellido1 As String
Dim Apellido2 As String
Dim NombreCompleto As String
Nombre = InputBox( "¿Cual es tu Nombre?")
Apellido1 = InputBox( "¿Cual es tu primer Apellido?")
Apellido2 = InputBox( "¿Y el segundo?")
NombreCompleto = Nombre + Apellido1 + Apellido2
MsgBox "Tu nombre completo es: " + NombreCompleto
End Sub
En el código solicitamos el nombre y apellido, y al final, lo mostramos en sólo una línea de texto. En el ejemplo hemos utilizado el operador +, pero es más común usar el operador ampersan (&) como concatenador de cadenas de texto.
Sub TuNombre2
Dim Nombre As String
Dim Apellido1 As String
Dim Apellido2 As String
Dim NombreCompleto As String
Nombre = InputBox( "¿Cual es tu Nombre?")
Apellido1 = InputBox( "¿Cual es tu primer Apellido?")
Apellido2 = InputBox( "¿Y el segundo?")
NombreCompleto = Nombre & Apellido1 & Apellido2
MsgBox "Tu nombre completo es: " & NombreCompleto
End Sub
En el anterior ejemplo el nombre completo se muestra sin espacios. Puedes modificar el código para que muestre espacios entre el nombre y los apellidos.
Hagamos nuestro bucle más grande; probaremos primero con 10.
Sub PortarseBien2
Dim Contador As Integer
Dim Texto As String
For Contador = 1 To 10
Texto = Texto & "Tengo que portarme bien"
Next
MsgBox Texto
End Sub
Para mejorarlo un poco le agregaremos un saldo de línea al final de cada frase:
Sub PortarseBien3
Dim Contador As Integer
Dim Texto As String
For Contador = 1 To 10
Texto = Texto & "Tengo que portarme bien" & Chr(13)
Next
MsgBox Texto
End Sub
Mejoramos agregándole el número a cada línea:
Sub PortarseBien4
Dim Contador As Integer
Dim Texto As String
For Contador = 1 To 10
Texto = Texto & Contador & ".- Tengo que portarme bien" & Chr(13)
Next
MsgBox Texto
End Sub
Límites inferior y superior
Los límites inferior y superior no necesariamente tienen que ser positivos:
For Contador = -5 To 5
La instrucción Step
Tampoco tienen por que ir de uno en uno, cuando podemos ir de dos en dos, de tres en tres o en el intervalo que necesitemos, utilizando la palabra Step.
Sub PortarseBien5
Dim Contador As Integer
Dim Texto As String
For Contador = 1 To 20 Step 2
Texto = Texto & Contador & ".- Tengo que portarme bien" & Chr(13)
Next
MsgBox Texto
End Sub
Step no necesariamente tiene que ser entero, ni positivo:
For Contador = 100 To 10 Step -10
Una práctica habitual es escribir después de la palabra clave Next el mismo nombre de la variable que se ha usado como contador, por ejemplo.
For Contador = 10 To 100 Step 5
' Aquí iría el código
Next Contador
Es muy útil cuando existen varios bucles de repetición anidados.
Sub BuclesAnidados
Dim co1 As Integer, co2 As Integer
For co1 = 1 To 5
For co2 = 1 To 10
Next co2
Next co1
End Sub
La instrucción Exit For
La instrucción Exit For nos sirve para salir anticipadamente de un ciclo For...Next.
Option Explicit
Sub Usando_Exit_For()
Dim co1 As Integer
Dim sLetra As String
Dim sVocales As String
Dim sConsonantes As String
For co1 = 1 To 100
sLetra = Chr( Rnd() * 25 + 65 )
Select Case sLetra
Case "A", "E", "I", "O", "U"
sVocales = sVocales & " " & sLetra
Case "S"
Exit For
Case Else
sConsonantes = sConsonantes & " " & sLetra
End Select
Next
MsgBox "El ciclo termino en: " & co1 & Chr(13) & Chr(13) & _
"Vocales: " & sVocales & Chr(13) & _
"Consonantes: " & sConsonantes, 0, "Ejemplo Exit For"
End Sub
La función Chr(valor) nos devuelve el carácter ASCII correspondiente ha dicho valor. Por ejemplo, la letra A tiene un valor de 65 y la letra Z tiene un valor de 90. Por ello en la línea:
sLetra = Chr( Rnd() * 25 + 65 )
Obtenemos un valor aleatorio entre 65 y 90 y Chr nos devuelve el carácter correspondiente al valor aleatorio obtenido. Después evaluamos si es una vocal, si es la letra S o si es una consonante. Sólo en el caso de que el carácter devuelto sea una S, interrumpimos el ciclo For...Next y salimos utilizando el Exit For.
Al final mostramos el valor del contador para saber si terminó el ciclo o salió antes.
Estructura Do...Loop
Al tipo de ciclo usado en For..Next, algunos autores le llaman determinado pues sabemos donde empieza y donde termina, hay otro tipo de ciclos llamados indeterminados, pues dependen de otras condiciones para empezar o terminar el ciclo; veamos cuales son:
La instrucción Do...Loop, también nos sirve para crear repeticiones, pero en lugar de usar un contador, se evalúa una condición para decidir cuando terminar un bucle e incluso cuando empieza o si empieza.
Veamos ejemplos:
Sub DameTuNombre
Dim Nombre As String
Do
Nombre = InputBox( "¿Cual es tu Nombre?")
Loop While Nombre = "”
End Sub
Analicemos línea por línea el código anterior.
Sub DameTuNombre 'Iniciamos la macro
Dim Nombre As String 'Declaramos una variable de texto
Do 'Iniciamos el bucle
Nombre = InputBox( "¿Cual es tu Nombre?") 'Solicitamos un valor, en este caso un nombre
Loop While Nombre = "" 'Continuamos el bucle “'''mientras'''” la condición sea VERDADERA
End Sub 'Finalizamos la macro
Mediante el código forzamos al usuario a escribir un valor en el cuadro de dialogo, si bien suele ser deseable proporcionar al usuario una forma de cancelar o interrumpir el bucle. Veamos una primera alternativa:
Sub DameTuNombre2
Dim Nombre As String
Dim Respuesta As Integer
Do
Nombre = InputBox( "¿Cual es tu Nombre?" )
If Nombre = "" Then
Respuesta = MsgBox( "Al parecer no escribiste nada, ¿realmente quieres salir?", 32 + 4, "Salir" )
'Recuerda que un 6 significa que el usuario presiono el botón SI
If Respuesta = 6 Then
'Establecemos la variable con cualquier cosa para que termine el bucle
Nombre = "cualquier cosa"
End If
End If
Loop While Nombre = ""
End Sub
El código anterior parece que funciona bien, pero hay una simple forma de “engañarla”. Prueba a introducir varios espacios y verás que sale inmediatamente. Para subsanar este inconveniente haremos uso de una función integrada en OOo Basic que sirve para eliminar los espacios vacíos al inicio y al final de una cadena: la instrucción Trim, que se utiliza de la siguiente forma.
Sub DameTuNombre3
Dim Nombre As String
Dim Respuesta As Integer
Do
Nombre = InputBox( "¿Cual es tu Nombre?" )
'''Nombre = Trim( Nombre )'''
If Nombre = "" Then
Respuesta = MsgBox( "Al parecer no escribiste nada, ¿realmente quieres salir?", 32 + 4, "Salir" )
'Recuerda que un 6 significa que el usuario presiono el botón SI
If Respuesta = 6 Then
'Establecemos la variable con cualquier cosa para que termine el bucle
Nombre = "cualquier cosa"
End If
End If
Loop While Nombre = ""
End Sub
Hemos mejorado su comportamiento, si bien siempre se nos puedes ocurrir más alternativas por prever o mejorar el código.
La instrucción Until
Veamos otra variante de esta estructura que nos permite invertir la lógica de la condición:
Sub DameTuNombre4
Dim Nombre As String
Do
Nombre = InputBox( "¿Cual es tu Nombre?")
Loop '''Until''' Nombre <> ""
End Sub
Ahora con la instrucción Until evaluamos la variable Nombre. Mientras sea diferente de vacía, es decir, contenga algo, el bucle se repetirá, con lo que estamos definiendo hasta cuando se repite. La condición tiene que seguir siendo verdadera para que el bucle termine.
Veamos ahora la macro completa, con validación incluída.
Sub DameTuNombre5
Dim Nombre As String
Dim Respuesta As Integer
Do
Nombre = InputBox( "¿Cual es tu Nombre?")
Nombre = Trim( Nombre )
If Nombre = "" Then
Respuesta = MsgBox( "Al parecer no escribiste nada, ¿realmente quieres salir?", 32 + 4, "Salir" )
'Recuerda que un 6 significa que el usuario presiono el botón SI
If Respuesta = 6 Then
'Establecemos la variable con cualquier cosa para que termine el bucle
Nombre = "cualquier cosa"
End If
End If
Loop Until Nombre <> ""
End Sub
Tal vez te preguntaras ¿porque dos formas de hacer lo mismo? No todos tenemos el mismo modo de razonar. En casi todo y más en programación, hay más de una forma de hacer las mismas cosas, lo cual enriquece y es bueno para ampliar horizontes.
La instrucción Do While
Las dos variantes de la estructura que hemos visto ejecutan el código escrito entre Do..Loop al menos una vez. Si necesitamos o queremos controlar que en caso de cumplirse una condición no se ejecute ni una sola vez, pasaremos la instrucción al inicio de la estructura de la siguiente forma:
Sub DameTuNombre6
Dim Nombre As String
Dim Lista As String
'Solicitamos un dato
Nombre = InputBox( "¿Dame un Nombre?")
'Le quitamos los espacios sobrantes al inicio y al final
Nombre = Trim( Nombre )
'Iniciamos el bucle, si la variable es diferente de vacía
Do While Nombre <> ""
'Formamos una lista de los nombres introducidos
Lista = Lista & " - " & Nombre
'Solicitamos otro nombre
Nombre = Trim( InputBox( "¿Dame otro Nombre?") )
Loop
'Si la lista contiene algo lo mostramos
If Lista <> "" Then
MsgBox Lista
End If
End Sub
Destacamos las dos formas en que hacemos uso de la instrucción InputBox: la primera de forma directa y la segunda, de forma anidada.
Anidar funciones resulta muy familiar si eres un usuario medio/avanzado de cualquier hoja de calculo. La anidación de funciones resulta muy útil en programación.
Existe otra variante para lograr el mismo propósito, utilizando la palabra clave Until, en lugar de While.
La instrucción Exit Do
Si deseamos finalizar anticipadamente un bucle Do...Loop, podemos utilizar la palabra clave Exit Do de la siguiente forma:
Option Explicit
Sub Usando_Exit_Do()
Dim sClave As String
Dim sTmp As String
sClave = "mellon"
Do
sTmp = Trim(InputBox("Habla amigo y entra"))
If sTmp = "mellon" Then
MsgBox "Y se abren las puertas de Moria"
Exit Do
End If
Loop Until sTmp = "salir"
End Sub
Por lo tanto, disponemos de dos formas de terminar el bucle: la condición final, y utilizando Exit Do.
Ten cuidado con los ciclos indeterminados, una condición mal planteada te puede dejar dentro de un ciclo infinito |
Con los elementos vistos hasta ahora ya se pueden hacer muchas cosas. Podemos empezar a a pensar en como automatizar esos pasos tan repetitivos y tediosos que a veces se nos presentan; para ello, tendremos presente siempre en mente el diagrama que vimos en el apartado Declarar Variables.
Si tienes dudas acerca de lo aquí explicado, tienes algún problema con AOO, o quieres ampliar la información, no dudes en dirigirte al Foro Oficial en español de Apache OpenOffice para Macros y API UNO |