You are on page 1of 26

Càlcul Digital Aplicat

Mètodes Matemàtics
Curs 2012-2013

IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 1
Microsoft
®
Visual Basic 2010 Express
Fundamentos de Programación en Visual Basic 2010
Este documento pretende ser una guía básica de programación para desarrollar aplicaciones en Microsoft
®

Visual Basic 2010 y por tanto se va a centrar en la escritura correcta de código.
Se supone que el alumno ya está familiarizado con el diseño de formularios y cómo se incluyen controles en
éstos. En el documento referido a controles se describen cuáles están disponibles en esta versión del
programa y cuál es su utilidad. Por tanto se parte de que el alumno ya conoce cómo ejecutar un programa,
bien pulsando un elemento de un menú, bien activando un evento de uno de los controles situados en el
formulario, como puede ser pulsar un botón de comando.
Por tanto, se parte de una aplicación en la que se ha completado la fase de diseño y se ha de incluir el
código para que funcione correctamente.
Escritura de código en una aplicación
Seguidamente se va a empezar a escribir código para observar cómo se declaran las variables, cómo se
modifican propiedades de controles en código, cómo se ejecutan métodos y cómo se llama a eventos.
La primera etapa que se va a explicar es escribir el código para poder finalizar la aplicación. Para ello, se
activa la ventana de código correspondiente al formulario se pulsa la lista desplegable que aparece en la
parte izquierda. Tal como se puede apreciar aparece una lista con todos los controles incluidos en el
formulario con su nombre correspondiente, la referencia al formulario, y la palabra (GENERAL), que hace
alusión al código que no está vinculado a un objeto específico.

2 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Código para finalizar una aplicación
Normalmente, en una aplicación siempre se incluye un botón o una opción de menú que permite finalizar el
programa. En este caso, si hay una opción de menú denominada mnuSalir que tiene como objetivo finalizar
la aplicación, se selecciona. A continuación se despliega la lista de la parte derecha en la que aparecen todos
los eventos posibles que se pueden producir con el elemento del menú.

Como se puede observar en la figura, Microsoft
®
Visual Basic rellena automáticamente el código que hace
referencia al encabezado del evento CLICK, que corresponde a pulsar el botón principal del ratón sobre el
elemento del menú. Éste es el evento predefinido para este tipo de control, sin embargo se puede apreciar
que se dispone de un número considerable de eventos tal como aparece en la lista desplegable, aunque los
que se van a emplear en la asignatura van a ser básicamente aquéllos que realicen una acción, como
efectuar un cálculo numérico, y no los que se emplean en el diseño de las aplicaciones.
Una vez seleccionado el evento CLICK se puede escribir el código siguiente:

Si se ejecuta la aplicación, tras guardar los cambios, y se pulsa sobre el elemento de menú mnuSalir se
observa que se cierra el formulario y que finaliza la aplicación. Como es lógico, en todos los proyectos
siempre se debe incluir un botón de comando o una opción de menú que permita salir del formulario.
Se puede observar que el texto escrito tras el apóstrofe está en un color diferente al del resto de la línea.
Ello es debido a que este texto es un comentario, no es código de Microsoft
®
Visual Basic 2010. Conviene
añadir comentarios a lo largo del código que clarifiquen el propósito del mismo, especialmente en algoritmos
complejos.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 3
Declaración de variables y constantes
En primer lugar, en cualquier código que se desarrolle, se deben haber declarado las variables y constantes
con las que se trabaja. Si se ha configurado correctamente Microsoft
®
Visual Basic 2010 está activada la
opción OPTION EXPLICIT que obliga a que todas las variables y constantes se declaren explícitamente, activada
también la opción OPTION STRICT y desactivada la opción OPTION INFER.
Si en algún momento de la ejecución aparece un mensaje como el siguiente en la lista de errores, indica que
una variable no se ha declarado. La aplicación resalta qué variable es, y el programador debe declarar dicha
variable en el lugar correspondiente, si no la ha declarado, o bien, si se trata de un error tipográfico porque
ha escrito mal la variable, rectificarlo.

Además el programa incorpora una serie de ayudas visuales cuando se desarrolla el código que son de gran
utilidad para prevenir los errores.

Para declarar una variable o constante se debe tener en cuenta los siguientes aspectos
▪ Si es una variable o una constante
▪ El tipo de dato que ha de contener
▪ El ámbito de validez
Cuando se declara una variable o constante, deben especificarse claramente todos estos aspectos. Las
declaraciones de variables o constantes siempre se efectúan en el inicio del procedimiento o del módulo en
el que se utilicen o en el caso de variables empleadas únicamente en bucles al inicio de éstos.
Variable o constante
Como su nombre indica, una variable contiene información que puede modificarse a lo largo del programa, o
entre ejecuciones diferentes del programa. Así, las dimensiones de una matriz pueden no cambiar a lo largo
de la ejecución de un programa pero, si se cambia el problema es probable que las dimensiones sean
diferentes. Por ello, las dimensiones de esa matriz se declararán como variables.
Una constante es un valor que no va a modificarse nunca. Ejemplos de constantes serían el número e o el
número π, el límite de precisión admisible en un método numérico, el número máximo de iteraciones
permitidas, etc. En todos estos casos, los valores no cambian a lo largo de un problema ni al resolver
problemas diferentes. La palabra clave que permite especificar que es una constante es Const.
4 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Microsoft
®
Visual Basic 2010 en su librería matemática (Math) incluye los valores de las dos constantes
matemáticas más empleadas, mencionadas previamente, e y π. Se presenta en la siguiente línea cómo se
puede acceder a dichos valores en una línea de código, junto a algunas funciones matemáticas.
valor = Math.Cos(2.0 * Math.PI * frec * t)
numero = Math.Log10(Math.E)
Tipo de dato
Una variable o constante debe de estar asociada siempre a un tipo de dato. Es obligatorio, al declarar una
variable o constante, especificar qué tipo de dato contiene. Los tipos de datos más habituales en la
resolución de problemas numéricos son los siguientes:
▪ VALORES ENTEROS
Según el margen de valores que se vayan a emplear se dispone de tres tipos de datos:
Short (2 bytes): Admite valores de -32 768 a 32 767
Integer (4 bytes): Admite valores de -2 147 483 648 a 2 147 483 647.
Long (8 bytes): Admite valores de -9 223 372 036 854 775 808 y 9 223 372 036 854 775 807
Las operaciones con números enteros que devuelven números enteros no tienen asociado error de
redondeo. Además las operaciones con números enteros son más rápidas que con otro tipo de
datos. El tipo de valor entero que se va a emplear habitualmente es Integer.
▪ VALORES EN COMA FLOTANTE
Según el margen de valores que se vayan a emplear se dispone de dos tipos de datos:
Single (4 bytes): El margen de valores va de -3,4028235E+38 a -1,401298E-45 para valores
negativos, de 1,401298E-45 a 3,4028235E+38 para valores positivos y el cero.
Double (8 bytes): Los valores van de -1,79769313486231570E+308 a -4,94065645841246544E-324
para números negativos, de 4,94065645841246544E-324 a 1,79769313486231570E+308 para valores
positivos y el cero.
El tipo de valor en coma flotante que se va a emplear habitualmente es Double.
▪ VALORES DE CADENA DE TEXTO
String (el número de bytes depende de la longitud de la cadena).
▪ VALORES LÓGICOS
Boolean (2 bytes): Únicamente puede contener valores de Sí o No (True o False).
Ámbito de validez
Una variable o constante tiene asociado un ámbito de validez, es decir, en qué lugar de código se puede
emplear dicha variable o constante. Existen tres ámbitos de validez:
▪ PROCEDIMIENTO O LOCAL: El ámbito de validez está restringido al de la rutina en la que se encuentran
declaradas. Es la mejor opción, ya que así se evitan problemas de modificación del valor de las
variables en diferentes lugares del código, lo que haría muy difícil la depuración de errores. Se pueden
emplear los mismos nombres de las variables en rutinas diferentes sin que haya que tener ninguna
precaución especial.
Existen dos variantes de variables locales. La forma normal es declarar una variable mediante la
palabra Dim. En este caso, cada vez que se llama al procedimiento en Visual Basic se inicializa la
variable (si es una variable numérica se pone a cero, si es una cadena de texto es la cadena vacía y si
es una variable booleana su valor es FALSE), a no ser que se especifique directamente otro valor.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 5
Si la variable se declara mediante la sentencia Static, indica que la variable es estática. Eso quiere
decir que al acabar de ejecutar el procedimiento la variable permanece residente en memoria y al
llamar de nuevo al procedimiento sigue manteniendo su último valor.
▪ MÓDULO: En este caso el valor de la variable o constante es accesible en todos los procedimientos que
se incluyen en el formulario o módulo en el que se trabaja. Únicamente se deben declarar como
variables de módulo aquellas que compartan información entre diferentes procedimientos
de evento. La palabra clave que se emplea para declarar una variable de módulo es Private.
▪ GLOBAL: Su ámbito de validez es para todo el proyecto, o sea se puede utilizar y modificar en cualquier
procedimiento de la aplicación. Se debe evitar su uso, salvo en casos muy justificados. La palabra
clave que se emplea para declarar una variable global es Public.
Por tanto, hay que dejar bien claro, respecto al ámbito de validez de las variables que, siempre que sea
posible, lo mejor es definirlas como de procedimiento (locales). En el caso de que haya variables cuyo valor
se deba compartir por diferentes eventos (y únicamente en este caso) de un formulario se deben definir
como variables de módulo. Las variables globales tienen que ser de uso muy restringido y, por tanto, no es
en absoluto recomendable su uso ya que la depuración de errores se complica enormemente.
Ejemplos de declaraciones de variables y constantes
VARIABLES Y CONSTANTES LOCALES O DE PROCEDIMIENTO
Dentro de un procedimiento, y justo después del encabezado irían las declaraciones:
Private Sub Procedimiento()
Const EPS As Double = 0.0000001 'Declaración de una constante
Dim valor1 As Integer 'Declaración de un número entero
Dim valor1a As Integer = 165 'Número entero con valor inicial
Static valor2 As Double 'Declaración de una variable estática
Static valor2a As Double = 1.0 'Variable estática con valor inicial
Se pueden declarar varias variables en la misma línea con su correspondiente tipo de datos
Dim valor As Integer, i As Integer, texto As String
Sin embargo en Microsoft
®
Visual Basic 2010 se pueden definir las variables sin poner al lado su tipo de
datos ya que toman el tipo de datos correspondiente al que aparece después de la primera variable a la que
se le asigna uno. Así en la siguiente línea de código
Dim valor, i As Integer, texto As String
la primera variable, valor es de tipo INTEGER al igual que la segunda, i, que también lo es. Lo normal es
separar las variables por tipo y definir en líneas separadas los tipos de datos diferentes.
VARIABLES Y CONSTANTES DE MÓDULO
Estas variables o constantes se deben declarar en la sección DECLARACIONES del apartado (GENERAL) del
código del formulario o módulo en donde se declaren.
Private Const EPS As Double = 0.00000000000001 'Declaración de una constante
Private valorModulo As Integer 'Declaración de una variable
La palabra Private que aparece al declarar la variable o constante hace referencia a que tiene un ámbito
de validez privado de dicho módulo (o formulario), con lo que los procedimientos exteriores a dicho módulo
o formulario no pueden acceder a dicho valor.
6 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Es posible que haya variables, por ejemplo un contador como puede ser la variable i, que aparezcan en más
de un procedimiento del módulo (o formulario). Hay que tener claro que no se deben definir como
variables de módulo ya que en cada procedimiento tienen un valor específico que no debe compartirse
con otros procedimientos, por tanto se deben declarar siempre como variables locales y no de módulo.
VARIABLES Y CONSTANTES GLOBALES
Las variables globales únicamente se pueden declarar en la sección DECLARACIONES de (GENERAL) en un
módulo de código (Module con nombre de archivo *.vb). Si se realiza en un formulario, Visual Basic
generará automáticamente un error como dicha variable aparezca en cualquier otro elemento. Para que eso
no suceda, debe incluirse en un módulo de código.
Public Const EPS As Double = 0.00000000000001 'Declaración de una constante
Public final As Boolean 'Declaración de una variable booleana global
Public numDades As Long 'Declaración de una variable entera global
CONSIDERACIONES SOBRE DECLARACIONES DE VARIABLES Y CONSTANTES
Hay que tener clara la prioridad a la hora de definir el ámbito de validez de las variables. La mayor prioridad
es la de las variables locales o de procedimiento, a continuación las de módulo y por último las globales. Sin
embargo, como ya se ha comentado anteriormente, el uso de variables de módulo y, en especial, globales
se debe restringir al máximo para evitar problemas de interferencias entre valores de variables.
Existen una serie de directrices a la hora de declarar variables y constantes.
En una aplicación de Visual Basic, las variables públicas o globales se deben usar sólo cuando no exista
ninguna otra forma cómoda de compartir datos entre formularios. Cuando haya que usar variables
globales, es conveniente declararlas todas en un único módulo agrupadas por funciones y dar al módulo
un nombre significativo que indique su finalidad, como PUBLIC.VB.
Una variable tiene alcance global si se declara como PUBLIC en un módulo. Una variable tiene alcance de
nivel de módulo si se declara como PRIVATE en un módulo o en un formulario, respectivamente.
Constantes
El cuerpo del nombre de las constantes se debe escribir en mayúsculas con las palabras separadas por el
carácter subrayado. Por ejemplo:
MAX_I TERACI ONES Número máximo de iteraciones
LI MI TE_ERROR Valor límite del error de cálculo de un método numérico
Variables
El cuerpo de un nombre de variable se debe iniciar en minúscula y debe tener la longitud necesaria para
describir su funcionalidad. Si está formado por más de una palabra, las siguientes deben empezar por
mayúsculas. Por ejemplo:
numer oDat os
val or Fi nal
Para nombres que se usen con frecuencia o para términos largos, se recomienda usar abreviaturas
estándar para que los nombres tengan una longitud razonable. En general, los nombres de variables con
más de 32 caracteres pueden ser difíciles de leer.
Cuando se usen abreviaturas, hay que asegurarse de que sean coherentes en toda la aplicación. Alternar
aleatoriamente entre CNT y CONTAR dentro de un proyecto provoca una confusión innecesaria.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 7
Vectores y matrices
Visual Basic permite definir variables que contengan varios valores del mismo tipo de dato. De esta manera
se puede manipular de forma eficiente vectores y matrices. Para acceder a uno de los valores de dicha
matriz o vector, basta únicamente especificar el índice correspondiente y el sistema accede directamente a
dicho valor. Todo lo explicado previamente en cuanto a variables es aplicable a los vectores o matrices.
Para declarar un vector se indica con el nombre de la variable y a continuación un paréntesis abierto y otro
cerrado. En el caso de una matriz, como tiene más de un índice, hay que incluir una coma entre los
paréntesis para cada nuevo índice que incluya. Así, una matriz de dos índices se indica con un paréntesis
abierto, una coma y un paréntesis cerrado tal como se muestra en la instrucción siguiente.
Dim matriz(,) As Double, texto() As String 'matriz: 2 índices; texto(): 1 índice
Antes de asignar valores a un vector o matriz es necesario especificar sus dimensiones. Si las dimensiones
son función de variables, ya que pueden cambiar entre ejecuciones, la matriz se puede declarar en función
de dichas dimensiones.
Dim matriz(n, m) As Double, texto(nPalabras) As String
Sin embargo, es posible que dentro del mismo procedimiento, en ocasiones, se deba cambiar las
dimensiones. En este caso se emplea la instrucción REDIM, tal como se muestra a continuación. Al efectuar
una instrucción REDIM se inicializan todos los valores de la matriz.
ReDim matriz(0 To n, 0 To m), texto(nPalabras)
En el primer tipo de declaración se indican el límite de los índices, entre 0 y n el primero y entre 0 y m el
segundo. En el segundo caso únicamente se indica el límite superior, nPalabras. En Visual Basic 2010 el
valor inferior del índice para todos los vectores o matrices es siempre 0, por tanto en este segundo
caso los elementos del vector texto son los comprendidos entre 0 y nPalabras, y por tanto el número de
elementos del vector es de nPalabras+1. Normalmente no se especifican los dos límites en vectores
y matrices ya que es reiterativo.
En algunas ocasiones puede que no se conozca a priori el número de elementos que debe contener un
vector o matriz, ya que es posible que se lean desde un archivo del que se desconoce el número de datos
que contiene. En estos casos si se va cambiando la dimensión de la matriz o vector se debe evitar perder los
valores ya incluidos en el vector o matriz. Para ello se debe incluir la palabra clave PRESERVE después de la
instrucción REDIM.
ReDim Preserve matriz(n, m), texto(nPalabras)
Se debe de tener en cuenta que con la palabra clave Preserve únicamente se puede cambiar el valor
del último índice de la matriz. En un vector no representa ningún problema, pero en el caso de una matriz
únicamente podrá variarse el segundo índice, no el primero. En caso de que se intentara modificar los límites
del primer índice se generaría un error en tiempo de ejecución.
En algunos casos algunas matrices pueden tener un número de dimensiones fijas, y que no cambie en
distintas ejecuciones. Este tipo de matrices, denominadas estáticas se pueden declarar directamente con sus
dimensiones, que no se podrán modificar cuando se ejecute el programa. Un ejemplo podría ser la
declaración de una matriz que contenga un tablero de un Sudoku que tiene un número fijo de filas y
columnas (9x9). En este caso se podría declarar la matriz tal como se muestra en la siguiente instrucción.
Dim matrizSudoku(8, 8) As Integer
8 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Inicialización de valores en matrices
Para asignar valores a vectores y matrices es posible efectuarlo o bien igualando elemento a elemento de la
matriz o vector al valor deseado o en Visual Basic 2010 es posible inicializar los valores que contiene un
vector o matriz de la siguiente manera que es mucho más cómoda de escribir en código.
Dim a(,) As Double = {{1.5, 3.2, -4.5}, {-3.2, 4.1, 6.0}} 'Matriz (2x3)
Dim ncoef() As Integer = {1, 3, 2, -4, 5, -3, -2, 4, 1, 6, 0} 'Vector de 11 elementos
En este caso no se indican las dimensiones de la matriz o vector ya que directamente a partir de la
asignación de valores el sistema obtiene las correspondientes dimensiones.
Estructuras
En ciertas ocasiones, el programador debe poder trabajar con algún tipo de variable que no se encuentra
disponible en los tipos de datos del lenguaje de programación. En Visual Basic es posible crear estructuras
que permiten una mayor flexibilidad al lenguaje. Un ejemplo sería crear una estructura que permitiera
trabajar con números complejos.
Las estructuras se deben incluir en la sección de declaraciones de un módulo (*.vb), no un formulario, de la
forma siguiente.

Public Structure Complex
Public r As Double
Public i As Double

Public Sub New(ByVal re As Double, ByVal im As Double)
Me.r = re
Me.i = im
End Sub

Public Sub New(ByVal re As Double)
Me.r = re
Me.i = 0.0
End Sub

Public Sub New(ByVal Number As Complex)
Me.r = Number.r
Me.i = Number.i
End Sub

Public Overrides Function ToString() As String
If Me.i < 0.0 Then
Return Me.r & " " & Me.i & " i"
Else
Return Me.r & " +" & Me.i & " i"
End If
End Function

Public Shared Function Real(ByVal a As Complex) As Double
Return a.r
End Function

Public Shared Function Imag(ByVal a As Complex) As Double
Return a.i
End Function

IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 9

Se puede observar que es posible definir la operación suma entre números complejos, e igualmente la resta,
el producto, la división, operaciones entre números reales y complejos, el módulo de un número complejo,
etc. Una vez definida la estructura se pueden declarar variables o constantes, crear matrices o vectores
exactamente igual que si fuera cualquier otro tipo de dato.
Dim variableCompleja As Complex
Se pueden asignar valores y se pueden operar como si fuera cualquier otra variable.
variableCompleja = New Complex(5.0)
resultado = Math.Atan(Complex.Imag(variableCompleja) / Complex.Real(variableCompleja))
variableCompleja += New Complex(5.0, 5.0)
Public Shared Function Polar(ByVal modulus As Double,
ByVal argument As Double) As Complex
Return New Complex(modulus * Math.Cos(argument), modulus * Math.Sin(argument))
End Function

Public Shared Operator +(ByVal a As Complex, ByVal b As Complex) As Complex
Return New Complex(a.r + b.r, a.i + b.i)
End Operator

……

End Structure
10 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Estructuras de control
ESTRUCTURAS DE SELECCIÓN
Estructura If…Then…ElseIf…Else…End If
ESTRUCTURA SIMPLE
La primera estructura de selección es la que se presenta a continuación.
If Condicion Then
Instrucciones
End If
Tal como se puede apreciar, cada vez que Condicion sea cierto se realizarán una serie de Instrucciones,
mientras que en caso contrario, no se hará nada. Condicion puede ser una variable booleana, el resultado
de una expresión lógica, un valor devuelto por una función o incluso el valor de una variable, que se deberá
convertir en valor booleano. Cualquier valor que haya se debe transformar, si no lo es, en una variable de
tipo booleano, teniendo en cuenta que si corresponde a una variable numérica, si es cero se transforma en
FALSE y cualquier otro valor corresponderá a un valor TRUE. En función de dicho resultado se ejecutan o no
las correspondientes instrucciones.
ESTRUCTURA DOBLE
Se puede complicar algo más la estructura IF…THEN añadiendo que efectúe otras instrucciones en caso de
que la condición sea falsa. Así, la estructura doble queda de la siguiente manera.
If Condicion Then
Instrucciones_1
Else
Instrucciones_2
End If
En este caso si Condicion es cierta ejecuta Instrucciones_1, mientras que en caso contrario se ejecuta
Instrucciones_2.
ESTRUCTURA MÚLTIPLE
Por último, en este caso la estructura múltiple permite seleccionar una opción entre varias posibles, según el
caso en que la condición sea cierta. En este caso el sistema ejecutará la primera condición que sea cierta, y
no comprobará el resto de condiciones, aún en el hipotético caso de que éstas también fueran ciertas.
If Condicion1 Then
Instrucciones_1
ElseIf Condicion2 Then
Instrucciones_2
ElseIf Condicion3 Then
Instrucciones_3
Else
Instrucciones_n
End If
Si ninguna de las condiciones fuera cierta, se ejecutarían las Instrucciones_n, que corresponden al caso
de la opción Else.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 11
Estructura Select Case…Case…Case Else…End Select
La estructura SELECT CASE es una estructura en la que se compara un valor de referencia, en el caso
presentado Valor, con diferentes opciones. En el momento en que se cumpla la condición, se ejecutará el
código correspondiente y se continuará la ejecución a partir del final de la estructura. Eso quiere decir que
se ejecutará siempre la primera condición que sea cierta. A diferencia de la estructura IF vista
anteriormente, el valor con el que se comparan las condiciones en una estructura SELECT CASE es siempre el
mismo.
Select Case Valor
Case Caso_1
Instrucciones_1
Case Caso_2
Instrucciones_2
Case Caso_3
Instrucciones_3
Case Else
Instrucciones_n
End Select
Si no se cumple que Valor corresponde a alguno de los casos Caso_1, Caso_2 o Caso_3, se ejecutarán las
instrucciones incluidas en la opción Else.
ESTRUCTURAS DE REPETICIÓN
Estructura For…Next
Las estructuras de repetición FOR...NEXT se emplean cuando se conoce el número de veces que se debe
repetir las instrucciones que contiene. Ello implica que el contador que se utiliza para saber cuántas veces se
ha ejecutado el bucle debe ser un número entero, ya que en caso contrario no se puede asegurar que la
estructura se ejecute un número correcto de veces.
Dim i, numMaximo As Integer

...
For i = 1 To numMaximo
Instrucciones
Next
En este caso el código contenido en Instrucciones se ejecuta el número de veces que contenga la variable
numMaximo. El paso, si no se especifica lo contrario, es de uno en uno. En caso de que sea diferente, es
necesario especificarlo añadiendo al final de la línea que contiene el FOR la expresión STEP junto con el
tamaño del paso.
La siguiente estructura FOR...NEXT sería incorrecta, ya que no cumple con los requerimientos explicados
Dim i, numMaximo As Double

...
For i = 1 To numMaximo / 10 Step 0.1
Instrucciones_1
Next
En este caso, el número de veces que se ejecutará Instrucciones_1 no tiene porqué corresponder al
indicado en la variable numMaximo por problemas de redondeo. Por tanto, debe quedar claro, que los bucles
FOR…NEXT se deben realizar siempre con variables de tipo entero (SHORT, INTEGER o LONG y de las tres,
preferiblemente con INTEGER, ya que es en con la que se ejecuta más rápidamente), nunca con valores
SINGLE o DOUBLE. Si se necesita calcular valores en coma flotante de simple o doble precisión, se debe
12 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
evaluar a partir de la variable contador, mediante una adecuada conversión del valor, utilizando operaciones
o funciones disponibles en Visual Basic.
Además, se debe tener en cuenta que dentro de una estructura FOR...NEXT, no se debe variar el valor de la
variable contador, en este caso la variable i, ni el límite de las iteraciones, numMaximo.
Otra consideración importante es que si el paso del contador es positivo y el límite final del contador es
menor que el inicial, o bien el paso del contador es negativo y el límite final del contador es mayor que el
inicial, no se ejecutarán nunca las instrucciones que se encuentran dentro del bucle FOR...NEXT.
Estructuras Do…Loop
Existen cuatro variantes de estructuras DO...LOOP en Visual Basic. Todas ellas se emplean cuando se
desconoce a priori el número de iteraciones que se van a realizar en un procedimiento, como es el caso de
algoritmos numéricos de tipo iterativo.
Do While Condicion
Instrucciones
Loop
En este caso mientras Condicion sea cierta se ejecutarán las Instrucciones. Como ya se ha comentado
anteriormente, Condicion puede ser una variable booleana, el resultado de una expresión lógica, un valor
devuelto por una función o incluso el valor de una variable, que se deberá convertir en valor booleano.
Cualquier valor que haya se debe transformar en una valor de tipo booleano, teniendo en cuenta que si
corresponde a una variable numérica, si es cero se transforma en FALSE y cualquier otro valor corresponderá
a un valor TRUE. En función de dicho resultado se ejecutan o no las correspondientes instrucciones.
Do Until Condicion
Instrucciones
Loop
Este caso es equivalente al anterior, sólo que mientras Condicion sea falso se ejecutarán las
Instrucciones. En estos dos casos descritos es posible que Instrucciones no se ejecuten nunca porque
como se evalúa la Condicion al inicio según el resultado obtenido puede saltar directamente al final de la
estructura.
Do
Instrucciones
Loop While Condicion
En este caso, Instrucciones se repetirán mientras Condicion sea cierta.
Do
Instrucciones
Loop Until Condicion
Este caso es equivalente al anterior, sólo que Instrucciones se repetirá mientras Condicion sea falsa. En
estos dos últimos casos Instrucciones se ejecutará al menos una vez, ya que Condicion se evalúa al final
de la estructura.
Estructura While…End While
Existe otra estructura que se puede emplear en Visual Basic cuando se desconoce a priori el número de
iteraciones que se van a realizar en un procedimiento.
While Condicion
Instrucciones
End While
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 13
Este caso es equivalente a la primera de las variantes vista de la estructura DO...LOOP. Mientras Condicion
sea cierta se ejecutarán las Instrucciones. Condicion puede ser una variable booleana, el resultado de
una expresión lógica, un valor devuelto por una función o incluso el valor de una variable, que se deberá
convertir en valor booleano. Cualquier valor que haya se debe transformar en una valor de tipo booleano,
teniendo en cuenta que si corresponde a una variable numérica, si es cero se transforma en FALSE y
cualquier otro valor corresponderá a un valor TRUE. En función de dicho resultado se ejecutan o no las
correspondientes instrucciones.
ERRORES EN LAS ESTRUCTURAS DE CONTROL
ERROR POR EXCESO DEL NÚMERO DE ITERACIONES
Es posible que en los bucles DO…LOOP o WHILE…END WHILE se entre en un bucle sin fin. En rutinas de cálculo
que correspondan a métodos iterativos, se debe incluir un contador dentro del bucle para que, dentro de la
condición de salida del bucle, se verifique el número de iteraciones efectuadas y si se sobrepasa el límite,
finalizar el bucle.
ERROR DE ANIDAMIENTO
Las estructuras deben estar correctamente anidadas, o sea toda estructura de control ha de estar contenida
dentro de otra. En caso contrario Visual Basic generará un error por lo que el programa no puede compilarse
y no inicia la ejecución.

El editor de código de Visual Basic indica, tal como se muestra en la imagen anterior, la existencia de este
problema, ya que están cruzadas las estructuras. Además el propio editor, en el momento en que se escribe
la primera línea de una estructura y se valida la entrada con el retorno de carro, añade automáticamente la
línea final de la estructura. De esta forma es más difícil que se produzca este tipo de error.
ERROR POR MODIFICACIÓN DEL CONTADOR
Aunque Microsoft
®
Visual Basic no dé un error en ejecución, no se debe modificar dentro de un bucle
FOR…NEXT el valor de la variable contador, ya que se pueden obtener resultados inesperados.
Si se desea cambiar el valor del contador con un paso distinto de uno, se puede cambiar el valor de éste
(STEP) al especificar los datos en la sentencia correspondiente del bucle FOR…NEXT. Si lo que se desea es
salir del bucle, se deben emplear las instrucciones específicas para ello.
Por supuesto, tampoco se debe modificar dentro del bucle el valor superior (TO) o el incremento (STEP) de
cada iteración si están especificados como variables, ya que los resultados que se pueden obtener son
impredecibles. Para efectuar este tipo de iteraciones con estas modificaciones se debe emplear un bucle
DO…LOOP o WHILE…END WHILE en vez de un FOR…NEXT.
14 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Instrucciones Exit Do, Exit While y Exit For
Es posible finalizar la ejecución de un bucle FOR...NEXT, un bucle DO...LOOP o un bucle WHILE…END WHILE
antes de tiempo empleando las instrucciones Exit For, Exit Do o Exit While, respectivamente.
Normalmente dichas instrucciones se encuentran dentro de una estructura IF...THEN, de forma que cuando
se cumpla una condición determinada finalice el bucle.
For i = 1 To nIteraciones
Instrucciones_1
If Condicion Then
Exit For
End If
Instrucciones_2
Next
Si hubiera más de una estructura FOR...NEXT anidada, la sentencia Exit For finaliza el bucle interior. La
sentencia Exit Do se puede aplicar además de a los bucles DO...LOOP descritos anteriormente, a un bucle
DO…LOOP sin condiciones ni al inicio ni al final, tal como se muestra en el siguiente fragmento de código.
Do
Instrucciones_1
If Condicion Then
Exit Do
End If
Instrucciones_2
Loop
Como se puede apreciar en este caso, el bucle DO…LOOP no tiene ninguna condición al inicio o al final, con lo
que presenta un aspecto de bucle sin fin. Por ello es necesario incluir la sentencia Exit Do entre medio para
que pueda finalizar en algún momento dicho bucle cuando se cumpla la condición especificada por el
programador.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 15
Funciones y Subrutinas
DECLARACIÓN DE UN PROCEDIMIENTO
Al igual que con las variables, es necesario declarar correctamente los procedimientos contenidos en una
aplicación. En Visual Basic se dispone de dos tipos de procedimientos: funciones y subrutinas. El primero de
ellos devuelve un valor, del tipo con el que se haya declarado la función, mientras que el segundo no
devuelve un valor.
Al declarar un procedimiento se debe especificar:
▪ Ámbito de validez
▪ Tipo de procedimiento
▪ Nombre del procedimiento
▪ Parámetros de entrada y salida
▪ En el caso de una función, el tipo de dato que devuelve.
Se va a especificar cómo se debe de incluir cada uno de ellos en la declaración.
ÁMBITO DE VALIDEZ
Al igual que sucede con las variables, los procedimientos pueden ser accesibles desde todos los
procedimientos de una aplicación, o bien únicamente desde los procedimientos de su módulo o formulario.
Así, si se declara como Private, únicamente es accesible por parte de los procedimientos que se
encuentran en su mismo módulo o formulario. Es la opción por defecto para todos los procedimientos que se
encuentran dentro de un formulario (se supone que el formulario contiene procedimientos que únicamente
interaccionan con los elementos que contiene).
Si se declara como Public, es accesible por todos los procedimientos de la aplicación. Es la opción por
defecto para todos los procedimientos que se encuentran en un módulo de código (se supone que el código
del módulo tiene propósito general y se debe de poder acceder desde cualquier lugar de la aplicación).
TIPO DE PROCEDIMIENTO
Si se desea que el procedimiento sea una función se emplea la palabra clave Function, mientras que si se
desea que sea una subrutina la palabra clave es Sub. La única diferencia entre ambas es que el
procedimiento Function devuelve un valor, mientras que el Sub, no.
NOMBRE DEL PROCEDIMIENTO
El cuerpo de un nombre de un procedimiento se debe escribir en mayúsculas y minúsculas, empezando por
mayúsculas y debe tener la longitud necesaria para describir su funcionalidad. Además, los nombres de
procedimientos deben empezar con un verbo, como I NICIARNOMBREMATRIZ o CERRARDIÁLOGO, para indicar que
realizan una acción.
PARÁMETROS DE ENTRADA Y SALIDA
A continuación se incluyen los parámetros de entrada y salida del procedimiento. Para cada parámetro se
debe de especificar su nombre y el tipo de dato que contiene. Si un procedimiento no necesita parámetros
de entrada y salida, se puede dejar en blanco. Los nombres que se especifiquen en los parámetros tienen la
consideración de variables locales y por tanto su ámbito de validez es el del procedimiento donde se
declaren. Tomarán los valores correspondientes a los que se les asigne desde el procedimiento en el que se
les llame.
Cuando se definan los parámetros es obligatorio especificar si el paso de los valores al procedimiento se
hace por valor (ByVal) o por referencia (ByRef). Pasar por valor una variable a un procedimiento quiere
16 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
decir que se hace una copia del valor que contiene el programa principal en la memoria del procedimiento.
Todos los cambios que se hagan en él no afectarán al programa principal. Es la opción que se debe emplear
en aquellas variables que corresponden a valores de entrada al procedimiento.
Pasar por referencia una variable a un procedimiento quiere decir que se envía al procedimiento la posición
de memoria de la variable del programa principal. Todos los cambios que se hagan sobre la variable
afectarán al programa principal ya que se hacen directamente sobre la posición de memoria. Es la opción
que se debe emplear en aquellas variables que son de entrada y salida o únicamente de salida del
procedimiento.
En Microsoft
®
Visual Basic 2010, si no se especifica nada, el programa considera que la variable se pasa por
valor y añade ByVal automáticamente.
TIPO DE DATO
En el caso de los procedimientos Function se debe especificar el tipo de dato que devuelve. El tipo de dato
es uno cualquiera de los vistos anteriormente para las variables o constantes, o bien matrices o vectores.
Para que la función devuelva el valor deseado, se puede asignar dentro del código de la función dicho valor
al nombre de la función, o bien emplear la instrucción Return junto al valor que devuelve la función.
EJ EMPLOS DE DECLARACIÓN DE PROCEDIMIENTOS
Public Sub EscribirValores(ByVal valor As Integer, ByRef referencia As Integer)
Private Sub cmdActivar_Click()
Public Function CalcularAleatorio(ByVal inferior As Integer,
ByVal superior As Integer) As Integer
LLAMADA A UN PROCEDIMIENTO
La forma de llamar a una rutina depende de si ésta es un procedimiento SUB o FUNCTION. En caso de que sea
un procedimiento SUB se debe escribir el nombre del procedimiento seguido por los parámetros que se
incluyen en la lista de argumentos entre paréntesis. Para el ejemplo anterior sería:
EscribirValores(numeroValor, numeroReferencia)
Para un procedimiento Function la llamada se suele hacer desde una expresión, o bien se asigna su
resultado a una variable. Así, dos formas posibles de llamar a la función declarada anteriormente sería:
If CalcularAleatorio(3, 9) = 8 Then
resultado = CalcularAleatorio(minimo, maximo)
El orden en que aparecen los argumentos en cualquier llamada a un procedimiento debe corresponder,
exactamente, al que aparece en la definición de éste. Si no es así, no se obtiene un resultado correcto ya
que pueden ocurrir dos situaciones diferentes. La primera se produce cuando los tipos de variables no
coinciden o faltan o sobran parámetros de la lista. En este caso Microsoft
®
Visual Basic genera un error de
compilación y el usuario debe corregirlo para poder ejecutar la aplicación. La segunda situación corresponde
al caso en que los parámetros se dieran desordenados pero que los tipos de datos coincidieran. En esta
ocasión no se produce un error de compilación, con lo cual es más difícil de localizar ya que no se obtiene
ningún mensaje de error por parte del programa. Por tanto, se debe ser especialmente cuidadoso con las
llamadas a procedimientos para referir adecuadamente los parámetros necesarios y pasarlos en el orden
correspondiente.
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 17
EJ EMPLOS DE PROCEDIMI ENTOS
Este primer ejemplo corresponde a una función. Se puede observar cómo se devuelve la función dentro del
código.

Este procedimiento rellena un control DATAGRIDVIEW con los valores contenidos en la matriz MATRIU.

Si se desea presentar una matriz en la que además de los datos numéricos se tenga un vector con los
encabezados de fila y otro con los encabezados de columna se puede efectuar con un procedimiento que
tenga el mismo nombre, pero como los parámetros son distintos Visual Basic podrá distinguir a cuál de los
procedimientos corresponde la llamada.

Public Function CalcularAleatorio(ByVal inferior As Integer, ByVal _
superior As Integer) As Integer
Return CInt(Int((superior - inferior + 1) * Rnd() + inferior))
End Function
Public Sub PresentacionGrid(ByVal dgvw As DataGridView, ByVal matriu(,) As Double)
Dim nfilas As Integer = matriu.GetLength(0), ncols As Integer = matriu.GetLength(1)
With dgvw
.RowCount = nfilas
.ColumnCount = ncols
For i As Integer = 0 To nfilas - 1
.Rows(i).HeaderCell.Value = "Fila " & (i + 1).ToString
For j As Integer = 0 To ncols - 1
.Item(j, i).Value = matriu(i, j).ToString
Next j
Next i
For j As Integer = 0 To ncols - 1
.Columns(j).HeaderCell.Value = "Col " & (j + 1).ToString
Next j
.AutoResizeRowHeadersWidth(
DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
.AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells)
.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
.DefaultCellStyle.SelectionBackColor = .DefaultCellStyle.BackColor
.DefaultCellStyle.SelectionForeColor = .DefaultCellStyle.ForeColor
'.Enabled = False
End With
End Sub
Public Sub PresentacionGrid(ByVal dgvw As DataGridView, ByVal matriu(,) As Double,
ByVal TitulosCol() As String, ByVal TitulosFila() As String)
Dim nfilas As Integer = matriu.GetLength(0), ncols As Integer = matriu.GetLength(1)
With dgvw
.RowCount = nfilas
.ColumnCount = ncols
For i As Integer = 0 To nfilas - 1
.Rows(i).HeaderCell.Value = TitulosFila(i)
For j As Integer = 0 To ncols - 1
.Item(j, i).Value = matriu(i, j).ToString
Next j
Next i
For j As Integer = 0 To ncols - 1
.Columns(j).HeaderCell.Value = TitulosCol(j + 1)
Next j
.TopLeftHeaderCell.Value = TitulosCol(0)
.AutoResizeRowHeadersWidth(
DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
18 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010

El siguiente procedimiento efectúa el producto de dos matrices. Devuelve con el nombre de la función si es
posible realizar dicho producto (una variable Booleana que será True si se puede efectuar el producto y
False si no es posible). Además, en caso de que sea posible efectúa la operación.

Esta función se podría llamar de dos formas posibles, como función o como subrutina, ya que Visual Basic
admite ambas opciones en este caso:
If MultiplicarMatrices(matrizA, matrizB, matrizC) Then
MultiplicarMatrices(matrizA, matrizB, matrizC)
Para comprobar el distinto comportamiento de una variable si se para por valor o por referencia se puede
visualizar qué ocurre si se llama el siguiente procedimiento desde el programa principal, que se incluye
posteriormente.

Aunque como ya se ha comentado, la opción por defecto que asigna automáticamente Visual Basic 2010 es
por valor, se debe especificar en cada caso el tipo de paso de datos y siempre se debe verificar que se ha
efectuado correctamente según los criterios indicados anteriormente.
.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
.AutoResizeRows(DataGridViewAutoSizeRowsMode.AllCells)
.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
.DefaultCellStyle.SelectionBackColor = .DefaultCellStyle.BackColor
.DefaultCellStyle.SelectionForeColor = .DefaultCellStyle.ForeColor
'.Enabled = False
End With
End Sub
Public Function MultiplicarMatrices(ByVal a(,) As Double, ByVal b(,) As Double,
ByRef c(,) As Double) As Boolean
Dim nFilasA As Integer = a.GetLength(0) - 1, nColsA As Integer = a.GetLength(1) - 1
Dim nFilasB As Integer = b.GetLength(0) - 1, nColsB As Integer = b.GetLength(1) - 1

If nColsA = nFilasB Then
ReDim c(nFilasA, nColsB)
For i As Integer = 0 To nFilasA
For j As Integer = 0 To nColsB
For k As Integer = 0 To nColsA
c(i, j) += a(i, k) * b(k, j)
Next
Next
Next
Return True
End If
Return False
End Function
Public Sub PasarValores(ByVal valor As Integer, ByRef referencia As Integer)

referencia = referencia + 1
valor = valor + 1
End Sub

Private Sub cmdActivar_Click()
Dim nval, nref As Integer

Do
PasarValores(nval, nref)
'Escribir nval y nref en algún control para visualizar su valor
Loop While nref < 100
End Sub
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 19
Acceso a ficheros secuenciales
La mayoría de valores disponibles para el cálculo numérico se encuentran almacenados en ficheros de tipo
secuencial. Por tanto, es necesario conocer cómo poder leer el contenido de dichos archivos.
Normalmente, los archivos de tipo secuencial incluyen valores en el que el separador entre ellos es una
coma y el separador decimal es un punto. Se deben tener en cuenta esa información para poder leer
correctamente la información contenida en el fichero.
Se puede suponer que se dispone de un archivo que contiene cuatro valores numéricos diferentes, los dos
primeros enteros y los otros dos en coma flotante separados por comas, tabuladores o espacios en blanco.
El siguiente código permite leer los cuatro valores y asignar cada uno a una variable diferente.

También es posible efectuar la misma operación con un código alternativo que permitirá, como veremos
posteriormente más opciones.

La variable archivo, que aparece en ambos códigos, se puede generar desde el programa principal
empleando el control OPENFILEDIALOG disponible en esta versión de Visual Basic y que permite seleccionar el
archivo deseado.
Public Sub LeerSecuencial_VB(ByVal archivo As String, ByRef valor1 As Integer,
ByRef valor2 As Integer, ByRef valor3 As Double, ByRef valor4 As Double)
Dim NumArxiu As Integer

NumArxiu = FreeFile()
FileOpen(NumArxiu, archivo, OpenMode.Input)
Input(NumArxiu, valor1)
Input(NumArxiu, valor2)
Input(NumArxiu, valor3)
Input(NumArxiu, valor4)
FileClose(NumArxiu)
End Sub

Public Sub LeerSecuencial_NET(ByVal archivo As String, ByRef valor1 As Integer,
ByRef valor2 As Integer, ByRef valor3 As Double, ByRef valor4 As Double)

Dim aux(-1) As String
Dim k As Integer = 0
Dim MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(archivo)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(" ")

Dim currentRow As String() = MyReader.ReadFields()
'Evita errores en el caso de más de un espacio entre datos
For i As Integer = 0 To currentRow.Length - 1
If Len(currentRow(i)) > 0 Then
ReDim Preserve aux(k)
aux(k) = currentRow(i)
k += 1
End If
Next

valor1 = CInt(aux(0))
valor2 = CInt(aux(1))
valor3 = Val(aux(2))
valor4 = Val(aux(3))
End Sub
20 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Si se desea leer una matriz de datos en coma flotante de la que se conoce el número de filas y el número de
columnas porque son los dos primeros valores contenidos en el fichero, el código que permite leerla es el
siguiente.

Este código permite leer cualquier archivo con contenido numérico en forma matricial, en el que los dos
primeros valores del fichero indican el número de filas y el número de columnas respectivamente, y el resto
de valores los almacena en una matriz que se ha declarado como Double.
La siguiente rutina efectúa la misma operación mediante una estrategia diferente de lectura de fichero.

Se podría leer dicha matriz desde el programa principal mediante el siguiente código, en donde
dlgOpenFile corresponde a un control OPENFILEDIALOG que se encuentra en el correspondiente formulario y
dgvwMatriu y dgvwMatriu1 corresponden a sendos controles DATAGRIDVIEW.

Public Sub LeerSecuencialMatriz_VB(ByVal archivo As String, ByRef a(,) As Double)
Dim nFilas, nCols As Integer
Dim numArxiu As Integer

numArxiu = FreeFile()
FileOpen(numArxiu, archivo, OpenMode.Input)
Input(numArxiu, nFilas)
Input(numArxiu, nCols)
'Los índices van desde 0 hasta nFilas - 1 o nCols - 1, respectivamente
ReDim a(nFilas - 1, nCols - 1)
For i As Integer = 0 To nFilas - 1
For j As Integer = 0 To nCols - 1
Input(numArxiu, a(i, j))
Next
Next
FileClose(numArxiu)
End Sub
Public Sub LeerSecuencialMatriz_NET(ByVal archivo As String, ByRef a(,) As Double)
Dim nFilas, nCols As Integer
Dim currentRow As String()
Dim MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(archivo)

MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(" ", vbTab, ",")
currentRow = MyReader.ReadFields()

nFilas = CInt(currentRow(0))
nCols = CInt(currentRow(1))
ReDim a(nFilas - 1, nCols - 1)
For i As Integer = 0 To nFilas - 1
currentRow = MyReader.ReadFields()
For j As Integer = 0 To nCols - 1
a(i, j) = Val(currentRow(j))
Next
Next
End Sub
Private Sub mnuLeerDatos2_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles mnuLeerDatos2.Click
Dim matriuA(-1, 0), matriuB(-1, 0) As Double

dlgOpenFile.InitialDirectory = My.Application.Info.DirectoryPath
dlgOpenFile.FileName = ""
dlgOpenFile.Title = "Abrir fichero de datos"
dlgOpenFile.Filter = _
"Archivos de texto (*.txt)|*.txt|Todos los archivos (*.*)|*.*"
dlgOpenFile.ShowDialog()
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 21

A continuación se va a presentar otra forma de poder leer información de un fichero secuencial. Hay que
tener en cuenta que no siempre se incluye, como información en el fichero, el número de valores que
contiene. Por ello es necesario saber leer un fichero en el que se desconoce el número de datos, sin que se
genere un error.
En primer lugar se va a escribir el código para leer la información contenida en un fichero línea a línea. Para
ello se debe escribir el siguiente procedimiento en el módulo.

En él se emplea el bucle DO UNTIL EOF(NUMARXIU)…LOOP, que se va a ejecutar hasta que se alcance el final
del archivo. Esta estructura también es posible emplearla para leer valores de un vector sin conocer
previamente el número de elementos que contiene, ya que bastaría sustituir la función LINE INPUT por INPUT
si los valores fueran numéricos y aunque no se encontraran en líneas distintas.
Una forma alternativa de efectuar la misma operación es la del código siguiente.

Si se desea leer un fichero que contiene una matriz de la que no se dispone ni del número de filas ni del de
columnas, se puede escribir el siguiente código. En caso de que sea posible leer la matriz se puede operar
posteriormente con ella.

Dim archivo As String = dlgOpenFile.FileName
If len(archivo) > 0 Then
LeerSecuencialMatriz_VB(archivo, matriuA)
PresentacionGrid(dgvwMatriu, matriuA)
LeerSecuencialMatriz_NET(archivo, matriuB)
PresentacionGrid(dgvwMatriu1, matriuB)
End If
End Sub
Public Sub LeerSecuencialLineas_VB(ByVal archivo As String, ByRef a() As String)
Dim nLineas, NumArxiu As Integer

NumArxiu = FreeFile()
FileOpen(NumArxiu, archivo, OpenMode.Input)
Do Until EOF(NumArxiu)
ReDim Preserve a(nLineas)
a(nLineas) = LineInput(NumArxiu)
nLineas += 1
Loop
FileClose(NumArxiu)
End Sub
Public Sub LeerSecuencialLineas_NET(ByVal archivo As String, ByRef a() As String)
Dim nLineas As Integer
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(archivo)
Do
ReDim Preserve a(nLineas)
a(nLineas) = sr.ReadLine()
nLineas += 1
Loop Until a(nLineas - 1) Is Nothing
sr.Close()
End Sub
Public Function LeerMatlab_VB(ByVal archivo As String,
ByRef datos(,) As Double) As Boolean
Dim nCols, numFitx, nColsN As Integer, nFilas As Integer = 0
Dim valores(-1), datosAux(-1, 1) As Double
Dim aux As String, separador As String = ""

numFitx = FreeFile()
FileOpen(numFitx, archivo, OpenMode.Input)
22 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010

Do Until EOF(numFitx)
aux = LineInput(numFitx)
If nFilas = 0 Then
separador = DefinirDelimitador(aux)
End If
EstablecerSeparacion(aux, nColsN, valores, separador)
If nFilas = 0 Then
nCols = nColsN
Else
If nCols <> nColsN Then
Return False
End If
End If
ReDim Preserve datosAux(nCols - 1, nFilas)
For i As Integer = 0 To nCols - 1
datosAux(i, nFilas) = valores(i)
Next
nFilas += 1
Loop
FileClose(numFitx)
ReDim datos(nFilas - 1, nCols - 1)
For i As Integer = 0 To nFilas - 1
For j As Integer = 0 To nCols - 1
datos(i, j) = datosAux(j, i)
Next
Next
Return True
End Function

Public Sub EstablecerSeparacion(ByVal cadena As String, ByRef ndatos As Integer,
ByRef valores() As Double, ByVal separador As String)
Dim pos As Integer

ndatos = 0
Do While CBool(InStr(1, cadena, separador))
pos = InStr(1, cadena, separador)
If IsNumeric(Left(cadena, pos - 1)) Then
ReDim Preserve valores(ndatos)
valores(ndatos) = Val(Left(cadena, pos - 1))
ndatos += 1
End If
cadena = Right(cadena, Len(cadena) - pos)
Loop
If IsNumeric(cadena) Then
ReDim Preserve valores(ndatos)
valores(ndatos) = Val(cadena)
ndatos += 1
End If
End Sub

Public Function DefinirDelimitador(ByVal cadena As String) As String
Dim espacio, tabulador, coma As Integer

For i As Integer = 1 To Len(cadena)
Select Case Mid(cadena, i, 1)
Case vbTab
tabulador += 1
Case ","
coma += 1
Case " "
espacio += 1
End Select
Next
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 23

Se puede efectuar el mismo proceso de forma alternativa a partir del código de la siguiente rutina. Como se
puede observar, en este caso esta estrategia es más sencilla.

Sin embargo, en muchas ocasiones la tabla de datos numérica viene acompañada por textos de encabezado
de filas y columnas que describen el contenido de la tabla. Con el código anterior es imposible leer ese tipo
de archivos ya que únicamente espera valores numéricos. Para ello es necesario modificar la rutina anterior.
En este caso el contenido del archivo se separa en una matriz con los valores numéricos y dos vectores que
contienen los encabezados de fila y de columna.
If tabulador > 0 Then
Return vbTab
ElseIf coma > 0 Then
Return ","
ElseIf espacio > 0 Then
Return " "
Else
Return ""
End If
End Function
Public Function LeerMatlab_NET(ByVal archivo As String,
ByRef datos(,) As Double) As Boolean

Dim nFilas As Integer = 0, nCols As Integer
Dim datosAux(-1, 0) As Double
Dim MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(archivo)

MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(" ", vbTab, ",")

Do Until MyReader.EndOfData
Dim currentRow As String() = MyReader.ReadFields
If nFilas = 0 Then
nCols = currentRow.Length
Else
If nCols <> currentRow.Length Then
Return False
End If
End If
ReDim Preserve datosAux(nCols - 1, nFilas)
For i As Integer = 0 To nCols - 1
If Len(currentRow(i)) > 0 Then
datosAux(i, nFilas) = Val(currentRow(i))
Else
Return False
End If
Next
nFilas += 1
Loop
ReDim datos(nFilas - 1, nCols - 1)
For i As Integer = 0 To nFilas - 1
For j As Integer = 0 To nCols - 1
datos(i, j) = datosAux(j, i)
Next
Next
Return True
End Function
24 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010

A partir de estas rutinas básicas, es posible generar los procedimientos necesarios para leer cualquier
combinación de datos en un fichero.
Para poder guardar datos, la estructura es equivalente y lo único que hay que hacer es sustituir las
sentencias que leen datos por aquellas que escriben.
Así, si se desea crear un archivo que contenga cuatro valores numéricos diferentes, los dos primeros enteros
y los otros dos en coma flotante separados por comas, basta ejecutar el siguiente código.

Public Function LeerTablaDatos_NET(ByVal archivo As String, ByRef datos(,) As Double,
ByRef TitulosCol() As String, ByRef TitulosFila() As String) As Boolean

Dim nFilas As Integer = 0, nCols As Integer
Dim datosAux(-1, 0) As Double
Dim MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(archivo)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(" ", vbTab, ",")

Do Until MyReader.EndOfData
Dim currentRow As String() = MyReader.ReadFields
If nFilas = 0 Then
nCols = currentRow.Length
ReDim TitulosCol(nCols - 1)
For i As Integer = 0 To nCols - 1
TitulosCol(i) = currentRow(i)
Next
Else
If nCols <> currentRow.Length Then
Return False
End If
ReDim Preserve datosAux(nCols - 2, nFilas - 1), TitulosFila(nFilas - 1)
TitulosFila(nFilas - 1) = currentRow(0)
For i As Integer = 1 To nCols - 1
If Len(currentRow(i)) > 0 Then
datosAux(i - 1, nFilas - 1) = Val(currentRow(i))
Else
Return False
End If
Next
End If
nFilas += 1
Loop
ReDim datos(nFilas - 2, nCols - 2)
For i As Integer = 0 To nFilas - 2
For j As Integer = 0 To nCols - 2
datos(i, j) = datosAux(j, i)
Next
Next
Return True
End Function
Public Sub EscribirSecuencial_VB(ByVal archivo As String, ByVal valor1 As Integer,
ByVal valor2 As Integer, ByVal valor3 As Double, ByVal valor4 As Double)
Dim NumArxiu As Integer

NumArxiu = FreeFile()
FileOpen(NumArxiu, archivo, OpenMode.Output)
WriteLine(NumArxiu, valor1, valor2, valor3, valor4)
FileClose(NumArxiu)
End Sub
IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010 25
Se puede, también al escribir datos en un fichero utilizar otra alternativa tal como se observa en el siguiente
código.

Si se quiere escribir una matriz de datos en coma flotante y especificar el número de filas y el número de
columnas que serán los dos primeros valores que contendrá el fichero, el código que permite escribirla es el
siguiente.

El código equivalente con la opción de usar la clase StreamWriter es el que se presenta seguidamente. El
archivo generado es idéntico al anterior.

Si se pretende escribir la matriz con la estructura de filas y columnas y sin valores al inicio que especifiquen
su número de filas y columnas, se puede generar a partir del siguiente código.

Public Sub EscribirSecuencial_NET(ByVal archivo As String, ByVal valor1 As Integer,
ByVal valor2 As Integer, ByVal valor3 As Double, ByVal valor4 As Double)

Dim file As System.IO.StreamWriter =
My.Computer.FileSystem.OpenTextFileWriter(archivo, False)
file.WriteLine("{0},{1},{2},{3}", valor1, valor2, valor3, valor4)
file.Close()
End Sub
Public Sub EscribirSecuencialMatriz_VB(ByVal archivo As String, ByVal a(,) As Double)
Dim numArxiu As Integer

numArxiu = FreeFile()
FileOpen(numArxiu, archivo, OpenMode.Output)
WriteLine(numArxiu, a.GetLength(0), a.GetLength(1))
For i As Integer = 0 To a.GetLength(0) - 1
For j As Integer = 0 To a.GetLength(1) - 1
Write(numArxiu, a(i, j))
Next
Next
FileClose(numArxiu)
End Sub
Public Sub EscribirSecuencialMatriz1_NET(ByVal archivo As String, ByVal a(,) As Double)

Dim file As System.IO.StreamWriter =
My.Computer.FileSystem.OpenTextFileWriter(archivo, False)
file.WriteLine("{0},{1}", a.GetLength(0), a.GetLength(1))
For i As Integer = 0 To a.GetLength(0) - 1
For j As Integer = 0 To a.GetLength(1) - 1
file.Write("{0},", a(i, j))
Next
Next
file.WriteLine()
file.Close()
End Sub
Public Sub EscribirSecuencialMatriz2_NET(ByVal archivo As String, ByVal a(,) As Double)

Dim file As System.IO.StreamWriter =
My.Computer.FileSystem.OpenTextFileWriter(archivo, False)
For i As Integer = 0 To a.GetLength(0) - 1
For j As Integer = 0 To a.GetLength(1) - 2
file.Write("{0},", a(i, j))
Next
file.WriteLine("{0}", a(i, a.GetLength(1) - 1))
Next
file.Close()
End Sub
26 IQS, J .J .Molins, CDA-MM. Curso 2012-2013. Fundamentos de Programación en Visual Basic 2010
Por último, se presenta cómo escribir un archivo en el que además de los valores numéricos de los
resultados se incluyan los encabezados de filas y columnas para poder describir su contenido y etiquetar
convenientemente los valores. En este caso, además, se ha escogido separar los diferentes valores con
tabuladores, de forma que acabe teniendo la apariencia de una tabla de datos que sería posible importar
desde diferentes programas para un tratamiento posterior (informes, etc.).

A partir de los ejemplos presentados, es posible modificarlos para adaptarse a cualquier formato o necesidad
que se desee, sin dificultad.
Para crear un archivo secuencial y poder comprobar si la rutina desarrollada lo lee correctamente, basta
generarlo con el Bloc de Notas. Igualmente, para visualizar si el código desarrollado ha creado un archivo
con la estructura deseada, basta abrirlo, igualmente, con dicho programa.
Public Sub EscribirTablaDatos_NET(ByVal archivo As String, ByVal datos(,) As Double,
ByVal TitulosCol() As String, ByVal TitulosFila() As String)

Dim file As System.IO.StreamWriter =
My.Computer.FileSystem.OpenTextFileWriter(archivo, False)
For j As Integer = 0 To TitulosCol.Length - 2
file.Write("{0}" & vbTab, TitulosCol(j))
Next
file.WriteLine("{0}", TitulosCol(TitulosCol.Length - 1))
For i As Integer = 0 To datos.GetLength(0) - 1
file.Write("{0}" & vbTab, TitulosFila(i))
For j As Integer = 0 To datos.GetLength(1) - 2
file.Write("{0}" & vbTab, datos(i, j))
Next
file.WriteLine("{0}", datos(i, datos.GetLength(1) - 1))
Next
file.Close()
End Sub