Sei sulla pagina 1di 22

CURSO DE VB

CAPTULO 91

ndice de contenido
TRABAJANDO CON MATRICES.....................................................................................................2
MATRICES DE UNA DIMENSIN (MATRICES ESTTICAS)................................................2
OTRA MANERA DE CREAR UNA MATRIZ ESTTICA DE UNA DIMENSIN -Funcin
Array()-.......................................................................................................................................4
APROVECHAMOS PARA APRENDER LA FUNCIN Rnd() Y LA INSTRUCCIN
Randomize..................................................................................................................................6
MATRIZ ESTTICA SIN SABER LA LONGITUD DE LA MATRIZ. EJEMPLO DE
SUSTITUCIN DE CARACTERES.........................................................................................7
DETERMINANDO EL TIPO DE DATOS DE LA MATRIZ.........................................................9
MATRICES MULTIDIMENSIONALES (MATRICES ESTTICAS)........................................10
Un ejemplo para matriz de tres dimensiones............................................................................11
MATRICES DINMICAS............................................................................................................13
(y aprovechamos para aprender algunas SQL simples).................................................................13
ReDim Preserve........................................................................................................................16
ALGUNOS ELEMENTOS INTERESANTES DE LA MATRIZ: las funciones UBound() y
LBound() y la instruccin Erase....................................................................................................19
Y ACABAMOS EL TEMA DE MATRICES.....................................................................................21

1 La BD donde estn los ejemplos de este captulo os la podis bajar aqu.

1
Vistame en http://siliconproject.com.ar/neckkito/
TRABAJANDO CON MATRICES
Vamos a aprender cmo podemos trabajar con matrices en
nuestro deambular por VB para Access.

Y la pregunta del milln es... qu es una matriz? Si nos


pusiramos en plan acadmico podramos decir que una
matriz es un conjunto de variables del mismo tipo, las
cuales se hallan indexadas, siendo precisamente su ndice el
indicador de posicin de cada variable en la matriz.

Bonita definicin, verdad?

Vamos a destripar la definicin con un ejemplo. Supongamos que tenemos un tubo (de
plstico, de PVC, de cristal... lo que ms nos guste). Y tenemos unas bolitas (de gomaespuma)
que debemos meter en dicho tubo. Todas las bolitas son del mismo tipo (es decir, todas son
String, todas son Integer, todas son Date...).

La primera bolita lleva escrito: A es la primera letra del abecedario


La segundo bolita lleva escrito: B es la segunda letra del abecedario
La tercera bolita lleva escrito: C es la tercera letra del abecedario
Etc.

Como las hemos introducido en el tubo por este orden, la primera bolita llevar el ndice 1; la
segunda el ndice 2 y la tercera el ndice 3.

Nuestro tubo podra ser representado de la siguiente manera:

Tubo(Primera bolita, Segunda bolita, Tercera bolita)

Qu pasara si en nuestro cdigo quisiramos acceder a la B, segunda letra del abecedario?


Pues como sabemos que la segunda bolita lleva el ndice 2, podramos llamarla de la
siguiente manera:

v2Letra = Tubo(2)

Y si yo escribiera

vLetra = Tubo(3) ?

Ahora todo el mundo me podra contestar que vLetra cogera el valor de la tercera bolita, que
en este caso es C.

Creo que ahora ya podemos tener una idea ms clara de lo que es una matriz (espero). Si
no... bolitas tiene la cosa... je, je...

MATRICES DE UNA DIMENSIN (MATRICES ESTTICAS)


Nuestro ejemplo de las bolitas anterior correspondera a una matriz de una dimensin. Es
decir, que slo hay una dimensin de elementos. Quiz esto pueda resultar inicialmente
confuso, pero cuando veamos las matrices de varias dimensiones lo entenderemos mejor. Un
poco de paciencia!

La denominamos esttica porque conocemos de antemano el nmero de elementos que va a


contener la matriz.

2
Vistame en http://siliconproject.com.ar/neckkito/
Vamos a coger una BD en blanco y, en un formulario, vamos a aadir un botn de comando,
que llamaremos cmdMisDiasSemana. Primero indicaremos el cdigo y despus lo
analizaremos:

El cdigo asignado al evento Al hacer click de ese botn


sera:


Private Sub cmdMisDiasSemana_Click()
'Definimos las variables
Dim numDia As Variant
Dim DiasSem(7)
'Cargamos los valores de la matriz
DiasSem(1) = "Lunes... sueo"
DiasSem(2) = "Martes... casi lunes"
DiasSem(3) = "Mircoles... a la mitad"
DiasSem(4) = "Jueves... an quedan das"
DiasSem(5) = "Viernes... que no pasa"
DiasSem(6) = "Sbado... por fin!"
DiasSem(7) = "Domingo... casi lunes"
'Pedimos al usuario que introduzca un nmero
numDia = InputBox("Introduzca un nmero del 1 al 7", "DIA DE LA SEMANA")
'Controlamos la introduccin
If Not IsNumeric(numDia) Then Exit Sub
If numDia < 1 Or numDia > 8 Then Exit Sub
MsgBox DiasSem(numDia), vbExclamation, "ESTE ES MI DA"
End Sub

Veamos...

.- Definimos la matriz con su nombre y con su nmero de elementos. De ah que hayamos


escrito Dim DiasSem(7)
.- Al igual que hacemos con una variable, que primero la definimos y despus le asignamos un
valor, debemos asignar un valor a la matriz. Cul es la diferencia con una variable normal?
Puesto que debemos asignar tantos valores como elementos tiene la matriz.
.- A la hora de asignar valores a la matriz debemos indicar su posicin dentro de la misma. De
ah que escribamos

DiasSem(i) = Valor, donde i es el indicador de posicin.

.- Para invocar el valor deseado, simplemente llamamos a la matriz con su nmero de posicin.
De ah que hayamos escrito MsgBox DiasSem(numDia), donde numDia nos lo indicaba el
usuario a travs del InputBox.

Tambin os comentar que podemos definir la matriz indicndole la totalidad del rango. Es
decir, que en lugar de escribir

Dim DiasSem(7)

hubiramos podido escribir

Dim DiasSem(1 To 7)

Tambin os comentar que no hace falta empezar por el 1. Si nos interesara podramos definir
la matriz como

3
Vistame en http://siliconproject.com.ar/neckkito/
Dim DiasSem(6 To 13)

E incluso utilizar valore negativos, como

Dim DiasSem(-3 To 4)

Fcil, verdad?

OTRA MANERA DE CREAR UNA MATRIZ


ESTTICA DE UNA DIMENSIN
-Funcin Array()-
Acabamos de ver como declaramos la matriz con el nmero de elementos y despus la
cargbamos con sus valores correspondientes.

Podemos definir las matrices de otra manera, a travs de la funcin Array(). Supongamos que
queremos que el usuario introduzca un valor del 1 al 3, y que aparezca un mensaje con la
correspondencia a un valor en una matriz. Asignaremos el siguiente cdigo al botn cmdFallido
(despus explicar por qu le llamo Fallido). Ntese que no voy a introducir instrucciones de
control en el cdigo.

Private Sub cmdFallido_Click()


'Definimos las variables
Dim vValorUser As Single
Dim vValorMatr As Variant
'Asignamos valor a las variables
vValorMatr = Array(10, 20, 30)
vValorUser = InputBox("Introduzca una valor de 1 a 3", "VALOR")
MsgBox vValorMatr(vValorUser), vbInformation, "Valor"
End Sub

Veamos...

.- Hemos definido una variable, vValorMatr, de tipo variant. Esta ser nuestra matriz.
.- Hemos introducido sus valores a travs de la funcin Array, de la manera siguiente:
vValorMatr = Array(10, 20, 30)

Est todo listo? Pues no. Vamos a hacer una prueba. Hacemos click sobre el botn (con el
formulario en vista formulario) y, cuando nos pide el nmero, escribimos 1.

El sentido comn dice que nos debera devolver 10 (primera posicin). Sin embargo, qu
valor nos devuelve?

Volvemos a hacer click sobre el botn e introducimos el valor 3, y, para nuestra sorpresa,
obtenemos el siguiente resultado:

4
Vistame en http://siliconproject.com.ar/neckkito/
Demasiado alcohol para nuestro Access, quizs? Je, je... Ahora ya podis entender lo de
Fallido.

Vamos a ver qu ocurre.

Con este sistema, y por defecto, el indicador de posicin de la matriz empieza siempre por
cero. Es decir, que nuestra matriz tiene los siguientes valores:

vValorMatr(0) = 10
vValorMatr(1) = 20
vValorMatr(2) = 30

De ah que, al introducir un 1, el valor devuelto sea 20, y al introducir un 3 no exista esta


posicin (y en consecuencia nos salte el error 9).

Cmo solucionamos lo anterior? Pues tenemos dos posibilidades:

1.- Creamos un valor ficticio en la primera posicin (la cero), de manera que nuestra matriz
quedara definida de la siguiente manera:
vValorMatr = Array(0, 10, 20, 30)

Ahora s, si introducimos el valor 1, se nos devolver el 10.

2.- La segunda posicin es indicarle a Access que queremos que nuestra matriz no empiece
con el subndice cero, sino con el 1. Esta instruccin se la debemos indicar en la cabecera del
mdulo a travs de la expresin:

Option Base 1

Es decir, que la cosa nos debera quedar as:

5
Vistame en http://siliconproject.com.ar/neckkito/
Si lo hacemos as y probamos el botn veremos que ahora ya no es fallido.

Debemos tener esto en cuenta a la hora de confeccionar nuestras matrices para no llevarnos
alguna sorpresa desagradable. Ojo!

APROVECHAMOS PARA APRENDER LA FUNCIN Rnd() Y LA


INSTRUCCIN Randomize
Vamos a programar un juego de azar: el ordenador contra el humano. Vamos a simular que se
lanzan tres dados y que si el humano acierta el valor de una de las tiradas gana el humano; en
caso contrario pierde.

Lo que debemos hacer para nuestra planificacin es tener en cuenta los siguiente elementos:
.- El humano debe introducir un valor
.- Los resultados de las tres tiradas vamos a almacenarlos en una matriz
.- Vamos a comparar cada uno de los elementos de la matriz con el valor introducido por el
humano. Si hay coincidencia felicitamos al humano por haber ganado, si no pues lo hundimos
en la miseria.

Y cmo simulamos una tirada al azar? Pues a travs de la instruccin Randomize y la funcin
Rnd().

La instruccin Randomize se utiliza para iniciar el generador de nmeros aleatorios. La funcin


Rnd() es la que nos genera el nmero aleatorio. Para realizar una simulacin de nmeros
aleatorios debemos emplear la siguiente estructura:

Randomize
numAleatorio = Int((valorSuperiorDeseado * Rnd) + 1)

Donde valorSuperioDeseado es, lgicamente, la cota superior de los nmeros que queremos
generar.

Dicho de otra manera, y en el caso de un dado, la cota superior sera 6, por lo que
valorSuperiorDeseado = 6

Con todo lo anterior vamos a ver cmo sera un posible cdigo para nuestro juego. Fijaos que
no slo vamos a felicitar al humano, si acierta, sino que le vamos a decir la primera tirada que
coincida con el resultado igual.

6
Vistame en http://siliconproject.com.ar/neckkito/

Private Sub cmdDados_Click()
'Definimos las variables
Dim vHumano As Single
Dim i As Integer
Dim vDados(3) As Variant
'Iniciamos el proceso aleatorio
Randomize
'Generamos las tiradas y las guardamos en la matriz
vDados(1) = (Int(6 * Rnd) + 1)
vDados(2) = (Int(6 * Rnd) + 1)
vDados(3) = (Int(6 * Rnd) + 1)
'Solicitamos el valor al humano
vHumano = InputBox("Por qu valor apostamos -nmero del 1 al 6-?", "APUESTA")
'Utilizamos un bloque For...Next para realizar las comparaciones, dado que
'i nos dar el ndice de la matriz que estamos examinando
For i = 1 To 3
If vHumano = vDados(i) Then
MsgBox "Enhorabuena! Tu valor ha salido en la tirada nmero " & i, vbExclamation,
"GANASTE"
Exit Sub
End If
Next
'Si no ha habido coincidencias "machacamos" al humano
MsgBox "Mala suerte!. Los las tiradas han sido: " & vbCrLf _
& vDados(1) & " en la primera tirada" & vbCrLf _
& vDados(2) & " en la segunda tirada y" & vbCrLf _
& vDados(3) & " en la tercera tirada", vbCritical, "NO, NO..."
End Sub

MATRIZ ESTTICA SIN SABER LA LONGITUD DE LA MATRIZ. EJEMPLO


DE SUSTITUCIN DE CARACTERES
Si no sabemos la longitud de la matriz a priori, o sabemos que la podemos cambiar por
determinadas circunstancias a lo largo del tiempo, es realmente molesto tener que, cada vez,
acordarse de cambiar la longitud de la matriz.

Para evitar este inconveniente podemos referenciar la longitud de la matriz a una variable o
constante, de manera que si cambia dicha variable o constante tambin nos cambie
automticamente el tamao de la matriz.

Un ejemplo de cmo se utiliza lo anterior, y que adems es un ejemplo til en segn qu


ocasiones, lo constituye un cdigo de sustitucin de caracteres.

La idea es que el usuario introduce un texto en un TextBox (o campo) y acenta las vocales.
Por los motivos que sean nosotros no queremos que las vocales vayan acentuadas. Podemos
utilizar una matriz para recoger los caracteres errneos y aplicar su sustituto.

Utilizaremos la funcin Replace(), que ya vimos en el captulo anterior. Tambin utilizaremos la


funcin Mid() y la funcin Len(). Si tenemos dudas os recomiendo echar una ojeada rpida a
dicho captulo.

Si creamos un cuadro de texto y lo llamamos txtSustituyeTildes podramos, en el evento


Despus de actualizar, generar el cdigo siguiente:

7
Vistame en http://siliconproject.com.ar/neckkito/

Private Sub txtSustituyeTildes_AfterUpdate()
'Definimos las constantes y las variables
Const cadAcentos As String = ""
Const cadSinAcentos As String = "aeiou"
'Definimos las matrices referenciando su longitud a la
longitud
'de las cadenas de texto de las constantes
Dim mtrAcentos(Len(cadAcentos))
Dim mtrSinAcentos(Len(cadSinAcentos))
Dim i As Integer
Dim vText As String
'Asignamos valores a las matrices a travs de un bloque For...Next
'El bloque va recorriendo uno a uno los caracteres.
For i = 1 To Len(cadAcentos)
mtrAcentos(i) = Mid(cadAcentos, i, 1)
Next
For i = 1 To Len(cadSinAcentos)
mtrSinAcentos(i) = Mid(cadSinAcentos, i, 1)
Next
'Cogemos el valor escrito por el usuario
vText = Me.txtSustituyeTildes.Value
'Recorremos uno a uno los caracteres "prohibidos" y, si encontramos
'un carcter acentuado, lo sustituimos en vText
For i = 1 To Len(cadAcentos)
vText = Replace(vText, mtrAcentos(i), mtrSinAcentos(i))
Next
'Reescribimos el texto sin acentos
Me.txtSustituyeTildes.Value = vText
End Sub

Como podemos ver, hay una equivalencia de posiciones entre vocal acentuada o no; es decir, la
ocupa la primera posicin de la matriz mtrAcentos, y la a ocupa la primera posicin de la
matriz mtrSinAcentos. Es necesaria esta correspondencia porque, al utilizar la funcin
Replace() referenciada al nmero de posicin, si el primer valor de la matriz mtrSinAcentos
fuera j lo que hara el cdigo es sustituirnos todas las por j.

Vemos que hemos definido el tamao de la matriz en funcin de la longitud de las constantes.
Por qu? Ni que decir tiene que hubiramos podido definirlas as:

Dim mtrAcentos(5)
Dim mtrSinAcentos(5)

Imaginaos que las definimos as. Ponemos la BD en marcha para la introduccin de datos y
cuando el jefe revisa la informacin nos llama contento a su despacho y nos dice: hay
valores con acentos, y esa no era la idea, verdad?.

Miramos lo que nos indica y nos encontramos todas las vocales maysculas acentuadas. Qu
debemos hacer? Pues redefinir nuestras constantes de la siguiente manera:

Const cadAcentos As String = ""


Const cadSinAcentos As String = "aeiouAEIOU"

La cosa ya est arreglada. Ponemos de nuevo la BD a funcionar y... error 9! Nuestra matriz

8
Vistame en http://siliconproject.com.ar/neckkito/
debera tener 10 elementos pero como nos hemos olvidado del cambio sigue definida con 5.
Vuelta a cambiar el cdigo... a no ser que el tamao de la matriz est referenciado a la
longitud de las constantes, en cuyo caso... no problem.

Fijaos cmo hemos rellenado los valores de las matrices.


Usualmente el bloque For...Next es una excelente
herramienta para este tipo de menesteres.

Finalmente volvemos a recorrer los valores de la matriz,


aplicndolo al texto escrito. Si el texto tiene un valor que
aparece en mtrAcentos lo sustituye por su equivalente en
mtrSinAcentos. Tambin utilizamos un bloque For...Next
para recorrer los elementos de la matriz.

Tambin fcil... o quiz no tanto... no s...

DETERMINANDO EL TIPO DE DATOS DE LA MATRIZ


En un captulo anterior comentbamos los diferentes tipos de datos y sus caractersticas.
Vamos a profundizar un poquito ms en ello, de manera que aprenderemos ahora que existen
unos caracteres que nos convierten la variable en el tipo de datos en el que estamos
interesados.

Es decir, nosotros escribamos, por ejemplo,:

Dim i As Long para indicar que la variable i era un entero largo (Long). Pero si escribimos:

Dim i&

tambin estamos indicando que i es un entero largo, puesto que el ampersand nos representa
la tipologa de los enteros largos.

Por qu yo, personalmente, prefiero utilizar la primera frmula? Porque no me s de memoria


todos los smbolos que representan los tipos de datos (maravilloso F1...). Adems, para
alguien que lee el cdigo, es mucho ms cmodo leer <Dim i As Long> y saber que i es un
entero largo que no leer <Dim i&>... y quedarse pensando: qu tipo de valor representaba
el ampersand?.

Y cules son esos smbolos mgicos? En la siguiente tabla los tenis detallados (ojo, no
todos los tipos tienen carcter de declaracin de tipo):

TIPO SUFIJO
Integer %
Long &
Single !
Double #
Currency @
Decimal &
String $

Y por qu necesitamos lo anterior? Pues porque para declarar valores dentro de una matriz e
indicar el tipo de datos es la mejor manera de que disponemos.

9
Vistame en http://siliconproject.com.ar/neckkito/
Por ejemplo, supongamos que queremos definir una matriz que nos d unos puntos de corte
para rangos explcitamente de enteros. Cmo le asignaramos los valores, a la vez que
indicamos que dichos valores son enteros? Pues de la manera siguiente:

Dim miMatriz() as Variant


miMatriz = Array (0%, 50%, 100%)

Lgicamente, si deseamos que sean enteros largos


escribiramos:

Dim miMatriz() as Variant


miMatriz = Array (0&, 50&, 100&)

Os recuerdo que el sistema de sufijos puede ser utilizado igualmente en un cdigo que no
afecte a los elementos de la matriz. Por ejemplo, estos dos cdigos son equivalentes:

Cdigo 1:

Private Sub...
Dim vUser As Integer
Dim vText As String
Dim i As Long
'Resto de cdigo
End Sub

Cdigo 2

Private Sub...
Dim vUser%
Dim vText$
Dim i&
'Resto de cdigo
End Sub

MATRICES MULTIDIMENSIONALES (MATRICES ESTTICAS)


Las matrices pueden tener ms de una dimensin. Vamos a desarrollar este apartado con una
matriz de dos dimensiones.

Empecemos por definir la matriz. La estructura de dicha definicin sera la siguiente:

miMatriz(elementosPrimeraDimension, elementosSegundaDimension)

La mecnica de funcionamiento es, en el fondo, prcticamente igual a lo que hemos


explicado antes. La nica dificultad es la imaginacin del supuesto.

Expliqumoslo a travs de un ejemplo:

Imaginemos que tenemos tres contrincantes que se enfrentan en tres pruebas diferentes.
Los resultados de esas pruebas vienen dados por 1 (primer lugar), 2 (segundo lugar) y 3
(tercer lugar). Nuestros contrincantes son:

Donald

10
Vistame en http://siliconproject.com.ar/neckkito/
Goofy
Mickey

Vamos a crear una matriz de dos dimensiones que nos recoja la siguiente informacin:

CONTRINCANTE 1 PRUEBA 2 PRUEBA 3 PRUEBA


Donald 1 1 3
Goofy 3 2 1
Mickey 2 3 2

Nuestro cdigo pedir al usuario que introduzca un nombre del contrincante y un nmero de
prueba, y le devolveremos un mensaje diciendo en qu posicin qued.

El cdigo podra ser el siguiente:

Private Sub cmdResultadoPruebas_Click()


'Definimos las variables
Dim vConc As Byte
Dim vPrueba As Byte
Dim mtrResult(3, 3) As Variant
'Cargamos la matriz
mtrResult(1, 1) = 1
mtrResult(1, 2) = 1
mtrResult(1, 3) = 3
mtrResult(2, 1) = 3
mtrResult(2, 2) = 2
mtrResult(2, 3) = 1
mtrResult(3, 1) = 2
mtrResult(3, 2) = 3
mtrResult(3, 3) = 2
'Solicitamos la informacin al usuario
vConc = InputBox("Seleccione contrincante: 1 para Donald / 2 para Goofy / 3 para Mickey")
vPrueba = InputBox("Seleccione un nmero de prueba (1 al 3)")
'Mostramos el resultado
MsgBox "El contrincante seleccionado qued el nmero " & mtrResult(vConc, vPrueba) _
& " en la prueba seleccionada", vbInformation, "POSICIN"
End Sub

Como podemos ver, no hay mayor dificultad.

Un ejemplo para matriz de tres dimensiones


Os planteo un ejemplo de matriz de tres dimensiones. Como idea os apunto que intentis
desarrollarlo vosotros antes de mirar la solucin, a ver dnde nos surgen las dudas
existenciales. Lo nico que os aconsejo es que tengis a mano una aspirina, por si de tanto

11
Vistame en http://siliconproject.com.ar/neckkito/
pensar nos coge dolor de cabeza... je, je... Vamos a olvidarnos de poner cdigo de control para
introduccin de valores, dado que lo que nos interesa es centrarnos en el manejo de la matriz.

Tambin os indico que no tengo ni idea de medicina, por lo


que los valores que pongo en el ejemplo son totalmente
inventados y cualquier parecido con la realidad es pura
coincidencia.

Vayamos a por el enunciado:

Somos los tcnicos de un laboratorio que estamos realizando un estudio sobre la eficacia de
una pastilla para dormir. El estudio lo realizamos sobre dos sujetos (sujeto 1 / sujeto 2), a los
cuales administramos, al sujeto uno, la medicina, y al sujeto dos, un placebo. Lo que
analizamos es su nivel de endorfinas y su nivel de adrenalina. El estudio se desarrolla durante
tres semanas.

Los resultados obtenidos son los siguientes

SUJETO ELEMENTO 1 SEMANA 2 SEMANA 3 SEMANA


1 Endorfinas 50mm 60mm 80mm
Adrenalina 40mm 35mm 20mm
2 Endorfinas 45mm 55mm 50mm
Adrenalina 43mm 39mm 40mm

La idea es que el usuario introduzca un cdigo numrico (porque esta investigacin es sper-
secreta, por supuesto) de tres dgitos, y el cdigo le devuelva el valor buscado.

Es decir, que si introduce el cdigo 123 est pidiendo:

1 = Sujeto 1
2 = Elemento 2 = Adrenalina
3 = Semana = Semana 3

y el resultado obtenido, en este caso, sera 20mm.

nimo, que es fcil!!!!

El cdigo podra ser el siguiente:

Private Sub cmdMatriz3D_Click()


'Declaramos las variables
Dim vCod As Variant
Dim Dig1 As Byte, Dig2 As Byte, Dig3 As Byte
Dim mtrDatos(2, 2, 3) As Variant
'Construimos la matriz
mtrDatos(1, 1, 1) = "50mm"
mtrDatos(1, 1, 2) = "60mm"
mtrDatos(1, 1, 3) = "80mm"
mtrDatos(1, 2, 1) = "40mm"
mtrDatos(1, 2, 2) = "35mm"
mtrDatos(1, 2, 3) = "20mm"

12
Vistame en http://siliconproject.com.ar/neckkito/
mtrDatos(2, 1, 1) = "45mm"
mtrDatos(2, 1, 2) = "55mm"
mtrDatos(2, 1, 3) = "50mm"
mtrDatos(2, 2, 1) = "43mm"
mtrDatos(2, 2, 2) = "39mm"
mtrDatos(2, 2, 3) = "40mm"
'Solicitamos el cdigo al usuario
vCod = InputBox("Introduzca el cdigo de tres dgitos",
"CDIGO")
'Extraemos los dgitos convirtindolos a Byte
Dig1 = CByte(Left(vCod, 1))
Dig2 = CByte(Mid(vCod, 2, 1))
Dig3 = CByte(Right(vCod, 1))
'Mostramos el valor en un MsgBox
MsgBox "El resultado del cdigo ha sido " & mtrDatos(Dig1, Dig2, Dig3)
End Sub

Nos metemos con una de cuatro dimensiones...? Je, je...

MATRICES DINMICAS

(y aprovechamos para aprender algunas SQL simples)


Hasta ahora hemos visto matrices en las que sabamos previamente el nmero de elementos
que iba a contener la matriz, ya fuera de manera directa o de manera indirecta.

Sin embargo, hay ocasiones en que nos es imposible saber, a priori, cuntos elementos va a
contener nuestra matriz. Es ms, puede que iniciemos el proceso sin saberlo, en mitad del
proceso ya se pueda delimitar el nmero de elementos pero, ms adelante, ese nmero puede
volver a cambiar.

Para estos casos... matrices dinmicas.

Las matrices dinmicas se declaran igual que las estticas, pero sin indicar el nmero de
elementos. Es decir, podramos declarar una matriz as:

Dim miMatriz()

Vemos que dejamos los dos parntesis sin ningn valor entre ellos. Ya tenemos declarada
nuestra matriz.

A la hora de rellenarla hay que decirle al cdigo, de alguna manera, que vamos a proceder a
rellenar nuestra matriz. Para ello utilizamos la instruccin ReDim.

En definitiva, el proceso en lenguaje vulgar sera:

Private Sub...
'Ojo, Access: tengo un tubo pero no s de qu lo voy a llenar
Dim miMatriz()
'Cdigo
'Ojo, Access: ahora ya tengo claro cmo voy a llenar el tubo
Redim miMatriz(...)
'Cdigo

13
Vistame en http://siliconproject.com.ar/neckkito/
End Sub

Sigamos profundizando un poco ms en las entraas de


las matrices dinmicas.

Vamos a imaginarnos que utilizamos Access para controlar


a los socios de un club, y organizamos una comida. A la
comida pueden venir miembros e invitados no socios (los
cuales no tenemos en la base de datos, lgicamente), y que
para asistir a la comida es necesario recoger una invitacin
personalizada.

Es necesario crear una tabla con un formulario, darle el formato correspondiente y dems
para dar de alta los invitados no socios? Si no nos interesa eso podemos utilizar matrices
dinmicas.

Para preparar el ejemplo vamos a seguir los siguientes pasos:

1.- Creamos una tabla, que llamaremos TInvitacion, con un slo campo, [NomInvit], de tipo
texto. No fijamos ninguna clave principal.

2.- Crearnos un informe, que llamaremos RInvitacion, sobre nuestra tabla TInvitacion, de
acuerdo con la siguiente estructura:

Ojo! No olvidis insertar un salto de pgina aqu!!!!!

Fijaos que:
Hemos eliminado la seccin del encabezado y pie del informe
Hemos utilizado la seccin detalle para poder imprimir una secuencia de registros
Hemos insertado un salto de pgina para que no nos salgan todos los nombres
consecutivamente en la misma hoja, sino que nos deben salir a nombre por hoja.

3.- En un formulario insertamos un botn de comando, y en l asignamos el siguiente cdigo:

...
Private Sub cmdInvitacion_Click()
'Declaramos las variables
Dim sqlBorra As String, sqlAnexa As String
Dim mtrInvit() As Variant

14
Vistame en http://siliconproject.com.ar/neckkito/
Dim numInv As Variant
Dim i As Long
'Solicitamos cuntas invitaciones queremos imprimir
numInv = InputBox("N de invitaciones a imprimir?",
"N COMENSALES")
numInv = CLng(numInv)
'Redimensionamos la matriz
ReDim mtrInvit(numInv)
'Rellenamos la matriz
For i = 1 To numInv
mtrInvit(i) = InputBox("Nombre invitado?",
"INVITADO")
Next
'Eliminamos los warnings por ejecutar consultas, en este caso
DoCmd.SetWarnings False
'Actualizamos la informacin en la tabla TInvitados a travs de
'una SQL de datos anexados
For i = 1 To numInv
sqlAnexa = "INSERT INTO TInvitacion(NomInvit) SELECT " _
& """" & mtrInvit(i) & """" & "AS Invitado"
DoCmd.RunSQL sqlAnexa
Next
'Imprimimos las invitaciones
DoCmd.OpenReport "RInvitacion", acViewPreview
'Eliminamos los registros de TInvitaciones, para dejar la tabla slo en estructura
sqlBorra = "DELETE FROM TInvitacion"
DoCmd.RunSQL (sqlBorra)
'Reactivamos los warnings
DoCmd.SetWarnings True
End Sub

Ahora ya puede venir un socio y decirnos: quiero dos entradas para mi mujer y yo. Le damos
al botn, redimensionamos la matriz, cogemos los datos e imprimimos las entradas... simple y
efectivo.

Vamos a echar un vistazo al cdigo:

Declaramos la matriz sin asignarle ndice. Cuando nuestro socio nos dice que quiere dos
entradas redimensionamos esa matriz a travs de la lnea:

ReDim mtrInvit(numInv)

Rellenamos la matriz a travs de los nombres que nos da. Para ello utilizamos un bucle
FOR...NEXT, que nos va pidiendo los nombres y aumentando el ndice de cada elemento de la
matriz en una unidad a travs de la variable i

Para evitar los molestos mensajes de Va a anexar 2 filas a la tabla... desactivamos los
warnings a travs de

DoCmd.SetWarnings False

Creamos la SQL que nos va a anexar los datos que ya tenemos almacenados en la
matriz en la tabla TInvitado. Para ir recorriendo los elementos de la matriz utilizamos de nuevo
un bloque FOR...NEXT

15
Vistame en http://siliconproject.com.ar/neckkito/
La SQL para anexar los datos vemos que es una cadena de texto, que consta de las
palabras clave: INSERT INTO / Identificamos la tabla (Identificamos el campo) / SELECT
valorAInsertar / AS nombreInventado.

El valorAInsertar nos lo da la matriz, a travs de los valores


guardados. Lo que yo he llamado nombreInventado es
simplemente un nombre aclaratorio, para que al leer el
cdigo, nos aporte informacin adicional. Podra haber
escrito, por ejemplo, & """" & mtrInvit(i) & """" & "AS
PersonaInvitada", y el cdigo nos hubiera funcionado
perfectamente igual.

El valor que debe insertarse debe estar entre comillas. Es decir, que si quisiramos insertar
slo un nombre, por ejemplo Neckkito, y utilizaramos el objeto consulta para crear una
consulta de datos anexados, deberamos escribir:

INSERT INTO TInvitacion(NomInvit) SELECT Neckkito AS Invitado;

Esas comillas dobles no se pueden escribir directamente en cdigo, puesto que el propio
cdigo entendera que estamos finalizando la cadena, lo cual nos dara error. Para indicar, en
cdigo VB, que queremos que las comillas dobles sean literales debemos utilizar cuatro
comillas dobles, como hemos hecho en & """" & mtrInvit(i) & """"

Ejecutamos la SQL a travs de la sentencia:

DoCmd.RunSQL sqlAnexa

La SQL para borrar los registros de una tabla tiene una estructura muy simple:

DELETE FROM nombreTabla

Esto tan simple hace desaparecer para nunca jams todos los registros, por lo que os
recomiendo que seis muy cuidadosos antes de ejecutar una SQL de este tipo.

Finalmente reactivamos los warnings (ms que recomendable, obligado) a travs de:

DoCmd.SetWarnings True

Digo obligado porque si desactivamos los warnings no slo los desactivamos para este cdigo,
sino para toda la BD, y pueden producirse errores en otro procedimiento o mdulo y Access no
nos avisar, con lo que si el cdigo no nos funciona no sabremos por qu (no sabremos qu
error se est produciendo).

ReDim Preserve
Imaginemos que nuestro socio nos dice: Vamos a ser dos. Nosotros indicamos al cdigo que
2 van a ser los elementos de la matriz y a continuacin nuestro querido socio nos espeta:
Perdn. No seremos dos, seremos tres.

Pues a cancelar la operacin y a comenzar de nuevo.

Sin embargo, si prevemos esta posibilidad podemos utilizar la palabra clave Preserve para no
tener que comenzar de cero. Y qu nos hace el Preserve?

Supongamos que tenemos esta matriz:


Dim matriz()

16
Vistame en http://siliconproject.com.ar/neckkito/
Redim matriz(2)
matriz(1) = Neckkito
matriz(2) = Access

Si unas lneas ms abajo tengo que volver a redimensionar


la matriz escribira:

Redim matriz(3)
matriz(1) = Octavio
matriz(2) = Word
matriz(3) = Excel

Si yo quiero obtener el valor de matriz(2), qu valor obtendr? Pues obtendr Word. Y qu


pasa con el valor Access? Pues que se ha evaporado. En definitiva, hemos sobrescrito los
valores de la matriz.

Pero si tengo:

Dim matriz()
Redim matriz(2)
matriz(1) = Neckkito
matriz(2) = Access

y lneas de cdigo ms abajo utilizo el Preserve, podr escribir:

Redim Preserve matriz(3)


matriz(3) = Octavio

Qu consigo con eso? Que se me guarden los dos valores iniciales, y puedo aadir un valor
ms a la matriz sin sobrescribir nada.

Y gracias a eso nuestro socio del club puede rectificarnos al alza el nmero de comensales sin
problema.

Cmo sera ese cdigo? Pues sera una cosa as:

Private Sub cmdPreserve_Click()


'Declaramos las variables
Dim sqlBorra As String, sqlAnexa As String
Dim mtrInvit() As Variant
Dim numInv As Variant, numInvAdicional As Variant
Dim i As Long
Dim resp As Integer
'Solicitamos cuntas invitaciones queremos imprimir
numInv = InputBox("N de invitaciones a imprimir?", "N COMENSALES")
numInv = CLng(numInv)
'Redimensionamos la matriz
ReDim mtrInvit(numInv)
'Rellenamos la matriz
For i = 1 To numInv
mtrInvit(i) = InputBox("Nombre invitado?", "INVITADO")
Next
'Solicitamos si deben aadirse ms invitados
resp = MsgBox("Aadimos ms invitados?", vbQuestion + vbYesNo, "AADIR INVITADOS")
'Si la respuesta es S redimensionamos de nuevo la matriz

17
Vistame en http://siliconproject.com.ar/neckkito/
If resp = vbYes Then
numInvAdicional = InputBox("Cuntos invitados ms debemos aadir?", "AADIR")
ReDim Preserve mtrInvit(numInv + numInvAdicional)
For i = 1 To numInvAdicional
mtrInvit(numInv + i) = InputBox("Nombre
invitado?", "INVITADO")
Next
numInv = numInv + numInvAdicional
End If
'Eliminamos los warnings por ejecutar consultas, en
este caso
DoCmd.SetWarnings False
'Actualizamos la informacin en la tabla TInvitados a
travs de
'una SQL de datos anexados
For i = 1 To numInv
sqlAnexa = "INSERT INTO TInvitacion(NomInvit) SELECT " _
& """" & mtrInvit(i) & """" & "AS Invitado"
DoCmd.RunSQL sqlAnexa
Next
'Imprimimos las invitaciones
DoCmd.OpenReport "RInvitacion", acViewPreview
'Eliminamos los registros de TInvitaciones, para dejar la tabla slo en estructura
sqlBorra = "DELETE FROM TInvitacion"
DoCmd.RunSQL (sqlBorra)
'Reactivamos los warnings
DoCmd.SetWarnings True
End Sub

Analicemos el cdigo a travs de valores numricos

Supongamos que los invitados iniciales son 2. Tendremos:


numInv = 2
mtrInvit(2)

Si no hay que aadir ms invitados el cdigo salta el bloque If resp = vbYes Then, con lo que
estos valores no se modifican Nuestra SQL aade 2 registros.

Si hay que aadir ms invitados (por ejemplo, 3 ms) tenemos que, inicialmente:
numInv = 2
mtrInvit(2)

Comienza el If...
numInvAdicional = 3
....... Nuestra matriz se redimensiona a
ReDim Preserve mtrInvit(numInv + numInvAdicional) mtrInvit(2+3) mtrInvit(5)

La asignacin de valores a la matriz se realiza por un bucle FOR...NEXT, de manera que


mtrInvit(numInv + i) = InputBox("Nombre invitado?", "INVITADO")

Primera iteraccin i=1


mtrInvit(2+1) mtrInvit(3) Asignamos el tercer lugar de ndice al elemento de la matriz

Segunda iteraccin i=2


mtrInvit(2+2) mtrInvit(4)

18
Vistame en http://siliconproject.com.ar/neckkito/
Tercera iteraccin i=3
mtrInvit(2+3) mtrInvit(5)

Perfecto: redimensionamos nuestra matriz a 5 elementos y


ahora tenemos:
2 elementos iniciales
3 elementos adicionales

Fijamos el nuevo valor para numInv, a travs de:


numInv = numInv + numInvAdicional numInv = 2 + 3 =
5

End If

- Como ahora numInv=5 Nuestra SQL actualiza 5 registros

Luego nuestra impresin de la invitacin ser, simplemente, perfecta... Je, je...

Quiz este cdigo, si no se le coge el punto, sea un poco complicado. Yo os animo a seguirlo
imaginando su funcionamiento con valores numricos, y ver qu resultado obtenemos.

nimo!

ALGUNOS ELEMENTOS INTERESANTES DE LA MATRIZ: las funciones


UBound() y LBound() y la instruccin Erase
Puede interesarnos, en alguna ocasin, saber cul es el ndice mximo y mnimo de una
matriz. Para saber lo anterior tenemos las funciones UBound y LBound.

UBound nos proporciona el ndice mximo; LBound nos proporciona el ndice mnimo.

Supongamos que tenemos la siguiente matriz:

miMatriz(-10 To 10) As Integer

Si asignamos el siguiente cdigo a un botn obtendremos dichos valores:

Private Sub cmdUBoundLBound_Click()


Dim miMatriz(-10 To 10) As Integer
MsgBox "Cota inferior: " & LBound(miMatriz) & vbCrLf & _
"Cota superior: " & UBound(miMatriz), vbInformation, "COTAS"
End Sub

Imaginemos que, por los motivos que sean, tenemos dos matrices dinmicas, y que una de
ellas (matriz1) coge valores que dependen de diferentes variables o combinaciones de
variables. Esta matriz sufre variaciones de nmero de elementos a lo largo del desarrollo del
cdigo.

Finalmente, y porque as lo necesitamos, tenemos que crear una matriz (matriz2) con el
mismo nmero de elementos que la primera matriz.

Cmo podemos saber cuntos elementos conforman nuestra primera matriz? Pues aplicando
estas dos funciones.

19
Vistame en http://siliconproject.com.ar/neckkito/
Veamos:


Private Sub cmdNumElementos_Click()
'Declaramos las variables
Dim matriz1() As Integer
Dim matriz2() As Integer
Dim numElem As Integer, i As Integer
Dim cotaSup As Integer, cotaInf As Integer
Dim valorUser As Integer, vMult As Integer
'Solicitamos un valor al usuario
valorUser = InputBox("Introduzca un nmero del 1 al 10", "NMERO")
'Creamos un valor aleatorio entre el 1 y el 10
Randomize
vMult = Int((10 * Rnd) + 1)
'Redimensionamos la matriz
ReDim matriz1(valorUser * vMult)
'Rellenamos la matriz con valores cualquiera
For i = 1 To (valorUser * vMult)
matriz1(i) = 2 * i
Next
'Sacamos las cotas
cotaSup = UBound(matriz1)
cotaInf = LBound(matriz1)
'Obtenemos el nmero de elementos
numElem = cotaSup - cotaInf
'Ya podemos redimensionar nuestra segunda matriz
ReDim matriz2(numElem)
'Traspasamos los valores entre matrices
For i = 1 To numElem
matriz2(i) = matriz1(i)
Next
'Hacemos una comprobacin
MsgBox "El elemento nmero " & valorUser & " de la matriz1 es " & matriz1(valorUser) & _
vbCrLf & vbCrLf & "El mismo elemento de la matriz2 es " & matriz2(valorUser) & _
vbCrLf & vbCrLf & "El nmero de elementos de la matriz2 es " & numElem,
vbInformation, "DATOS MATRIZ"
'Liberamos la memoria ocupada por la matriz1
Erase matriz1
End Sub

Como vemos, se solicita un valor del 1 al 10 al usuario; se genera un nmero aleatorio del 1 al
10, y se dimensiona la matriz con el producto de estos dos operadores. Cul ser la
dimensin de la matriz? Pues es imposible saberlo de antemano, ni siquiera en la repeticin del
cdigo.

Sacamos pues la cota superior y la inferior, y a travs de una simple resta conseguimos el
nmero de elementos; es decir:

cotaSup = UBound(matriz1)
cotaInf = LBound(matriz1)
'Obtenemos el nmero de elementos
numElem = cotaSup - cotaInf

20
Vistame en http://siliconproject.com.ar/neckkito/
Tened en cuenta que podemos utilizar esta sper-frmula porque, tal y como comentbamos
en los primeros epgrafes de este captulo, la matriz, en este caso, asigna el valor 0 a la cota
inferior.

Si hubiramos sentado lo de <Option Base 1> tened en


cuenta que la frmula debera haber sido
numElem = cotaSup cotaInf + 1

Hemos establecido una comprobacin muy simple para ver


que los valores se han traspasado correctamente entre
matrices.

Finalmente, la ltima lnea de cdigo incluye la instruccin Erase. La funcin de la instruccin


Erase depende del tipo de matriz con el que estamos operando.

Si operamos con una matriz dinmica, Erase lo que consigue es liberar el espacio de memoria
que ocupaban los valores de dicha matriz. Dicho de otra manera, y en nuestro caso, vuelve a
dejar la matriz definida como

matriz1()

y si quisiramos volverla utilizar tendramos que redimensionarla otra vez y asignarle nuevos
valores.

Si la matriz, en cambio, es esttica, la accin de Erase depende del tipo de datos que contenga
la matriz. Os copio lo que dice la ayuda de Access sobre este tema:

Tipo de matriz Efecto de Erase sobre elementos de una matriz fija


Matriz numrica fija Establece cada elemento a cero.
Matriz de cadena fija Establece cada elemento a una cadena de longitud cero ("").
(longitud variable)
Matriz de cadena fija Establece cada elemento a cero.
(longitud fija)
Matriz de Variante fija Establece cada elemento a Empty.
Matriz de tipos definidos Establece cada elemento como si se tratara de una variable separada.
por el usuario
Matriz de objetos Establece cada elemento al valor especial Nothing.

Y ACABAMOS EL TEMA DE MATRICES


Hemos dado un buen repaso al tema de matrices, y hemos aprovechado para aprender
algunos elementos y sistemticas nuevas que podremos utilizar en nuestra BD (aunque no
trate de matrices).

Como siempre, y no me cansar de insistir en esto (haca tiempo que no deca esto), adems
de aprender lo que es el tema en s estara muy satisfecho si podis coger ideas de
mecnicas de cdigo para aplicarlas en vuestras BD's.

Creo que con estos 9 captulos y lo que hemos aprendido en ellos ya estamos en disposicin de
desarrollar algunas cosillas interesantes y chulas en nuestras BD's. Sin embargo, an nos

21
Vistame en http://siliconproject.com.ar/neckkito/
quedan por aprender un par de cosillas interesantes y chulas ms...

nimo, y suerte!

22
Vistame en http://siliconproject.com.ar/neckkito/

Potrebbero piacerti anche