Subido por Video Vid

dokumen.tips la-biblia-de-vb6pdf

Anuncio
Visual Basic - Guía del Estudiante Cap. 1
INTRODUCCION Antecedentes históricos.
El lenguaje de programación BASIC (Beginner's All purpose Symbolic Instruction Code ) nació en el año
1964 como una herramienta destinado a principiantes, buscando una forma sencilla de realizar
programas, empleando un lenguaje casi igual al usado en la vida ordinaria ( en inglés), y con
instrucciones muy sencillas y escasas. Teniendo en cuenta el año de su nacimiento, este lenguaje cubría
casi todas las necesidades para la ejecución de programas. Téngase en cuenta que las máquinas
existentes en aquella época estaban estrenando los transistores como elementos de conmutación, los
ciclos de trabajo llegaban a la impensable cifra de 10.000 por segundo y la memoria no pasaba de unos
pocos k´s en toroides de ferrita.
Los autores fueron los científicos John G. Kemeny (Budapest, 1926 – USA 1992) y Thomas E. Kurtz
(Illinois 1928) Su trabajo original se llamó True BASIC.
La evolución del BASIC por los años 70 fue escasa, dado el auge que tomaron en aquella época
lenguajes de alto nivel como el FORTRAN y el COBOL. En 1978 se definió una norma para unificar los
Basics existentes creándose la normativa BASIC STANDARD
Con la aparición de los primeros ordenadores personales, dedicados comercialmente al usuario
particular, allá por la primera mitad de los ochenta, el BASIC resurgió como lenguaje de programación
pensado para principiantes, y muchos de estos pequeños ordenadores domésticos lo usaban como
único sistema operativo (Sinclair, Spectrum, Amstrad)
Con la popularización del PC, salieron varias versiones del BASIC que funcionaban en este tipo de
ordenadores (Versiones BASICA, GW-BASIC), pero todas estas versiones del BASIC no hicieron otra
cosa que terminar de rematar este lenguaje. Los programadores profesionales no llegaron a utilizarlo,
habida cuenta de las desventajas de este lenguaje respecto a otras herramientas (PASCAL, C,
CLIPPER). El BASIC con estas versiones para PC llegó incluso a perder crédito entre los profesionales
de la informática.
Las razones para ello eran obvias:
- No era un lenguaje estructurado.
- No existían herramientas de compilación fiables.
- No disponía de herramientas de intercambio de información.
- No tenía librerías.
- No se podía acceder al interior de la máquina.
- Un largo etcétera de desventajas respecto a otros lenguajes de programación.
Tal fue ese abandono por parte de los usuarios, que la aparición del Quick-BASIC de Microsoft, una
versión ya potente del BASIC, que corregía casi todos los defectos de las versiones pasó prácticamente
inadvertida, a no ser porque las últimas versiones del sistema operativo MS-DOS incluían una versión de
Quick-BASIC algo recortada (Q-Basic) como un producto mas dentro de la amplia gama de ficheros
ejecutables que acompañan al sistema operativo, y aprovecha de él el editor de textos (Cada vez que se
llama al EDIT estamos corriendo el editor del Q-Basic).
Esta versión del popular BASIC ya es un lenguaje estructurado, lo que permite crear programas
modularmente, mediante subrutinas y módulos, capaz de crear programas ya competitivos con otros
lenguajes de alto nivel. Sin embargo llegaba tarde, pues los entornos MS-DOS estaban ya superados por
el entorno gráfico Windows.
Sin embargo algo había en el BASIC que tentaba a superarse: su gran sencillez de manejo. Si a esto se
le añade el entorno gráfico Windows, el aprovechamiento al máximo de las posibilidades de Windows en
cuanto a intercambio de información, de sus librerías, de sus drivers y controladores, manejo de bases
de datos, etc. el producto resultante puede ser algo que satisfaga todas las necesidades de
programación en el entorno Windows. La suma de todas estas cosas es VISUAL - BASIC. Esta
LSB Visual Basic - Guía del Estudiante
Capítulo 1
Página 1
herramienta conserva del BASIC de los años 80 únicamente su nombre y su sencillez, y tras su
lanzamiento al mercado, la aceptación a nivel profesional hizo borrar por fin el "mal nombre" asociado a
la palabra BASIC.
Actualmente (2001) se está comercializando la versión 6.0 de este producto. Desde su salida al
mercado, cada versión supera y mejora la anterior. Dados los buenos resultados a nivel profesional de
este producto, y el apoyo prestado por el fabricante para la formación de programadores, Visual-Basic se
ha convertido en la primera herramienta de desarrollo de aplicaciones en entorno Windows.
Es obligado decir sin embargo, que sigue siendo BASIC. No se pueden comparar sus prestaciones con
otros lenguajes cuando deseamos llegar al fondo de la máquina y controlar uno a uno sus registros. No
es ese el fin perseguido con VB y si es necesario llegar a esas precisiones será necesario utilizar otro
lenguaje que permita bajar el nivel de programación. (Visual-C). o realizar librerías (DLLs) que lo hagan.
En la mayor parte de las aplicaciones, las herramientas aportadas por VB son mas que suficiente para
lograr un programa fácil de realizar y de altas prestaciones.
Características Generales de Visual-Basic
Visual-Basic es una herramienta de diseño de aplicaciones para Windows, en la que estas se desarrollan
en una gran parte a partir del diseño de una interface gráfica. En una aplicación Visual Basic, el
programa está formado por una parte de código puro, y otras partes asociadas a los objetos que forman
la interface gráfica.
Es por tanto un termino medio entre la programación tradicional, formada por una sucesión lineal de
código estructurado, y la programación orientada a objetos. Combina ambas tendencias. Ya que no
podemos decir que VB pertenezca por completo a uno de esos dos tipos de programación, debemos
inventar una palabra que la defina : PROGRAMACION VISUAL.
La creación de un programa bajo Visual Basic lleva los siguientes pasos:
Análisis . Es el studio de las necesidades que han dado origen a la creación de ese programa.
Es lo que se se llama Análisis de la aplicación. Es la primera fase que debe tener siempre un
programa y es tambien la más olvidada entre los programadores noveles. Una aplicación no se
inicia con el teclado, sino sobre un papel.
- Creación de un interface de usuario. Este interface será la principal vía de comunicación
hombre máquina, tanto para salida de datos como para entrada. Será necesario partir de una o
varias ventanas - Formularios - a las que le iremos añadiendo los controles necesarios.
- Definición de las propiedades de los controles – Se dará la forma, posición, y todas las
características necesarias a los controles que hayamos colocado en ese formulario. Estas
propiedades determinarán la forma estática de los controles, es decir, como son los controles y
para qué sirven.
- Generación del código asociado a los eventos que ocurran a estos controles. A la
respuesta a estos eventos (click, doble click, una tecla pulsada, etc.) le llamamos Procedimiento,
y deberá generarse de acuerdo a las necesidades del programa.
- Generación del código del programa. Un programa puede hacerse solamente con la
programación de los distintos procedimientos que acompañan a cada objeto. Sin embargo, VB
ofrece la posibilidad de establecer un código de programa separado de estos eventos. Este
código puede introducirse en unos bloques llamados Módulos, en otros bloques llamados
Funciones, y otros llamados Procedimientos. Estos Procedimientos no responden a un evento
acaecido a un control o formulario, sino que responden a un evento producido durante la
ejecución del programa.
No es necesario entender de momento lo anterior. Visual Basic introduce un concepto nuevo de
programación, y es necesario cambiar hasta el argot del programador. Posiblemente se le habrán
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 2
acumulado demasiados términos de una sola vez. Es normal. A poco que siga leyendo verá las cosas
mas claras cuando se explique una por una.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 3
VARIABLES. DEFINICION Y ENTORNO
Basic, desde siempre, al contrario de otros sistemas de programación, no exigió la definición previa de
una variable. Una variable, como Vd. seguro que conoce, es un nombre que en el programa le
asignamos a un dato. Ese dato podrá cambiar. Piense por ejemplo, en un programa consistente en la
toma de datos de los alumnos de un centro escolar. Existirán varias variables para poder introducir los
datos de los alumnos. Estas variables pueden tener nombre tales como:
Nombre
Apellido1
Apellido2
Dirección
Teléfono
Salario
La variable Nombre tomará valores distintos según vayamos introduciendo los datos de los distintos
alumnos. Es posible, que a lo largo de la ejecución del programa, esta variable Nombre valga:
José
Pedro
María
Luis
Espero que su intuición o conocimiento anterior le lleve a conocer el concepto de variable. Mas adelante
lo verá mas claro.
Decíamos que Basic no exige la definición previa de las variables. Otras herramientas exigen que se
haga así. Por lo tanto es normal encontrar, en otros sistemas de programación, que un programa
comienza de la siguiente forma:
Declare Nombre As String
Declare Apellido1 As String
Declare Apellido2 As String
Declare Dirección As String
Declare Teléfono As String
Declare Salario As Número
Le dice que Nombre es una sucesión de letras
Le dice que Teléfono es una sucesión de letras
Le dice que Salario es un número
Mediante estas declaraciones, el programa sabe de que tipo de dato se trata y por tanto cómo debe
trabajar con él. En otros sistemas de programación distintos de Basic, es necesario realizar esta
declaración antes de introducir una variable.
Basic permite que no se declaren. Cuando a lo largo del programa le introducimos una variable nueva,
asume que es una variable y que el tipo es el adecuado para el valor que le estamos introduciendo en
ese momento.
Por ejemplo, si Basic encuentra estas instrucciones
Salario=50000000
Nombre ="Pedro"
Teléfono = "1234567"
entiende que Salario, Nombre y Teléfono son variables, que Salario es un número (No hemos metido su
valor entre comillas), y que Nombre y Teléfono son sucesiones de caracteres alfanuméricos (su valor
está entre comillas)
Esta particularidad de no necesitar declarar las variables hace que sea sencillo introducir una variable
nueva. Sin embargo entraña un gran peligro. Imagínese que en un paso posterior del programa, le
mandamos escribir esos tres datos anteriores con la instrucción PRINT
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 4
Print Salario
Print Nombre
Print Telwfono
Habrá observado en tercer lugar la palabra Telwfono, que por error ha introducido el programador.
Basic interpreta que Telwfono es una variable e irá a leer en memoria el valor que tiene. No tendrá
ningún valor. Por lo tanto no escribirá nada y encima no dará ningún aviso de que se ha cometido un
error. Nada es gratis en esta vida, y la facilidad para introducir variables se paga con la posibilidad de un
error.
El peligro de no declarar las variables no termina en esa posibilidad de error. Cuando no declaramos el
tipo de variables, Visual Basic supone que la variable es de un tipo que soporta cualquier tipo de datos :
una variable tipo Variant. En ese tipo podrá meter cualquier tipo de variable, pero a costa de ocupar
mucho mas espacio en la memoria que si la hubiese declarado con el tipo correcto para el dato que va a
meter en ella.
Basic ha pensado en ese problema, y se puede solucionar con esta que será la primera instrucción
BASIC que vamos a estudiar:
OPTION EXPLICIT
Obliga a declarar previamente las variables que se vayan a usar. De no haberla
declarado antes de usarla, el programa dará una comunicación de error.
Esta declaración debe ponerla al comienzo de la sección de declaraciones de cada formulario y módulo
que contenga su aplicación. Pero no se preocupe de ello puesto que VB lo ha hecho por Vd. Basta que
lo programe en las opciones del VB. Haga click en Herramientas | Opciones de la barra de menú del
VB y le aparecerá este cuadro, donde debe marcar las casilla Requerir declaración de variables. A
partir de ahora, será VB quien ponga la sentencia Option Explicit en el lugar correcto. (Fig. 1.1)
TIPOS DE VARIABLES
Las variables pueden ser de los siguientes tipos: (El número indicado en segundo lugar indica el número
de Bytes que ocupa en memoria.)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 5
Booleana
Byte
Integer
Long
Single
Doble
Currency
String
Date
Objet
Variant
(2)
(1)
(2)
(4)
(4)
(8)
(8)
(*)
(8)
(4)
(**)
Admite los valores 0 y 1, o True (verdadero) y False (falso)
Números enteros, en el rango de 0 a 255
Números enteros en el rango de -32768 a 32767
Números enteros en el rango de -2147483648 a 2147483647
Punto flotante, simple precisión
Punto flotante, doble precisión.
Entero, con punto decimal fijo (Típico de monedas)
Cadenas alfanuméricas de longitud variable o fija
Fechas
Referencia a objetos
Otros tipos de datos
(*) Una variable tipo String ocupa el mismo número de bytes que caracteres tenga la cadena.
(**) Una variable tipo Variant ocupa 16 bytes si se trata de un número y 22 bytes + longitud de la cadena
si se trata de un dato tipo cadena de caracteres.
Existen también variables definidas por el usuario (Ya verá la sentencia Type). En este tipo de variables
se pueden introducir muchos datos de distinto tipo. Los bytes necesarios para almacenar esa variable
dependerá de los datos que se hayan definido.
Dentro de las variables Objet (variables que se refieren a objetos) existe una gran variedad que a estas
alturas del curso no debemos complicarnos con ellas. Pero para adelantar algo, veremos que una
variable puede ser del tipo Form - Formulario - , tipo Recordset, etc. etc.
Cada tipo de variable ocupa unos determinados bytes. Si no se define una variable, VB toma como tipo
por defecto para la variable el tipo Variant, tal como citábamos anteriormente. Este tipo ocupa mas bytes
que, por ejemplo, un integer. Si el tipo de dato que vamos a introducir en una variable es un integer, y no
la hemos declarado como tal, VB asumirá para esa variable que es del tipo Variant, lo que le llevará a
gastar mas bytes de memoria (16) que los que necesitaría (2) si la hubiésemos declarado previamente.
Si esa variable va a estar en el rango de 0 a 255, y no declaramos previamente que la variable va a ser
del tipo Byte, o la declaramos como integer, p. e., estamos desperdiciando memoria RAM y
posiblemente, retardando la ejecución del programa. Lo mismo podemos decir del resto de las variables,
y lo importante que es declararlas y declararlas bien.
NOTA. Observe en la lista anterior que un dato Booleano ocupa 2 Bytes, mientras que un dato tipo Byte
ocupa un byte. En muchas ocasiones declaramos variables tipo Boolean con la intención de que ocupen
menos espacio. Paradoja del VB. Si la declaramos como Byte ocupamos menos espacio en memoria.
Declarar una variable como Boolean tiene también sus ventajas (escribirá menos código por lo general
cuando necesite leer o escribir una variable tipo Boolean), pero tenga presente esta observación
respecto al tamaño de los datos Boolean.
Puede declarar el tipo de la variable mediante un carácter después del nombre de la variable. Esta
técnica, obligatoria en Quick-Basic, está en desuso en VB. No es recomendable definir el tipo de esta
forma, pues existe un serio peligro de error. De cualquier forma, eso es potestativo del programador y de
sus costumbres.
Los caracteres que definen cada tipo de variable son:
%
Integer
&
Long
#
Double
@
Currency
Ejemplos Prácticos de declaración de variables
!
Single
$
String
En Visual Basic, cuando declaramos una variable como String (Cadena de caracteres), no es necesario
declarar su longitud. VB aceptará cualquier número de caracteres. Si desea evitar que se puedan
introducir más de un determinado número de caracteres, debe declarar su número. Por ejemplo :
Dim Var1 as String
LSB
Visual Basic – Guía del Estudiante
Var1 puede tener cualquier número de caracteres
Capítulo 1
Página 6
Dim Var2 as String * 15
Var2 puede tener un máximo de 15 caracteres.
En este segundo caso, si se introduce como Var2 una cadena de caracteres con mas de 15 caracteres,
Var2 tomará solamente los 15 primeros. Visual basic no presenta ningún aviso de que esa variable ha
omitido los caracteres que han sobrepasado la cifra de 15. Si desea que el usuario conozca esa
circunstancia, debe introducir el código oportuno para producir el aviso.
La declaración de variables tipo String con número de caracteres predefinido presenta también
inconvenientes a la hora de tratar esa cadena de caracteres con sentencias tales como Mid, Left y Right,
o a la hora de añadir una cadena a otra. La experiencia nos indica que NO merece la pena declarar
variables tipo String con el número de caracteres prefijado, excepto que sea necesario justamente
para definir la longitud de la cadena.
En una gran parte de los casos una variable que se compone de números debe declararse como una
variable de cadena de caracteres (String), y no como numérica. Cuando pensamos por ejemplo en un
número de DNI, compuesto por 7 u 8 cifras, un código postal, el número de una calle, el piso de un
edificio, parecen invitar a que la variable que los contenga sea una variable de tipo numérico (Byte,
Integer, Long, ...). Estas variables, aunque su contenido sean números, siempre se deben declarar
como String, ya que se tratan en realidad de cadenas de caracteres, aunque estos no sean letras sino
números. Para aclarar mas estas ideas, piense en el número del DNI con la letra del NIF incluido, o que
el lugar del DNI se deba rellenar con el número del permiso de residencia, (lleva letras). Piense en el
código postal de una provincia que comienza por 0 ( 08XXX = Barcelona ) . Si la variable que va a
contener ese código postal se declara como numérica, el cero de la izquierda lo desprecia, por lo que
ese código postal quedaría reducido al 8XXX, número de 4 cifras que el cartero nunca reconocería
como un código postal, que necesariamente ha de tener 5 cifras. Para terminar, piense la forma de
introducir en una variable numérica el número 32Bis de una calle o el piso S2 de un edificio. O piense en
una variable que va a contener un código de un producto. Ese código siempre va a ser un número, por
ejemplo de 9 cifras. ¿Ha pensado como trataría el ordenador una variable numérica que contiene el
código 000100123 ?. El resultado sería que convertiría ese código en la cifra 100123, y Vd. deberá
buscarse la vida para añadir los ceros iniciales a la hora de sacarlo a una impresora, por ejemplo.
En to dos los casos anteriores, el número no representa una cant idad n um é
rica, sino u n n om bre.
Lo qu e ocurre es que ese nom bre contiene solam ente números .
¿Qué variables debemos declarar entonces como numéricas ? La respuesta es bien sencilla : Aquellas
que van a cont ener datos c on lo que v amos a realizar operaciones m atemáticas.
Las variables booleanas (True/False) pueden en muchos casos sustituirse por una variable del tipo Byte.
Si ese datos True / False se va a introducir en una base de datos o en fichero en el disco, puede ser mas
prudente poner 0 en vez de False y 1 en vez de True.
Una variable byte ocupa muy poco, simplemente 1 byte como su nombre indica. Pero no puede contener
números mayores de 255 ni números negativos.
Cada vez que declare una variable numérica piense en los valores que puede tener, sobre todo cuando
esa variable va a ser el resultado de una operación matemática. Recuerde el escaso margen de una
variable tipo Integer ( de -32768 a 32767)
Si la aplicación va a tratar moneda, piense en la forma de expresar los números decimales y el número
de ellos permitidos, así como el redondeo. La variable correcta para este caso es Currency, pero
Currency le añade automáticamente el tipo de moneda de cada país (Pts. Para España) lo que con
frecuencia es un engorro. Los datos del tipo de moneda los toma del sistema operativo del ordenador,
por lo que no se extrañe si le expresa el número de pesetas en dólares. Cambie el país en su S. O.
Otro tipo de variable es Date. Este tipo de variable representa una fecha o una hora. Pero debe ser
objeto de un estudio un poco mas extenso para tener claro que es una fecha para Visual Basic, como las
trata y como se pueden comparar. Lo verá mas adelante al estudiar las funciones Format y DateDiff.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 7
Ambito de las variables.
Denominamos ámbito de una variable a las partes del programa donde esa variable está declarada.
Para entenderlo mejor, veamos someramente la forma de un programa desarrollado en VB.
Un programa VB tiene uno o varios formularios. Cada formulario tiene varios controles. Tanto el
formulario como cada uno de sus controles tienen una parte del programa, justamente la parte
relacionada con cada uno de los eventos que pueden suceder bien al formulario o a los controles. A
estas partes las habíamos llamado Procedimientos. Podemos tener procedimientos que no estén
relacionados con ningún evento ocurrido al formulario o a sus controles. (Los Procedimientos que iremos
insertando a lo largo de la aplicación)
Aparte de formularios y controles, un programa puede tener Módulos, y en cada uno de los módulos
podemos insertar cuantos Procedimientos y Funciones queramos. La estructura de un programa VB
puede ser de la siguiente forma:
Formulario1
Declaraciones
Proc. A1
Proc. A2
Proc. A3
Proc. A4
Proc. A5
Proc. AA1
Proc. AA2
Proc. AA3
Formulario2
Declaraciones
Proc.B1
Proc.B2
Proc.B3
Proc.B4
Proc.BB1
Proc.BB2
Proc.B33
Formulario3
Declaraciones
Proc.C1
Proc.C2
Proc.C3
Proc.C4
Proc.CC1
Proc.CC2
Proc.CC3
Proc.CC4
Módulo1
Declaraciones
Proc.D1
Proc.D2
Proc.D3
Proc.D4
Modulo2
Declaraciones
Proc.E1
Proc.E2
FunciónE1
FunciónE2
FunciónE3
FunciónE4
FunciónE5
FunciónE6
Si se declara una variable dentro de un procedimiento o Función, esa variable "NO SALE" del
Procedimiento o Función donde se declaró. El procedimiento puede estar en un Formulario (Cualquier
procedimiento de un control o un procedimiento creado por nosotros) o en un Módulo (En este caso, el
procedimiento solo puede ser creado por nosotros)
En un Formulario, una variable puede declararse de dos formas : Privada o Pública. Para declarar una
variable a nivel de formulario debe hacerse en la sección de declaraciones, que está la ventana de
código Objeto = General , Proc. = Declaraciones . Si se declara Privada, esa variable se puede ver en
todo el formulario, (es decir, en todos los procedimientos de todos los controles del formulario y en los
Procedimientos que pudiésemos insertar en ese formulario), pero no sale de dicho formulario. Si se
declara como Pública, esa variable puede verse por todo el formulario, de la misma forma que lo haría
declarada como Privada, y además puede ser usada desde otro Formulario o Módulo, citándola con el
nombre del Formulario, seguido del nombre de la variable (Formulario.Variable)
En un Módulo una variable puede declararse como Privada, con lo que no saldrá de ese Módulo, o
Pública, pudiendo en este caso usarse en todo el programa. Cuando se declara una variable como
pública en un Módulo, basta referirse a ella por su nombre, sin citar el nombre del Módulo donde se
declaró.
En VB es posible declarar varias veces las variables, es decir, pueden declararse a nivel de formulario,
en su apartado de declaraciones, y esa variable conservará su valor en todas las partes de ese
formulario. Sin embargo, si se declara una variable con el mismo nombre a un nivel inferior, por ejemplo
al principio de un procedimiento, esa variable será una variable distinta a la anterior, aunque tenga el
mismo nombre, al declararla en un Procedimiento, solamente será válida en ese Procedimiento. Una vez
que hayamos salido de ese procedimiento, la variable con ese nombre volverá a ser la declarada en el
Formulario. En realidad, lo que tenemos son dos variables distintas, pero con el mismo nombre, una
declarada para todo el formulario excepto para el procedimiento donde se volvió a declarar, y otra para
ese procedimiento concreto.
NOTA.- No es recomendable declarar una variable a dos niveles. Es mucho mejor utilizar otro nombre
para esa variable dentro del procedimiento donde se le declararía por segunda vez. A esta nota cabe
exceptuar cuando declaramos variables para una operación tipo contador
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 8
For I = 1 To N
Esa variable I es práctico declararla con el mismo nombre en cada Procedimiento donde se use.
Tipos de declaración de variables.
Sentencia DIM
Es la forma mas común de declarar una variable como
Privada. Puede emplearse en un Procedimiento, Función, Formulario o
Módulo. La sintaxis es de la siguiente forma:
nombrevariable As Integer
Dim
(o el tipo que sea)
Declarando una variable con la sentencia DIM, en un formulario , Función , procedimiento o módulo , el
ámbito de la variable será el explicado anteriormente para una variable declarada como Privada. Es
decir, esa variable no sale del formulario, procedimiento ó módulo donde se declaró. Cada vez que
entremos al formulario, procedimiento o módulo, esa variable tomará el valor cero (si es numérica) o nulo
(si es string).
Sentencia PRIVATE
Es la forma de declarar una variable como Privada. Puede
emplearse solamente en la sección de declaraciones de un Formulario o
Módulo. La sintaxis es de la siguiente forma:
Private
nombrevariable As Tipovariable
Declarando una variable mediante la sentencia PRIVATE en un Formulario o Módulo, esa variable puede
usarse en todo ese Formulario o Módulo (En todos sus Procedimientos y Funciones), pero NO fuera del
Formulario o Módulo donde se declaró.
La sentencia Private no puede usarse en un procedimiento o función.
Es la forma de declarar una variable como Pública. Puede
emplearse solamente en la sección de declaraciones de un Formulario o
Módulo. La sintaxis es de la siguiente forma:
Sentencia PUBLIC
Public
nombrevariable
As Tipovariable
Declarando una variable de esta forma en la sección de declaraciones de un Módulo, esa variable
puede usarse en cualquier parte del programa citándola simplemente por su nombre.
Si se declara de esta forma en la sección de declaraciones de un Formulario, esa variable puede usarse
en toda el programa. Para nombrarla, si estamos en el Formulario donde se declaró basta con citarla por
su nombre. Si no estamos en ese Formulario, habrá que citarla por el nombre del Formulario, seguido
del nombre de la variable, separados por un punto :
NombreFormulario.Nombrevariable
En un Módulo puede usarse también la sentencia Global en vez de Public :
Sentencia GLOBAL Declara una variable que es válida en todo el programa. La
sintaxis es:
Global
nombrevariable As
tipovariable
La sentencia Global sólo puede usarse en el apartado de declaraciones de un Módulo. Esta sentencia
se mantiene por compatibilidad con versiones anteriores de VB. No la use .
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 9
Sentencia STATIC
Como se dijo anteriormente, una variable declarada en un procedimiento pierde su valor al salir de él. Lo
peor es que una vez que el programa vuelva a entrar en ese procedimiento, la variable estará puesta a
cero. Afortunadamente, esto último tiene solución. Si declarásemos una variable en un procedimiento o
función, como estática, esa variable, aunque no la podremos utilizar fuera de ese procedimiento o
función, cuando volvamos a él conservará el valor que tenía cuando lo abandonamos. Esta declaración
como estática se realiza mediante la instrucción Static
Static
nombrevariable
As
tipovariable
El nombre de una variable puede ser tan largo como queramos. hasta un máximo de 40 caracteres. En
la versión VB para España se pueden usar incluso la Ñ y vocales acentuadas. Es indiferente usar
mayúscula ó minúsculas. No se sorprenda, si por ejemplo, la ha declarado con mayúsculas y luego la
cita con minúsculas al escribir el código, que automáticamente se cambie a mayúsculas. El nombre de
una variable siempre debe comenzar por una letra.
No hay problema por utilizar variables largas. Al compilar el programa no se lleva el nombre, es decir, no
le va a ocupar mas espacio. Utilice siempre nombres que le definan la variable con algún sentido. Es
muy útil a la hora de acordarse como se llaman, y sobre todo, a la hora de rehacer un programa que
realizó hace seis meses.
Pese a que Visual Basic no obliga a declarar variables, es muy útil hacerlo. De esta forma se tiene
control sobre el programa. La experiencia se lo irá demostrando.
Resum imo s la forma de declarar una variable:
En un Procedimiento (La variable no puede usarse fuera de esta Procedimiento)
Dim Variable As Tipovariable
En un Procedimiento, com o permanente (La variable no puede usarse fuera de este procedimiento, y
dentro de él conserva el valor aunque se salga y se vuelva a entrar)
Static Variable As Tipovariable
En un Form ulario (En su sección de declaraciones)
Como Privada (Solamente se puede usar en ese Formulario)
Dim Variable As Tipovariable
ó
Private Variable As Tipovariable
Como Pública (Puede usarse en toda la aplicación)
Public Variable As Tipovariable
En un Módulo
Como Privada (Solamente puede usarse en ese Módulo)
Dim Variable As Tipovariable
ó
Private Variable As Tipovariable
Como Pública (Puede usarse en toda la aplicación)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 10
Public Variable As Tipovariable
ó
Global Variable As Tipovariable
Error típico de un programador novel de Visual Basic
Creo que esta costumbre viene del lenguaje C. Pero no vale en VB. Se trata de declarar varias variables
juntas en una misma línea :
Dim Variable1, Variable2, Variable3, Variable4 As String
Esta declaración está MAL hecha. Visual Basic interpretará que Variable1, Variable2 y Variable3 son del
tipo Variant, y solamente Variable4 la supone como tipo String
La forma correcta de hacerlo, si queremos declarar esas variables un una sola línea, es la siguiente :
Dim Variable1 As String, Variable2 As String, Variable3 As String, Variable4 As String.
Forma de conocer el tipo de una variable. Función TypeName
Podemos conocer el tipo con el que se ha declarado una variable. Esto se hace mediante la Función
TypeName, que devuelve una cadena con el tipo de una variable.
MiTipo = TypeName(NombreVariable)
NombreVariable puede ser cualquier variable con excepción de las de tipos definidos por el usuario.
La cadena de caracteres devuelta por TypeName puede ser una de las siguientes:
Cadena devuelta
La variable contiene
Byte
Entero
Largo
Simple
Doble
Moneda
Fecha
Cadena
Boolean
Error
Empty
Null
Objeto
Desconocido
Nada
Un byte
Un entero.
Un entero largo.
Un número de punto flotante de precisión simple.
Un número de punto flotante de precisión doble.
Un valor de moneda.
Una fecha.
Una cadena.
Un valor Boolean.
Un valor de error.
No inicializado.
No hay datos válidos.
Un objeto que no respalda Automatización OLE.
Un objeto de Automatización OLE cuyo tipo es desconocido.
Una variable de objeto que no se refiere a un objeto.
Si NombreVariable es una matriz, la cadena devuelta puede ser cualquiera de las cadenas posibles con
un paréntesis vacío adherido. Por ejemplo, si NombreVariable es una matriz de enteros, TypeName
devolverá "Integer()".
Vamos a hacer nuestro primer programa en Visual Basic. Arranque VB y coloque en el formulario que
aparece nada mas arrancarlo, un botón de comando (CommandButton) y tres etiquetas (Label). El botón
de comando le aparecerá con el nombre de Command1 y los labels con Label1, Label2 y Label3. Haga
doble click sobre el formulario. Le aparecerá una ventana. En la parte superior izquierda tiene una línea
con la palabra Form y una flecha hacia abajo que parece que va a desplegar algo. Haga click sobre esa
flecha y luego sobre la palabra General que le aparecerá. Teclee aquí las declaraciones de varias
variables (observe que en la ventana similar de la derecha aparece Declaraciones). Puede que ya le
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 11
aparezca la linea con Option Explicit. Si no le aparece, tecléela.
Option Explicit
Dim MiString As String
Dim MiEntero As Integer
Dim MiObjeto As Control
‘Hemos declarado que MiString es una variable tipo String
‘Hemos declarado que MiObjeto es una variable tipo Objeto
Haga doble click sobre el botón de comando. Le aparecerá la ventana anterior, pero referida ahora al
Command1. Teclee el siguiente código :
Private Sub Command1_Click()
Set MiObjeto = Command1
‘Y aquí decimos que MiObjeto es precisamente el Command1
Label1 = TypeName(MiString)
label2 = TypeName(MiEntero)
Label3 = TypeName(MiObjeto)
End Sub
En los labels 1, 2 y 3 aparecerá el tipo de cada variable: String, Integer y CommandButton.
Esta función tiene mucha utilidad para determinar errores durante el diseño. Cuando aparece el error “No
coinciden los tipos” puede interrogarse al programa para ver qué tipo de variable es el que hemos
declarado. Esta idea es especialmente útil cuando el trabajo a realizar sea retomar el trabajo comenzado
por otro programador.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 12
Lenguaje Basic del Visual Basic.
No ha sido un juego de palabras. VB emplea unas instrucciones casi iguales a las que emplea Quick
Basic. Sin embargo ha añadido otras nuevas instrucciones, inherentes con la programación visual.
Vamos a estudiar aquí las instrucciones y definiciones mas sencillas, comunes a QB y VB.
Sentencias condicionales.
Llamamos sentencias condicionales a aquellas que se realizan si se cumple una determinada condición.
Son las sentencias por las que empieza cualquier texto de Basic, y este no va ser menos.
La sentencia condicional más usada es:
Si se cumple una condición Entonces
Realiza estas instrucciones
Si no se cumple
Realiza estas otras instrucciones
Fin de la sentencia.
Así de fácil es programar en Basic. Lo que ocurre es que esta herramienta habla inglés, y lo descrito
anteriormente toma la forma:
If condición Then
Instrucciones
Else
Otras instrucciones
End If
En este ejemplo, o se cumple una condición y ejecuta unas determinadas instrucciones, o no se cumple,
y ejecuta otras instrucciones distintas. Puede ocurrir que, caso de no cumplirse la condicion primera, se
abra un abanico de dos o tres posibilidades. La sentencia condicional tendría entonces la forma:
If condición 1 Then
Instrucciones
ElseIf Condición 2
Otras instrucciones
ElseIf Condición 3
Otro juego de instrucciones
Else
Instrucciones que debe realizar caso de no cumplir las condiciones 1, 2 y 3.
End If
Como decíamos anteriormente, este es el tipo de sentencia condicional mas usada.
Existe otra sentencia condicional muy usada: Select Case
Su nombre casi nos define lo que es: Selecciona, dependiendo del caso, un determinado juego de
instrucciones:
Select Case variable
' variable es una variable que puede tomar los valores (p.e.) de 1 a 4
Case 1
Instrucciones a ejecutar en caso de que variable = 1
Case 2
Instrucciones a ejecutar en caso de que variable = 2
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 13
Case 3
Instrucciones a ejecutar en caso de que variable = 3
Case 4
Instrucciones a ejecutar en caso de que variable = 4
Case Else
Instrucciones a ejecutar en caso de que variable sea distinta a los valores
anteriores
End Select
Este procedimiento resulta mucho mas sencillo y rápido que las sentencias If Then Else
vistas anteriormente, cuando el margen de elección es mayor que 2.
Puede agrupar varios valores en una misma línea. Por ejemplo, si tiene 100 valores posibles, y el
tratamiento es igual para varios de ellos, puede agruparlos así:
Select Case Valor
Case Is < 20
Instrucciones
Case Is = 20
Instrucciones
Case Is = 21, 22, 23, 24, 25, 26
Instrucciones
Case Is > 26
Instrucciones
End Select
Cuando lo que queremos es elegir un valor, no ejecutar instrucciones como hacíamos anteriormente,
disponemos de otras dos funciones: Choose y Switch.
Switch toma una serie de parámetros, todos por parejas. El primer término de cada pareja es la
expresión a evaluar. El segundo es el valor que tiene que devolver. En realidad Switch es una función
(las funciones las veremos muy pronto)
A = Switch (B=1, 5, B=2, 7, B=3, 11)
Esta instrucción obtiene un valor para A que dependerá del valor que tome B entre los valores posibles
(1, 2 ó 3)
La sentencia Choose es casi igual, cambia solamente la forma. La misma intrucción anterior puede
realizarse con Choose de la siguiente forma:
A = Choose ( B, 5, 7, 11 )
En estas sentencias, Switch y Choose, si el valor de B no coincide con ninguno de los valores que se
le habían establecido (1, 2 ó 3 en nuestro caso), la sentencia devuelve el valor Nulo ( Null ). Esto puede
producir algún error si no se contempla esa posibilidad.
Las sentencias Switch y Choose no se usan mucho en programación. Parece que los programadores
o no las conocen o se lían (y es comprensible) al utilizarlas. Le garantizo que puede llegar a ser un gran
programador sin necesidad de utilizarlas. Use preferentemente If End If y Select Case.
Otra sentencia condicional: IIF
Devuelve uno de entre dos valores, dependiendo de la evaluación de una expresión.
Sintaxis
Iif (Expresión, SiEsCierto, SiEsFalso)
Expresión es la expresión a evaluar.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 14
SiEsCierto
SiEsFalso
Valor o expresión devuelta si Expresión es True.
Valor o expresión devuelta si Expresión es False.
Observaciones
IIf siempre evalúa SiEsCierto y SiEsFalso, aunque sólo vaya a devolver una de ellas. Por esta razón,
deberá vigilar que no se produzcan efectos no deseados. Por ejemplo, si al evaluar SiEsFalso se
produce un error de división entre cero, se generará un error aunque Expresión dé como resultado True.
Como ejemplo, en el formulario de nuestro primer programa introduzca un nuevo botón de comando.
Introduzca también un TextBox. Vea que poco a poco vamos metiendo cosas aunque no las conocemos
todavía. Mas tarde las conocerá. El TextBox tendrá por nombre Text1. Haga doble click sobre el botón
de comando e introduzca el siguiente código :
Private Sub Command2_Click()
Dim MiVariable As String
MiVariable = IIf(Clng(Text1.Text) > 100, "Es mayor", "Es menor")
Label1 = MiVariable
End Sub
Al ejecutar el programa, debe introducir un valor numérico en Text1. Si ese valor numérico es menor que
100, MiVariable tomará el valor “Es menor” (No se cumple la condición expresada en el primer
parámetro Text1.Text > 1000). Si introduce una cantidad mayor, se cumple esa condición, por lo que
MiVariable tomará el valor “Es mayor”. El valor que toma la variable puede verlo en Label1.
Fíjese que hemos declarado MiVariable como String, ya que va a contener un dato tipo cadena de
caracteres.
Con estas sentencias condicionales es posible realizar bifurcaciones del programa, cambiar las
propiedades de un objeto, obtener resultados de operaciones, ....
Sentencias de bucle.
Es muy común utilizar bucles a lo largo de un programa. Un bucle es una sucesión repetitiva de
instrucciones, que se estarán realizando mientras se cumpla una condición o mientras no se cumpla otra
condición. Es tan sencillo como esto:
Mientras condición
Instrucciones
Fin del bucle
Existen dos formas de bucle: Una, que realiza un número determinado de recorridos por el bucle. Es el
denominado bucle por contador. Otra, realiza el bucle hasta que se cumpla (o deje de cumplirse) una
condición. Es el llamado bucle por condición.
Bucle por contador
Realiza el bucle tantas veces como le indiquemos. Por ejemplo, en este bucle nos va a presentar
las 26 letras mayúsculas del alfabeto inglés
For N=65 To 90
Label1.caption = Chr ( N )
Next N
Este "programa" nos presentará en una caja (Label) los caracteres cuyo número ASCII vaya desde el 65
(A) al 90 (Z)
Comenzará presentando el correspondiente al número 65, e irá presentando
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 15
sucesivamente el 66, el 67, etc., hasta llegar al 90, donde se parará.
Bucles por condición
Ejecuta las instrucciones del bucle mientras se cumple una condición
X=0
Do While X < 1000
X=X+1
Loop
El programa toma una variable ( X ) que previamente tuvimos la curiosidad de ponerla a cero, e
incrementa su valor una unidad. Analiza si el valor de X es menor que 1000, y si es cierto, vuelve a
realizar el bucle. Así hasta que X ya no sea menor que 1000. Al dejar de cumplirse que X sea menor que
1000, sale del bucle. Acabamos de realizar un temporizador, y también de exponer las sentencias
condicionales y los bucles, inicio de cualquier curso de Basic. Como final de lección, se propone un
problema. Con el primer bucle, donde visualizábamos los caracteres A a la Z, posiblemente no nos
diese tiempo de ver cada una de las letras que iban apareciendo en la pantalla, en la etiqueta Label1,
dado que cambiaría con mucha velocidad, y solamente veríamos la Z, que es donde se detuvo el
programa. Podemos poner un temporizador cada vez que presente una letra, y así nos dará tiempo a
verla. Con los dos bucles vistos anteriormente ya podemos hacerlo.
Si lo que queremos es que el programa se ejecute mientras no se cumpla una determinada condición, la
sentencia será:
X=0
Do Until X > 1000
X=X+1
Loop
Observe que la diferencia entre una y otra es la condición, While para indicar Mientras se cumpla que
... y Until para indicar Mientras no se cumpla que ....
Para terminar bien el programa anterior utilizaremos la condición de While (Mientras se cumpla la
condición)
For N=65 To 90
Label1.caption = Chr ( N )
Label1.RefreshN
X=0
Do While X < 1000
X=X+1
Loop
Next N
' Refresca la etiqueta
Este es nuestro primer programa en BASIC. En VISUAL BASIC es idéntico, pero nos falta la interface
gráfica. Para realizarla basta con abrir el VB y sobre el formulario que aparece al abrirlo, introducir una
etiqueta, (Label) que llevará el nombre por defecto de Label1. Solo nos queda pensar donde
introducimos el código anterior. Podemos introducir un botón de comando (Command Button) que
saldrá con el nombre por defecto de Command1. Haga doble click sobre el botón. Aparecerá el
procedimiento Click. Este procedimiento es el que se realiza cuando hacemos click sobre ese botón.
Escriba en ese procedimiento este código.
Private Sub Command1_Click() ' Esta línea sale automáticamente
For N=65 To 90
Label1.caption = Chr ( N )
' Refresca la etiqueta
Label1.RefreshN
X=0
Do While X < 1000
' Bucle de temporización (*)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 16
X=X+1
Loop
Next N
End Sub
' Termina el bucle de temporización
' Esta línea sale automáticamente
Hemos puesto nuestra primera piedra en Visual Basic. Este ejemplo es muy sencillo. Visual Basic es tan
sencillo como este ejemplo.
(*)
Las temporizaciones no se hacen realmente así. El ejemplo anterior no deja de ser una forma
sencilla de detener el programa, para que en los comienzos de su carrera como programador pueda ver
el contenido de una etiqueta. Si lo hiciera de esta forma, su ordenador estaría detenido realizando una
función bastante triste, contar hasta 1000 para luego continuar el programa. Y lo que es peor, en un
ordenador a 300 MHz. Tardaría menos tiempo que en uno a 66. Esta misma función puede hacerla con
Sleep que la verá mas adelante, que es la forma limpia y elegante de hacer una temporización
Formas de salir de un bucle
Para salir de un bucle, podemos esperar a que se complete, bien porque se ha cumplido la condición
(Bucles por condición) o a que se haya llegado al final de la cuenta (Bucles por contador). Pero puede
ocurrir que interese salir del bucle sin haber terminado la ejecución total del mismo, por ejemplo, porque
ya hemos encontrado lo que estabamos buscando, y sería una pérdida de tiempo seguir ejecutando el
bucle cuando ya hemos obtenido lo que buscamos. Para ello, basta con ejecutar la sentencia Exit Do
(Cuando hemos comenzado el bucle con Do Until o Do While, o con Exit For cuando lo hemos
comenzado con For ... To
Ejemplos
En el siguiente ejemplo pretendemos parar el programa cierto tiempo, a la espera que otro equipo se
conecte a través del puerto serie. (Cuando se conecte, el control MSComm1 detectará la señal DSR que
le envía el otro equipo y deberemos salir inmediatamente del bucle para, por ejemplo, atender a ese
puerto serie)
Contador = 0
Do While Contador < 1000
Contador = Contador + 1
DoEvents
If MSComm1.DSRHolding = True Then Exit Do
Sleep (1000)
Loop
‘Aquí comenzamos a atender al puerto serie
En el siguiente ejemplo, deseamos transmitir por el puerto serie una serie de números, del 1 al 1000,
pero siempre y cuando que el equipo que está al otro lado de la línea serie esté a la escucha (Condición
MSComm1.DSRHolding = True) Si se desconecta ese equipo, y la condición pasa de True a False,
deseamos salir del bucle:
For I = 1 To 1000
If MSComm1.DSRHolding = False Then Exit Do
MSComm1.Output = Str(I)
Next I
No se preocupe que no entienda esto del MSComm. Lo entenderá perfectamente unos capítulos mas
adelante. Lo importante es que entienda la idea de salir de un bucle por la vía rápida.
Función DoEvents
Si hablameos de bucles, necesariamente debemos hablar de la función DoEvents. Y es así por la misma
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 17
razón que cada vez que ponemos un bucle, deberíamos poner dentro de ese bucle la palabra mágica
DoEvents.
Imagínese que Visual Basic está ejecutando este código:
Do While Valor < 100
Valor = valor + 1
If Valor = 90 then Valor =1
Loop
Observará que la variable Valor nunca podrá llegar a tener el valor 100, puesto que cada vez que llega a
90 le ponemos de nuevo el valor 0. El programa no va a salir nunca del bucle, pero además no podrá
atender a otros eventos que se produzcan en el ordenador (por ejemplo la pulsación de una tecla) ya que
el microprocesador está atendiendo solamente a ese bucle. Si lo está ejecutando desde el propio
entorno de Visual Basic, deberá parar la ejecución mediante las teclas Ctrl – Pausa. No podrá pararlo
mediante el botón Terminar de la barra de herramientas de VB. En un programa compilado posiblemente
tenga que reiniciar el equipo mediante Alt – Ctrl – Sup, llevándose por delante el resto de los programas
que se estén ejecutando en ese momento en su PC.
No es difícil cometer este error involuntariamente. Esto es lo que se llama un bucle infinito. Para que no
suceda, o al menos, que si nuestro programa entra en un bucle infinito se pueda salir de una forma no
tan agresiva, hay que introducir dentro del bucle la instrucción DoEvents. Cuando VB encuentra esta
función el control del microprocesador al sistema operativo, y si hay alguna operación en espera (la
pulsación de una tecla, por ejemplo) la ejecuta y posteriormente vuelve a ejecutar el bucle. De esta
forma, podemos salvar al menos los datos de las otras aplicaciones que se están ejecutando al mismo
tiempo.
El bucle tomaría esta forma:
Do While Valor < 100
Valor = valor + 1
If Valor = 90 then Valor =1
DoEvents
Loop
Salir de un procedimiento antes de terminar su ejecución
Y ya que explicamos como se sale de un bucle por la vía rápida, veamos como salir de un
procedimiento usando también esa “vía rápida”.
Para salir de un procedimiento basta con ejecutar la sentencia Exit Sub. En el ejemplo siguiente,
usamos el botón BotonLeerNombre para introducir el dato Nombre en una base de datos. Pero ese
campo puede tener como máximo, 20 caracteres. Si el usuario ha introducido mas de 20 caracteres,
debemos salir del procedimiento donde se introduce ese dato sin ejecutarlo de forma íntegra:
Private Sub BotonLeerNonbre_Click()
Mivariable = Text1.Text
If Len(Mivariable) > 20 Then
MsgBox "El Campo Nombre debe tener como máximo 20 caracteres"
Text1.Text = ""
‘Con esta instrucción saldríamos de este procedimiento
Exit Sub
Else
'Aqui vendrían las lineas de instrucciones donde trataríamos
'el contenido de Text1, si tuviese menos de 20 caracteres
End If
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 18
NOTA. Los ejemplos anteriores sirven solamente de ilustración para explicar el código que estamos
estudiando. No pretenda ver una forma mejor de realizar la misma función, que seguro que existe.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 19
BASIC DE VISUAL BASIC
(y2)
Funciones de cadena
Se denomina CADENA a una sucesión de caracteres. Una cadena puede tener uno o varios caracteres
alfanuméricos. Una cadena es también una sucesión de números.
Ejemplo de cadenas:
Curso de Visual Basic
abcdefghijklmnopqrstuvwxyz1234567890
123456789
Hagamos una distinción entre una cadena que contenga números y un número. Un número tiene un
valor, pero también tiene una presentación escrita. El valor es algo que estará en el ordenador como una
sucesión de bits. Dependiendo de como lo hayamos declarado, tendrá mas o menos bits. Pero esa
información no es un número legible por el usuario. Lo que sí es legible por el usuario es la
representación en numeración decimal (u octal, o hexadecimal, o incluso en binario) de ese número. Esa
representación del número en un determinado sistema de numeración es una cadena.
Así, el número nueve, que en la memoria del ordenador será una sucesión de bits, nos lo podrá
presentar como:
9
9
11
1001
En numeración decimal
En numeración hexadecimal
En numeración octal
En numeración binaria
Esas formas de presentarnos el número son CADENAS de caracteres. El valor del número dentro del
ordenador es un NUMERO.
Para presentar un número en la pantalla, el ordenador debe convertirlo previamente a una cadena.
Cuando introducimos un valor numérico por teclado o pantalla, el ordenador para hacer operaciones con
él, debe transformarlo a un número.
Estas consideraciones nos llevan a las dos primeras funciones con cadenas:
Str
(número)
Val
(cadena numérica)
Obtiene el valor (el número) correspondiente a esa
cadena.
Convierte un número a una cadena en numeración
decimal.
Ejemplos
Variablenumerica = Val (TextBox1.Text)
Este ejemplo convierte la cadena de caracteres (numéricos) que hubiese en la caja de texto
TextBox1 en un número, y asocia este número a la variable Variablenumerica.
Si el contenido de la caja de textos no fuesen caracteres numérico (abcd, por ejemplo),
Variablenumerica tomaría el valor 0.
Label1.Caption = Str (Variablenumerica)
Este ejemplo pondría en la etiqueta Label1 los caracteres correspondientes al valor que tuviese la
variable Variablenumerica .
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 20
Nota para recordar: Siempre habrá que convertir un número a una cadena cuando queramos
presentarlo en la pantalla. Siempre habrá que convertir a número la cadena de caracteres numéricos que
hayamos introducido por teclado o por pantalla, cuando queramos operar con ese número. Un Label,
cuando tiene que presentar un único número, no le pedirá que se lo convierta a cadena, pues VB hace
automáticamente esa conversión. Sin embargo, cuando tiene que presentar un número, y además un
texto en el mismo Label, VB no realizará automáticamente ese cambio, por lo que le dará un error. Le
recomiendo que convierta los números a variables de cadena siempre que los quiera presentar en un
Label o TextBox. Cuando tenga mas experiencia en VB verá que esta observación estará un poco de
más. Pero de momento, convierta cada dato según lo vaya a necesitar.
Existe una función mas amplia que Str. Se trata de Cstr. Esta función no solamente transforma un
número a una cadena, como hace Str, sino que convierte cualquier tipo de variable a una variable tipo
String (cadena).
Esta función transforma, por ejemplo, una variable tipo Booleana en una variable de cadena, devolviendo
la cadena “Verdadero” si el valor de la variable booleana es True, y “Falso” si es False.
Puede también transformar a una cadena de caracteres el valor de un CheckBox o de un OptionButton.
En estos casos devuelve 0 y 1 para el CheckBox (Desactivado / Activado) y Verdadero ó Falso para el
OptionButton (Activado / Desactivado)
label1.Caption = CStr(booleana)
Label1.Caption = Verdadero si booleana es true
Label1.Caption = Falso si booleana es False
Label2 = CStr(Check1.Value)
Label2.Caption = 1
Label2.Caption = 0
Label3 = CStr(Option1.Value)
Label3.Caption = Verdadero si Check1 está activado
Label3.Caption = Falso si Check1 está desactivado
si Check1 está activado
si Check1 está desactivado
Si se aplica Cstr a una variable tipo Fecha/Hora devuelve la fecha / Hora en formato corto.
Vea mas adelante la colecc ión de funcion es Cxx
Mas funciones de cadena:
Left (cadena, n)
Extrae los n primeros caracteres de una cadena, comenzando por la izquierda.
Si cadena = Curso de Visual Basic
(Para todos los ejemplos)
Resultado = Left (cadena, 10)
---->
Right (cadena, n)
Resultado = Curso de V
Extrae lo n últimos caracteres de la cadena
Resultado = Right (cadena, 10)
---->
Resultado = sual Basic
Mid (cadena, m, n)
Extrae n caracteres de la cadena, siendo el primer carácter
extraído el que ocupa el lugar m.
(Vea Instrucción Mid mas abajo)
Resultado = Mid (cadena, 3, 10) ---->
LCase (cadena)
LSB
Visual Basic – Guía del Estudiante
Resultado = rso de Vis
Devuelve otra cadena igual, pero con todos los
caracteres en minúsculas. (LCase = Lower Case)
Capítulo 1
Página 21
Resultado = Lcase (cadena)
---->
UCase (cadena)
Devuelve otra cadena igual, pero con todos los
caracteres en mayúsculas. (UCase = Upper Case)
Resultado = UCase (cadena)
---->
Len (cadena)
Resultado = curso de visual basic
Resultado = CURSO DE VISUAL BASIC
Devuelve la longitud de la cadena
Resultado = Len (cadena)
---->
Resultado = 21
LenB (Cadena)
Devuelve el número de Bytes empleados para almacenar la
cadena. Sorpréndase, es el doble que Len (Cadena)
String (n, carácter)
Devuelve una cadena de n caracteres como el indicado
Resultado = String (8, "a")
---->
Resultado = aaaaaaaa
Resultado = String (8, Chr(65))
---->
Resultado = AAAAAAAA
Resultado = String (8, 65)
---->
Resultado = AAAAAAAA
Space (n)
Devuelve una cadena formada por n espacios.
Resultado = "A" + Space (6)+ "B"
---->
Resultado = A
B
LTrim
Elimina los posibles espacios que tenga una cadena por
Su izquierda.
Rtrim
Elimina los posibles espacios que tenga una cadena por
Su derecha.
Trim
Elimina los espacios que tenga una cadena, tanto por su
izquierda como por su derecha. (No elimina los espacios
centrales de la cadena)
Estas tres funciones se emplean para quitar los posibles espacios que pueden resultar de una
entrada de datos. Tienen especial importancia cuando se toman los datos de un archivo o base de datos,
donde fueron introducidos por otro programa.
La función Trim hay que usarla cada vez que convertimos un número a cadena de caracteres. Cuando
usamos Str(Número), la función Str introduce un espacio al comienzo de la cadena que, en la mayor
parte de los casos, produce un error cuando lo vamos a comparar, a introducir en una base de datos,
etc.
(Vea Ejercicio Cap11 del dis co)
No se pone ningún ejemplo de estas funciones, pues sería difícil verlo impreso.
Busca la cadena1 dentro de cadena y devuelve el
InStr (cadena, cadena1)
número de orden dentro de cadena donde se encuentra la primera letra de cadena1
Resultado = InStr (cadena, "sua")
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
---->
Resultado = 12
Página 22
StrConv
Convierte una cadena de caracteres en otra, según las
instrucciones que le sigan. Puede sustituir a UCase o LCase si la
instrucción es UpperCase o LowerCase respectivamente, o poner la primera
letra de todas las palabras de la cadena en mayúsculas, si la instrucción es
ProperCase.
Resultado = StrConv (cadena, UpperCase)
----> Resultado = CURSO DE
VISUAL BASIC
Resultado = StrConv (cadena, LowerCase)
----> Resultado = curso de visual
basic
Resultado = StrConv (cadena, ProperCase)
----> Resultado = Curso De Visual
Basic
Instrucción Mid
Mid puede usarse también para cambiar el contenido de una cadena. Observe la sutileza entre Mid
como Función de cadena y Mid como Instrucción.
La Instrucción Mid reemplaza un número especificado de caracteres en una variable de cadena con
caracteres de otra cadena.
Sintaxis
Mid(cadena1, inicio[, longitud]) = cadena2
Mid (cadena, 7,2)=”AB”
---- > Resultado = Curso AB Visual Basic
Si la cadena que vamos a introducir tuviera más caracteres, tomará solamente los primeros
Mid (cadena, 7,2)=”ABCDE”
---- > Resultado = Curso AB Visual Basic
Funciones Asc y Chr
Estas funciones se utilizan para obtener el número ASCII de un carácter, y para, sabiendo el número
ASCII, hallar el carácter correspondiente.
Función Asc
Devuelve el código de carácter correspondiente a la primera letra de una cadena de caracteres.
Sintaxis
MiVariable = Asc (Cadena)
Cadena es cualquier expresión de cadena válida. Si la cadena no contiene caracteres, ocurrirá un error
en tiempo de ejecución.
Ejemplo :
Label1 = Asc (“ABCD”)
Label1 presentará 65
Nota Hay otra función (A s c B ) que puede usarse con bytes contenidos en una cadena. En lugar de
devolver el código del carácter para el primer carácter, AscB devuelve el primer byte.
Función Chr
Devuelve el carácter asociado con el código de carácter especificado.
Sintaxis
Chr (CódigoCarácter)
El argumento CódigoCarácter es un número en el intervalo de 0 a 255, inclusive, que identifica a un
carácter.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 23
Ejemplo
Label1 = Chr (65)
Label1 contendrá el carácter A
Como ejemplos de números de caracteres algo especiales se debe señalar el carácter 10 (avance de
línea) y el carácter 13 (Retroceso de carro). La tecla ENTER produce ambos caracteres cada vez que se
pulsa.
Otros caracteres importantes son, el Backspace (carácter 8), y el espacio (carácter 32)
Nota Se proporciona otra función (ChrB) para su uso con datos de byte incluidos en una cadena. En
lugar de devolver un carácter, que puede ser de uno o de dos bytes, ChrB siempre devuelve un solo
byte.
FUNCIONES CON NUMEROS
_________________________
Visual Basic puede operar con números tal como lo haría cualquier persona. Conoce las 4 reglas, y
puede utilizar paréntesis de la misma forma que los escribimos sobre el papel.
Los operadores que utiliza para las operaciones básicas son:
+
*
/
\
Mod
^
Suma
Resta
Multiplicación
División
División sin decimales
Resto de una división
Eleva a un exponente
Ejemplos
Resultado = 12 + 15
Resultado = 15 - 12
Resultado = 15 * 12
Resultado = 15 / 12
Resultado = 15 \ 12
Resultado = 15 Mod 12
Resultado = 12 ^ 2
---->
---->
---->
---->
---->
---->
---->
Resultado = 27
Resultado = 3
Resultado = 180
Resultado = 1.25
Resultado = 1
resultado = 3
Resultado = 144
resultado = ( ( 4 * 3 ) / 2 ) ^ 2
---->
Resultado = 36
Estos operadores se denominan Operadores aritméticos.
Existen otras operaciones que se pueden realizar con números: comparaciones. Los operadores que
realizan comparaciones se denominan Operadores relacionales. El resultado de las operaciones
realizadas con estos operadores solamente admiten dos resultados: True (Cierto) o False (Falso)
Estos operadores son:
=
<>
<
<=
>
>=
Igual que
No igual que
Menor que
Menor o igual que
Mayor que
Igual o mayor que
Estos operadores se suelen utilizar en estructuras de programa donde se tome una decisión.
El operador = puede usarse también para comparar cadenas o fechas.
Operadores Lógicos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 24
Estos operadores podemos usarlos con variables Booleanas, es decir, aquellas que solamente pueden
tomar los valores cero y uno, y con caracteres (un carácter = 1 Byte = 8 bits) realizando la operación
correspondiente bit a bit con los 8 bits de cada carácter. Pero en este caso, los parámetros deben
introducirse en decimal. Por ejemplo, si quiere realizar la función And entre el carácter 15 (00001111) y
el 131 (10000011) , debe ponerlo de la forma Resultado = 15 And 132. El resultado de esta operación
será el byte 00000011, pero como Ud. ya se habrá dado cuenta, le devolverá el valor 3. En el ejercicio
Cap11 puede ver un ejemplo muy explicativo
Operador
Devuelve True si
Devuelve False si
And
A=True y B=True
Cualquier otro caso
Or
A=True o B=True
A=False y B=False
Xor
A=True y B=False
A=False y B=True
A=True y B=True
A=False y B=False
Eqv
A=True y B=True
A=False y B=False
A=True y B=False
A=False y B=True
Imp
A=True y B=True
A=False y B=True
A=False y B=False
A=True y B=False
Not
A=False
A=True
Like
A=True
A=False
Otras Funciones con números
Int , Fix Devuelven la parte entera de un número con decimales
In t y Fix eliminan la fracción de un número y devuelven el valor entero resultante. La diferencia entre In t
y Fi x es que si el número es negativo, In t devuelve el primer entero negativo menor o igual a número,
mientras que Fi x devuelve el primer entero negativo mayor o igual a número. Por ejemplo, Int convierte 8,4 en -9, y Fix convierte -8,4 en -8.
Abs
Devuelve el valor absoluto de un número
Sgn
Devuelve el signo de un número
Sqr
Devuelve la raíz cuadrada de un número
Exp
Devuelve el número elevado al exponente
indicado
Log
Devuelve el logaritmo natural de ese número
Trigonométricas
LSB
Sin
Devuelve el valor del seno de un ángulo
(Expresado en radianes)
Cos
Devuelve el coseno de un ángulo (En radianes)
Tan
Devuelve la tangente de un ángulo
Atn
Devuelve un arco cuya tangente sea el número
Visual Basic – Guía del Estudiante
Capítulo 1
Página 25
(Angulo en radianes)
Funciones para el Cambio de Base de Numeración
Función Hex
Devuelve una cadena, es decir, un string, que representa el valor
hexadecimal de un número.
Sintaxis
VariabledeCadena = Hex (número)
Si número no es un número entero, se redondea al número entero más cercano antes de ser evaluado.
Mediante esta función se puede convertir un número de hasta ocho caracteres hexadecimales.
Se pueden representar números hexadecimales directamente, anteponiendo &H. Por ejemplo, &H10
representa al decimal 16 en la notación hexadecimal.
Función Oct
Sintaxis
Devuelve la cadena (String) que representa el valor octal de un
número.
VariabledeCadena = Oct (número)
Si número no es entero, se redondea al número entero más cercano antes de ser evaluado.
Puede realizarse la conversión hasta el valor de 11 caracteres octales.
Se pueden representar números octales directamente, anteponiendo &O a números en el intervalo
apropiado. Por ejemplo, &O10 representa a 8 en base diez en la notación octal.
Recuerde que estas dos funciones devuelven una Cadena de caracteres, no un número. El
resultado deberá tratarlo como una cadena de caracteres.
Funciones Cxxx para conversión del tipo de datos.
Son un tipo de funciones que convierten un dato o expresión a un tipo de datos determinado
Función Cbool Convierte una expresión al tipo de datos Boolean.
Sintaxis
VariableBooleana = Cbool (expresión)
El argumento expresión es cualquier expresión numérica o expresión de cadena válida.
Si expresión es cero, se devuelve False; de lo contrario, se devuelve True Si la expresión no se puede
interpretar como un valor numérico, ocurrirá un error de tiempo de ejecución.
Función CByte Convierte una expresión al tipo de datos Byte.
Función CCur Convierte una expresión al tipo de datos Currency. (Moneda)
Función CLng Convierte un dato a un tipo Long.
CLng se diferencia de las funciones Fix e Int en que trunca, en vez de redondear, la parte fraccionaria
de un número. Cuando la parte fraccionaria es exactamente 0,5, la función CLng siempre la redondea al
número par más cercano. Por ejemplo, 0,5 se redondea a 0 y 1,5 a 2.
Función CInt Convierte un dato a un tipo Integer.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 26
CInt se diferencia de las funciones Fi x y In t en que trunca, en vez de redondear, la parte fraccionaria de
un número. Cuando la parte fraccionaria es exactamente 0,5, la función CInt siempre la redondea al
número par más cercano. Por ejemplo, 0,5 se redondea a 0 y 1,5 a 2.
Función CDbl Convierte una expresión al tipo de datos Double.
Función CSng Convierte una expresión a un tipo de datos Single.
Debe usar las función CByte, CCur, CLng , CInt en lugar de Va l para proporcionar conversiones que
reconozcan las variantes internacionales, cuando se convierte de cualquier otro tipo de datos. Por
ejemplo, los diferentes separadores decimales se reconocen adecuadamente, dependiendo de la
configuración de la información local de su PC.
Si la expresión a convertir queda fuera del intervalo aceptable para el tipo de datos a obtener, ocurrirá un
error.
Función CStr Convierte una expresión a un tipo de datos String.
Debe usar la función CStr en lugar de Str para proporcionar conversiones que reconozcan las variantes
internacionales, cuando se convierte de cualquier otro tipo de datos a String. Por ejemplo, los diferentes
separadores decimales se reconocen adecuadamente, dependiendo de la configuración de la
información local de su sistema.
Dependiendo del tipo de dato que se va a convertir, CStr devuelve:
Boolean
Date
Null
Empty
Error
Numérico
String conteniendo True o False.
String conteniendo una fecha en el formato de fecha corta de su sistema.
Un error de tiempo de ejecución.
String de longitud cero ("").
String conteniendo la palabra Error seguida del número de error.
String conteniendo el número.
Función Cvar Convierte una expresión a un tipo de datos Variant.
Función Cdate Convierte una expresión al tipo de datos Date. (Fecha / Hora)
Nota curiosa y a tener muy en cuenta
En algunas ocasiones (no siempre, misterios del VB) cuando hacemos una operación entre números,
cuyas variables que los contienen se han declarado de distinto tipo, puede ocurrir que dé un error. Por
ejemplo, queremos obtener una suma que debe ser un Long, a partir de varios números tipo Byte.
Declaramos las variables de la siguiente forma:
Dim Suma as Long, I1 As Byte, I2 As Byte, I3 As Byte, I3 As Byte, I5 As Byte
Suma = I1 + I2 + I3 + I4 + i5
El resultado de esta operación es que da un error, pues no entiende que sumando varios Byte (números
comprendidos entre 0 y 255) puedan dar un número de otro tipo. Dará seguramente el error 6, Overflow.
Para que esto no suceda, haremos el truco de convertir el primero de los números que forman parte en
la operación matemática a un Long, y de esta forma, VB ya se da cuenta que el resultado de esa
operación es un Long:
Suma = CLng(I1) + I2 + I3 + I4 + I5
Tenga en cuenta esa observación inicial que NO ocurre en todas las ocasiones. (Y me parece que era
un fallo de los muchos que tenía VB5)
Otras Funciones
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 27
Una función curiosa
Timer
Tiempo acumulado
Devuelve el tiempo (en segundos) que ha
pasado desde las 12 de la noche.
Generación de números aleatorios
Randomize (Numero) Inicia el generador aleatorio tomando como dato de partida
el Numero. Devuelve el resultado en una variable llamada Rnd.
NOTA MUY IMPORTANTE para versiones de VB anteriores a la 6.- Los números aleatorios
generados de esta forma son siempre iguales, eso sí, dependiendo del número que se le introduzca
como parámetro. Esta generación de números no produce números aleatorios pues como se dijo,
dependen del numero que se meta como parámetro, y si este se repite, se repite la sucesión de números
que nos crea el generador aleatorio. (Afortunadamente lo han corregido en la versión 6)
La forma de obtener números realmente aleatorios es introducir como parámetro un número que sea
variable con el tiempo. Ese número no puede ser otro que el número timer visto antes. Y siempre con la
precaución de que medie mas de un segundo entre dos instrucciones Randomize. La función toma
entonces la forma:
Randomize Timer
La función Randomize devuelve una variable Rnd con un número comprendido entre 0 y 1
(Nunca será 0 ni 1) Leyendo el valor de la variable sucesivas veces, se puede obtener una sucesión de
números aleatorios. No es necesario ejecutar la instrucción Randomize Timer cada vez que se quiera
obtener un dato de la variable Rnd.
Un ejemplo. Generador de números para la Lotería Primitiva
Supongamos que tenemos un formulario con una etiqueta de nombre Label1, un botón de comando de
nombre Command1. Cuando hagamos click sobre el botón de comando deberá generar un número
comprendido entre el 1 y el 49. En el procedimiento click de Command1 pondremos el siguiente código:
Private Sub Command1.click
Randomize Timer
A = Rnd * 100
A = CInt(A)
Do While A > 49
A = A - 49
Loop
Do While A < 1
A = A + 49
Loop
Label1.caption = A
End Sub
Realice este pequeño programa, con la instrucción Randomize Timer y sin ella.
Funciones con fechas.
Las fechas son cadenas especiales. Visual Basic sabe obtener y tratar la información relativa a la fecha y
la hora. Dispone para ello de una declaración de variable: Date. Una variable declarada como date
puede contener una fecha, una fecha y una hora o una hora solamente.
Date
LSB
Devuelve la fecha de hoy. Esta fecha la toma del reloj del ordenador.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 28
Time
Devuelve la hora actual.
Now
Devuelve la fecha y hora actual.
WeekDay
Devuelve el día de la semana (En número, 1=Domingo, 2=Lunes,...)
Day
Obtiene el día, a partir de una fecha
Month
Obtiene el mes a partir de una fecha.
Year
Obtiene el año a partir de una fecha.
Hour
Obtiene la hora a partir de una hora
Minute
Obtiene el minuto a partir de una hora.
Second
Obtiene el segundo a partir de una hora.
DateAdd
Añade un intervalo de tiempo a una fecha
DateDiff
Obtiene el intervalo de tiempo entre dos fechas
DatePart
Devuelve una parte de una fecha (semana, trimestre, etc.)
DateSerial
Compone una fecha a partir de parámetros relativos
TimeSerial
Compone una hora a partir de parámetros relativos.
DateValue
Devuelve una fecha a partir de un dato que se le parezca y VB
pueda obtener de él una fecha válida
Mediante estas instrucciones podemos obtener el dato necesario de una fecha u hora. Por ejemplo, para
obtener el día de hoy solamente:
Día = Day (Now)
Día será un número
El día de la semana lo obtendríamos
Diasemana = WeekDay (Now)
Diasemana será un número
DateValue, una instrucción que le sacará mucho provecho
Fecha = DateValue (12-07-96)
Fecha = DateValue (12 07 96)
Fecha =12/07/96
La función DatePart merece estudio aparte. Con esta función podemos averiguar el mes, trimestre,
semana, día del año, etc.
La sintaxis de esta función es :
VariableNumérica = DatePart (Intervalo, fecha[, primerdíasemana[, primerasemanaaño]])
Valor para Intervalo
q
m
y
d
w
LSB
Obtendremos el
Trimestre
Mes
Día del año
Día
Día de la semana
Visual Basic – Guía del Estudiante
Capítulo 1
Página 29
ww
h
n
s
Semana
Hora
Minuto
Segundo
El parámetro Primerdíasemana puede ser un número o una constante (veremos a lo largo de todo el
curso, que VB usa constantes que son palabras reservadas por VB que generalmente comienzan por
vb) que indica que día es para nosotros el primero de la semana
Constante
vbSunday
vbMonday
vbTuesday
vbWednesday
vbThursday
vbFriday
vbSaturday
Número
1
2
3
4
5
6
7
Primer día de la semana
Domingo (predeterminado)
Lunes
Martes
Miércoles
Jueves
Viernes
Sábado
Para el parámetro primerasemanaaño podemos emplear uno de los siguientes números o constantes:
Constante
Valor
Descripción
vbFirstJan1
1
vbFirstFourDays
2
vbFirstFullWeek
3
Empieza con la semana en la que se encuentra el 1 de enero
(predeterminado).
Empieza con la primera semana que tenga al menos cuatro
días en el año nuevo. (Standard ISO 8086)
Empieza con la primera semana contenida completamente en
el año nuevo.
Por ejemplo, y tomando como referencia para todos los ejemplos el día 22 de Septiembre de 1998, fecha
en la que se ha escrito este texto, (Now = 22/09/1998), tenemos :
Variable = DatePart (“m”, Now)
variable = DatePart ("q", Now)
variable = DatePart ("d", Now)
variable = DatePart ("y", Now)
variable = DatePart ("w", Now)
Variable = 10
Variable = 3
Variable = 22
Variable = 265
Variable = 3 (Martes, pues el primer día de la semana
era el domingo - Predeterminado)
variable = DatePart ("w", Now, vbMonday)
Variable = 2 (Primer día semana = lunes)
variable = DatePart ("ww", Now, vbMonday, vbFirstFourDays)
Variable = 39, que indica el número de la semana dentro del año.
Cuidado con como se escriben las fechas. Una posibilidad es la usada en los ejemplos, pero solamente
vale para el día de hoy. Puede expresar la fecha metiéndola entre dos signos #, pero en ese caso debe
estar expresada en el formato mm/dd/yy (mes/día/año). Ejemplo :
variable = DatePart("ww", #9/22/98#, vbMonday, vbFirstFourDays)
Pero lo mas fácil para el formato de fecha usado en España es meter la fecha entre comillas dobles, y
usar el formato especificado para el país :
variable = DatePart("ww", "22/9/98", vbMonday, vbFirstFourDays)
Con las comillas dobles puede incluso no poner el año. En este caso le pone por defecto, el año en
curso.
variable = DatePart("ww", "22/9", vbMonday, vbFirstFourDays)
Estas tres formas de expresar la fecha funcionan perfectamente, al igual que cuando lo hacíamos con
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 30
Now, y el resultado sigue siendo 39.
Nota para recordar de las variables tipo Date
(No se extrañe que esta explicación la encuentre solamente en esta Guía del Estudiante)
Visual Basic trata las fechas como números. Y precisamente como un número Double. Emplea por lo
tanto 8 bytes para representar una fecha. Por ejemplo, al día 12 de Julio de 1999, (Fecha en la que el
autor de este libro alcanzó la respetable edad de #9 años) le corresponde el valor de 36563. Ese es el
número de días transcurridos desde el origen de tiempos tomado por VB (Y por muchas otras
aplicaciones de Microsoft y de otras marcas) hasta ese fatídico día. ¿ Cual es ese origen del tiempo? El
30 diciembre 1899. ¿Que porqué ese día?. No lo sé. Pero es fácil intuir que motivos prácticos para que
cualquier fecha del siglo XX tuviese un número positivo. Porque las anteriores a ese día las trata como
números negativos. Por ejemplo, el día 12 de Octubre de 1492, VB lo trata como el día número 148.732. Ese numero puede conocerlo utilizando la función CDbl sobre una variable tipo Date. Puede
verlo en el ejercicio Cap12 del disco.
Una hora también es una variable tipo Date. Y una composición Día / Hora también. ¿Que como trata
los minutos dentro de una variable Date? Pues como decimales de ese número Double. Por ejemplo, la
hora 12:00:00 del día 12 de julio de 1999 es para VB
36.563,5
Es decir, la parte decimal representa la fracción de día transcurrido desde el comienzo del día
(medianoche) hasta la hora en cuestión. No debemos confundir esta fracción del día (0,5 para las
12:00:00) con el valor de la función Timer para ese instante (45.000)) que representa el número de
segundos transcurridos desde la 12 de la noche de ese día.
Cuando se tratan variables tipo Date, VB que es un lenguaje inteligente, interpreta como tipo de datos
Date determinados datos que no lo son. Por ejemplo, 12 Julio 1999 es tal y como puede verse, una
sucesión de caracteres. Si ejecutamos el código:
Dim Pepe as Date
Pepe = “12 Julio 1999”
‘ A partir de ahora, Pepe contendrá el valor 36.563
‘ Para ver ese valor basta con hacer
Label1.Caption = CDbl (Pepe)
Al estar Pepe declarada como variable tipo Date, VB busca todas las posibilidades de extraer una fecha
(o una hora) del dato que le estamos metiendo. Otra cosa ocurriría si la declarásemos como String o
Variant. En cualquiera de estos casos, Pepe contendría el literal introducido, es decir, “12 Julio 1999”
De lo anterior se desprende una cosa, dado que la fecha la guarda como un número, no importa en que
formato le introduzcamos una fecha. Si ponemos que Fecha1 = “12/7/99” es idéntico a poner fecha1 =
12/07/1999 ó Fecha1 = 1999-07-12. Eso sí, debe reconocer el formato, y luego, el dato, lo tratará como
un número Double. Lo volveremos a ver cuando estudiemos las bases de datos. Access trata las fechas
de idéntica forma.
Función FORMAT
Esta función permite presentar cadenas numéricas o fechas de una determinada forma. Permite
establecer el Formato de esa cadena.
Si recurre a la ayuda de VB acerca de esta función se va a enterar muy poco de lo que puede dar de sí.
La sintaxis que presenta es :
Format(expresión[, formato[, primerdíadesemana[, primerasemanadelaño]]])
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 31
Lo mejor que puede hacer con esta definición de la sintaxis de Format es olvidarla. No le aclara mucho lo
que se puede hacer con Format. La función Format se usa para poner una fecha en un determinado
formato. Con la expresión :
FechadeHoy = Format (Now, “yyyy-mm-dd”)
la variable FechadeHoy tendrá el valor 1998-05-21, que se refiere al día 21 de mayo de 1998, según el
formato recomendado por la norma ISO-8601 para la presentación de fechas. Si hubiésemos puesto la
expresión FechadeHoy = Format (Now, “dd/mm/yy”) , la variable FechadeHoy contendría el valor
21/05/98 referido al día citado.
Las posibilidades de Format llegan también al campo de las cadenas numéricas. Por ejemplo la cifra
123456 se transformará en las siguientes expresiones, según como empleemos la función Format
Variable = Format(123456, "Currency")
Variable = Format(123456, "Standard")
Variable = 123.456 Pts
Variable = 123.456,00
Veamos ahora con un poco mas de conocimiento la sintaxis de Format
Variable = Format (expresión[, formato[, firstdayofweek[, firstweekofyear]]])
No se complique la vida con el tema del primer día de la semana ni la primera semana del año. No lo
usará con frecuencia. Centrémonos mas en el parámetro Formato. Puede tomar muchos valores.
Veamos los principales. Primero para números
Observe que usamos la expresión Variable = Format (1234567,”Formato”) para todos los ejemplos de
números.
Para poner los números separados por millares :
Variable = Format(1234567, "##,###,###")
Variable = 1.234.567
(Cada carácter # indica que ahí va un número. El separador debe ser una coma, no un punto, aunque
esto depende del idioma que esté usando)
Puede poner una de estas expresiones, eso si, siempre entre comillas dobles :
General Number
Currency
Fixed
Standard
Percent
Scientific
.
Muestra el número tal como lo tecleó
En formato de la moneda de su sistema operativo
Sin separador de millar y dos decimales (1234567,00)
Con separador de millares y dos decimales (1.234.567,00)
Multiplica el número por cien y lo presenta cono
porcentaje(123456700,00%)
Usa notación científica (1,23E+06)
Para fechas (Observe que usamos el ejemplo Format(Now, “Formato”) siendo Now la fecha y hora
actual (21/07/98 a las 22:16:00 )
General Date
Long Date
Medium Date
Short Date
yyyy-mm-dd
yy-mm-dd
Long Time
Medium Time
Short Time
LSB
21/07/98 22:16:00
martes 21 de julio de 1998
21-jul-98
21/07/98
1998-05-21
98-07-21
22:19:53
10:20 PM
22:20
Visual Basic – Guía del Estudiante
Capítulo 1
Página 32
hh :mm :ss
hh :mm
22 :21 :29
22 :21
RECOMENDACIÓN ISO 8601
Va como cultura general. Esta recomendación dice que el formato de fecha debe ponerse de la forma
yyyy-mm-dd (p.e. 1998-10-05 para referirse al 5 de Octubre de 1998). Para este formato, pondremos :
FechaISO8601 = Format (Now, “yyyy-mm-dd”)
Tenga presente esta recomendación. La Administración Española está obligada a exigir su cumplimiento
en todas aquellas aplicaciones que realicen intercambios de fecha y hora.
Format dispone de mas opciones. Sería muy largo explicarlas aquí. Para mas información, en la WEB
de Microsoft (www.microsoft.com) puede encontrar mas formatos posibles.
Pero vamos a volver con el tema de las variables tipo Date.
Cuando realizamos el Format sobre una fecha, esta fecha puede ser un literal (un string), o una variable
tipo fecha
Si en Text1 tenemos la expresión 12 Julio 1999, y queremos convertir esa fecha al formato ISO 8601,
podemos hacerlo de cualquiera de estas dos formas:
Private Sub LFormat1_Click()
Dim Pepe As Date
Pepe = Text1.Text
LFormat1 = Format(Pepe, "yyyy-mm-dd")
End Sub
Ó
Private Sub LFormato2_Click()
LFormato2 = Format(Text1.Text, "yyyy-mm-dd")
End Sub
La función Format es suficientemente inteligente para darse cuenta que con el formato yyyy-mm-dd le
estamos pidiendo una fecha. Si le metemos una fecha no hay problema (caso de meterle Pepe, variable
declarada como Date). Pero si le metemos una cadena de caracteres (caso de Text1.Text) intenta
obtener de esa cadena una fecha válida. Si lo consigue lo presenta. Si no lo consigue, dará un error.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 33
MATRICES
__________
Cuando utilizamos varias variables que tienen un significado similar para nosotros, pero que son distintas
(Por ejemplo, el nombre de los alumnos de una clase) podemos utilizar una matriz. Esta matriz está
formada por tantos elementos como alumnos tenga la clase. El nombre asociado a cada uno de los
elementos de la matriz puede ser:
Alumno (n)
Donde n es el número por orden de lista de ese alumno.
Las matrices normalmente comienzan a numerar por el número 0. Este comienzo puede no ser el mas
apropiado para la variable que estamos planteando, pues ningún alumno tiene el número de orden 0.
Para hacer que una matriz comience a numerar por el 1 se debe definir mediante la instrucción:
Option Base 1
que debe colocarse al comienzo del módulo o formulario donde declaremos la matriz.
Para declarar la matriz se hace como con todas las variables, especificando entre paréntesis el número
de elementos que componen la matriz:
Dim Alumno (25) as String
Hemos declarado que la variable alumno es una cadena, y que hay 25 elementos en esa matriz.
Una matriz también se puede declarar de la siguiente forma :
Dim Alumno(1 To 25) as String
Donde le decimos que la variable Alumno tiene 25 elementos, que el primero tiene el índice 1 y el último
tiene el índice 25.
Pero imaginemos que queremos meter en la misma matriz el nombre, primer apellido y segundo apellido
del alumno. Necesitaremos declarar una matriz de 25 por 3. Como todos los elementos serán cadenas
de caracteres, podemos declararla de la siguiente forma:
Dim Alumno (1 To 25, 1 To 3) As String
De esta forma, el primer apellido del alumno que ocupa el puesto número 15 de la clase, será el
elemento:
Alumno (15, 2)
Podemos definir matrices de dimensión superior a dos. Podemos llegar a un máximo de 60 dimensiones.
Una matriz de 5 dimensiones se declararía:
Dim Variable ( 1 To N, 1 To M, 1 To P, 1 To Q, 1 To R)
entendiendo que hay N, M, P, Q y R elementos en cada una de las dimensiones respectivamente.
Una variable ya declarada como una matriz puede redimensionarse a lo largo del programa mediante la
instrucción ReDim
ReDim Alumno (1To 25)
Mediante esta instrucción, estamos ReDimensionando una matriz ya declarada. No se puede
redimensionar una matriz inexistente.
Mediante la declaración 1 To 25 le estamos diciendo que el primer elemento de la matriz es el 1,
independientemente de lo que hayamos puesto en OPTION BASE. Si se redimensiona simplemente
con el número de elementos :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 34
ReDim (25)
le estamos diciendo que tiene 25 elementos, pero que el primero sea el 0 ó el 1 depende de haber
puesto OPTION BASE 0 u OPTION BASE 1.
Una matriz puede redimensionarse cuantas veces se quiera a lo largo de la aplicación, pero esa
redimensión no puede afectar al número de dimensiones de la matriz. Si redimensionamos la matriz
perd erála info rm ación exis tente . Para evitar perder la información presente en la matriz, debe utilizar
la sentencia ReDim Preserve.
Si usa la palabra clave Preserve en matrices de dimensión superior a 1, va a encontrarse con
comportamientos no esperados. Como podrá ver en la Ayuda de VB, usando ReDim Preserve sólo
puede cambiar el tamaño de la última dimensión de matriz y no puede modificar en ningún momento el
número de dimensiones. NO es cierto del todo. SÍ lo podrá hacer una sola vez.
Respecto a cambiar el número de dimensiones, si ha declarado la matriz con unas dimensiones
determinadas, ya no podrá cambiar las dimensiones ni con ReDim ni con ReDim Preserve. Le saldrá un
error que dice que las dimensiones de la matriz ya han sido declaradas.
Pero si ha declarado la matriz sin dimensiones :
Dim MiMatriz()
puede cambiar las dimensiones
y volver a cambiarlas
ReDim MiMatriz (1 To 5, 1 To 9)
ReDim MiMatriz (1 To 8, 1 To 15, 1 To 6)
Observe que no solamente la hemos cambiado dos veces de dimensiones (la primera a 2 y la segunda a
3), sino que también hemos cambiado el número de elementos en cada dimensión.
Si hubiésemos utilizado ReDim Preserve solamente podríamos haber usado la primera de las dos líneas
anteriores :
ReDim Preserve MiMatriz (1 To 5, 1 To 9)
pero ya no podríamos volver a cambiar el número de dimensiones con la segunda línea. Nos daría un
error.
Con ReDim podemos cambiar el número de elementos de cada dimensión cuantas veces queramos.
Por ejemplo, podemos redimensionar MiMatriz de las siguiente forma :
ReDim MiMatriz (1 To 5, 1 To 9)
ReDim MiMatriz (1 To 15, 1 To 20)
ReDim MiMatriz (1 To 25, 1 To 30)
...........................
Si hubiésemos empleado ReDim Preserve, podríamos cambiar los elementos de todas las dimensiones
de la matriz una vez :
ReDim Preserve (1 To 5, 1 To 9)
a partir de ahora, solamente podemos cambiar los elementos de la última dimensión :
ReDim Preserve (1 To 5, 1 To 20)
ReDim Preserve (1 To 5, 1 To 30)
es decir, no podremos hacer esto :
ReDim Preserve (1 To 10, 1 To 30) donde se señala en negrita el error.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 35
Esto no causa ningún error en una matriz de una dimensión, ya que si la matriz tiene sólo una dimensión,
puede cambiar el tamaño de esa dimensión porque es la única y la última.
Cuando a lo largo de la aplicación se va redimensionando una matriz, podemos llegar la circunstancia de
que, en un momento determinado, no sepamos las dimensiones de esa matriz.
Para conocer el índice máximo y mínimo de una matriz se usan las funciones UBound y LBound.
UBound devuelve el mayor subíndice disponible para la dimensión indicada de una matriz.
UBound(nombredelamatriz[, dimensión])
Sintaxis
LBound devuelve el mayor subíndice disponible para la dimensión indicada de una matriz.
Sintaxis
LBound(nombredelamatriz[, dimensión])
Ejemplo Tengamos una matriz llamada Mimatriz, de tres dimensiones. En un momento de la aplicación
se ejecutó la siguiente instrucción válida :
ReDim Mimatriz (1 To 100, 0 To 3, 5 To 20)
En otro momento queremos tener el control de los índices de esa matriz, y queremos averiguar el índice
menor y mayor de cada una de sus dimensiones :
(IID1= Indice Inferior Dimensión 1, ISD 1 = Indice Superior Dimensión 1, etc. )
IID 1= LBound (Mimatriz, 1)
ISD1 = UBound (Mimatriz, 1)
IID 2= LBound (Mimatriz, 2)
ISD2 = UBound (Mimatriz, 2)
IID 1= LBound (Mimatriz, 3)
ISD1 = UBound (Mimatriz, 3)
IID1 = 1
ISD1 = 100
IID1 = 0
ISD1 = 3
IID1 = 5
ISD1 = 20
Función Split
Una vez visto lo que es una matriz, vamos a ver una función interesante para el tratamiento de cadenas
de caracteres. La función Split
Descripción
Esta función toma una cadena de caracteres compuesta varias subcadenas, separadas entre ellas
mediante un separador, y devuelve una matriz de una dimensión, que contiene esas subcadenas.
Sintaxis
Split (expresión[, delimitador[, contar[, comparar]]])
Donde:
Expresion es la variable que contiene la cadena de caracteres de entrada
Delimitador. Contiene el carácter o caracteres que se usan de delimitador entre subcadenas
Contar es un número donde indicamos el número de subcadenas que queremos extraer. Si no
se pone nada, extrae todas las cadenas. Si se pone un valor, extrae el número de cadenas que
le indiquemos. En este caso, en la última cadena, mete el resto de subcadenas que quedaban
sin meter.
Comparar es un valor numérico que nos da cuatro opciones de comparación para comparar las
subcadenas. Este parámetro es solamente para alumnos avanzados
Ejemplo.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 36
En el siguiente ejemplo veremos como separar distintos datos que están dentro de un TextBox (Text1)
separados entre ellos por una coma.
Private Sub Command1_Click()
Dim MiVariable() As String
Dim I As Integer
MiVariable = Split(Text1.Text, ",")
For I = 0 To UBound(MiVariable)
List1.AddItem MiVariable(I)
‘Declaramos una matriz (MiVariable) del tipo String
‘Declaramos una variable auxiliar como numérica
‘Ejecutamos la función Split
‘Ejecutamos un bucle para introducir las subcadenas
‘en un ListBox
Next I
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 37
VISUAL BASIC
Tras esta pequeña introducción al lenguaje Basic ya estamos en disposición de encender el ordenador y
comenzar a trabajar con Visual - Basic. Se supone que su PC tiene instalado el programa Visual Basic
6.0
Entre en el programa VB. Le aparecerá en pantalla algo similar a esto : (Para VB Vers. 6)
Fig. 1.2 Aspecto del entorno de desarrollo de aplicaciones VB
Este es el comienzo del VB . Observe que en esta pantalla existen varias cosas. En la parte superior , la
barra de título del programa Visual Basic, con el texto :
Proyect1 - Microsoft Visual Basic (Diseño)
Por debajo de esta barra de Título del VB, encontramos la barra de menú de VB, con las leyendas :
Archivo Edición Ver Proyecto Formato Depuración Ejecutar Consulta Diagrama Herramientas
Complementos Ventana Ayuda
Por debajo de esta barra de menú tenemos la barra de herramientas, donde podrá ver varios iconos,
que cada uno representa un determinada operación que Vd. puede realizar. Estas operaciones está
todas en la línea de menú, y puede acceder a ellas abriendo los menús desplegables que existen en
cada una de las palabras Archivo Edición Ver ...... de esta línea de menú. El hecho de colocar las
operaciones mas usuales en un icono en la barra de herramientas se hace para mayor comodidad del
usuario.
A la izquierda o derecha de la pantalla tiene una caja rectangular con varias columnas de iconos. Esa
caja es la Caja de Herramientas (No la confunda con la barra de herramientas de la parte superior)
Esta caja de herramientas es, salvando las distancias, lo mismo que una caja de herramientas real que
pueda tener un mecánico para realizar su trabajo. En ella están los iconos que representan a los
controles con los que Vd. va a desarrollar su aplicación VB. No están todos los que pueden estar, al igual
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 38
que en una caja de herramientas de un mecánico no están todas las herramientas que puede usar.
Están solamente las mas usuales. Si necesita alguna mas, puede cogerla de otra parte (barra de Menú,
Proyecto | Componentes) y agregarlos a esa caja de herramientas, al igual que lo haría un mecánico con
una herramienta especial, que la metería en su caja sólo cuando va a realizar un trabajo determinado
para el que la necesite.
Posiblemente esta caja de herramientas no le aparezca tal y como la ve en esta figura. Eso depende de
la versión y la personalización. Para añadir un nuevo control haga click en Proyecto | Componentes y le
aparecerá una caja con todos los controles existentes. Puede seleccionar nuevos controles para añadir a
la caja de herramientas, marcando la casilla que está a la izquierda del nombre del control que quiere
introducir. Una vez seleccionados todos los nuevos controles, haga click en APLICAR . Salga haciendo
Click en ACEPTAR, y podrá observar que esos nuevos controles ya se le han añadido a la caja de
herramientas. Esos controles le aparecerán cada vez que cargue el proyecto actual. No es prudente
meter muchos controles en la caja. Ponga solamente los que necesite normalmente en sus aplicaciones.
Ocupará menos memoria y tardará menos tiempo en cargar el programa VB. Además, cuando realice
una aplicación y la distribuya una vez compilada, Visual Basic entregará en los disquetes de distribución
las DLL’s u OCX’s correspondientes a todos los controles personalizados que Vd. tenga en la caja de
herramientas, los necesite el programa o no los necesite. Esto le va a suponer que está cargando
subprogramas inútiles en el ordenador destino de su aplicación. A la hora de compilar el programa
(Crear archivo .EXE) quite todos los controles personalizados que no necesite su aplicación. (Sólo los
controles personalizados. Los controles comunes - CommandButton, Label, TextBox, etc.-, no se pueden
eliminar de la caja de herramientas)
Para quitar controles de su caja de herramientas, debe proceder de forma análoga, a lo que hizo para
meterlos en la caja de herramientas, pero al revés. No se preocupe a la hora de quitarlos. Si está
utilizando un determinado control, VB no le dejará quitarlo.
En el centro, y ocupando casi toda la pantalla, tenemos el Formulario. Este Formulario es la interface
gráfica de su aplicación, sobre el que podrá añadir los controles que necesite. Lo veremos mas adelante
con todo detalle.
Puede tener dos ventanas más adosadas a la caja de herramientas, una denominada Ventana de
Propiedades, donde puede ver las propiedades del formulario o de cualquier control que tenga dentro
del proyecto, y otra, denominada Ventana de Proyecto, donde puede ver todos los formularios
existentes. Existen otras ventanas, por ejemplo la Ventana de Depuración. Por cada formulario y cada
control que introduzca en el proyecto, le aparecerá otra ventana, denominada Ventana de código.
No se extrañe de que esta presentación gráfica del Visual Basic coincida con otros sistemas de
desarrollo (Delphi, p.e.). La lógica de desarrollo de una aplicación en Windows ha llevado a varios
fabricantes de software a utilizar un entorno gráfico similar (diríamos idéntico). A Visual basic le queda el
orgullo de ser el primero en utilizarlo. (¡Y el mejor!)
Con lo descrito anteriormente ya tenemos, al menos, fijado el argot con el que expresarnos para
comenzar a estudiar el VISUAL BASIC. Veamos con un poco mas detalle la Ventana de Código.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 39
Fig. 1.3 Ventana de código
Esta figura le muestra un Formulario con su ventana de código. Cada objeto gráfico de VB tiene su
propia ventana de código. Así, si en este formulario hubiésemos introducido un Label y dos
CommandButton, todos ellos tendrían su propia ventana de código. La ventana de código la podemos
ver haciendo doble click sobre cualquier objeto de nuestro proyecto. En este caso hemos hecho doble
click sobre el único objeto que teníamos : el formulario.
Observe las dos cajas de la parte superior, uno con la inscripción Objeto : que en el momento que le
sacamos la foto tenía Form, y el otro con la inscripción Proc : (procedimiento), que en el momento de la
foto tenía Load. A estas cajas les denominamos Lista de Objetos y Lista de Procedimientos
respectivamente.
Haciendo click sobre la flecha de cada lista, se despliega un menú, en la lista de objetos se desplegará
una lista con los nombres de cada objeto existente en ese momento dentro del formulario. Haciendo click
sobre uno de los nombres, nos presentará la ventana de código de ese objeto. Todos los objetos
gráficos (controles) existentes dentro de un formulario y el propio formulario aparecerán en la misma lista
de objetos.
Haciendo click sobre la flecha de la lista de procedimientos, se despliega la lista con todos los
procedimientos posibles para ese objeto. Siempre saldrá uno. Si tenemos escrito código en uno de los
procedimientos, saldrá por defecto ese procedimiento para el cual hemos escrito el código. Si no hay
código en ninguno de los procedimientos, saldrá el que tenga por defecto cada objeto.
Solamente nos queda por decir, para cerrar este capítulo, que es un procedimiento.
Para ello vamos a explicar lo que es un evento. Un Evento es algo que le puede ocurrir a un objeto. En
una interface gráfica, lo que le puede ocurrir a un objeto es que se le haga click, doble click, que se pase
el cursor del ratón por encima, etc. Este es el Evento. El Procedimiento es la respuesta por parte de
ese objeto, al evento que le está sucediendo.
Esa respuesta, esa forma de Proceder del objeto al evento que le está sucediendo, debemos
programarla según nuestras necesidades, es decir, debemos escribir el código que necesite nuestra
aplicación como respuesta al evento que acaba de ocurrir. Posiblemente, no queramos ninguna
respuesta a muchos de los eventos que pueden acaecer a un objeto. Cada objeto tiene muchos eventos
y solamente queremos aprovechar los que nos interesan. Para que un evento no produzca ningún
efecto, basta con dejar sin código el procedimiento correspondiente a ese evento. En los eventos que
queramos que realice alguna operación, le escribiremos en su procedimiento el código necesario para
que esa operación se realice. Sin darnos cuenta, hemos comenzado a escribir el código de la aplicación.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 40
Observará que el primer elemento del menú desplegable de la lista de objetos se denomina General.
Este no es en realidad ningún objeto, sino un apartado existente en cada formulario, que, al desplegar su
lista de procedimientos tiene la sección de declaraciones, donde debemos declarar las variables que
queremos que afecten a todo el formulario y sus controles, y tendrá además, los nombres de todos los
procedimientos que introduzcamos (véase un poco mas adelante). En este menú desplegable de la
lista de procedimientos del General verá con frecuencia cosas que Vd. no puso allí. Cosas tales como
Command1_click, y en la ventana un determinado código. Esto ocurre cuando se borra algún control que
tenía escrito código en alguno de sus procedimientos. Visual Basic sabe lo mucho que cuesta escribir el
código asociado a un control. Si borramos un control de nuestro formulario accidentalmente, después de
haber introducido todo el código asociado a él, Visual Basic nos sorprende con que ese código no lo tira
inmediatamente, sino que lo reserva como un procedimiento en ese apartado General del formulario. Si
en realidad queríamos borrar el control y todo su código, debemos quitarlo de ese apartado General de
nuestro formulario, pues en realidad, si no lo queremos, no hará otra cosa que estorbar. Para quitarlo
basta con borrar todo el código que aparece en la ventana de código cuando hacemos click sobre el
nombre del control eliminado. Deberemos borrar todo el código, incluida la cabecera donde figura el
nombre del control eliminado, y la parte final, que siempre termina con End Sub.
El primer estorbo lo observará si crea otro control con el mismo nombre, cosa fácil ya que VB da un
nombre por defecto a cada control (Command1, Command2....). El código asociado al control eliminado
pasará automáticamente al nuevo control con el mismo nombre.
Una aplicación puede tener todo su código escrito en los sucesivos procedimientos del formulario y de
los controles que tenga ese formulario.
Puede ocurrir que un determinado evento no esté entre los posibles eventos de los controles de nuestra
aplicación. Piense por ejemplo, el evento de que la variable A sea igual a la variable B. No existe en
ninguno de los controles ese procedimiento. No se preocupe, puede crear un procedimiento que se
ejecute cuando su programa lo decida. Podemos añadir cuantos procedimientos queramos. Estos
procedimientos se añaden al formulario, y deberán definirse por un nombre que Vd. debe elegir. Para
que se ejecuten las instrucciones (código) incluido en ese procedimiento, basta simplemente con
nombrarlo por ese nombre.
Para insertar un procedimiento debe ir a la barra de menú, hacer click sobre Herramientas, y en el menú
que le desplegará, volver a hacer click sobre Agregar Procedimiento. VB le presentará un cuadro donde
le pedirá el nombre, si quiere que sea un procedimiento, una función o una propiedad. A lo largo del
curso irá viendo que es cada cosa.
Escribiendo el código en los sucesivos procedimientos, bien en los propios de cada objeto, bien en los
procedimientos que vayamos creando, es posible completar la aplicación. Pero en una aplicación larga
esta forma de escribir el código no sería la mas adecuada. Es mas, posiblemente sería demasiado
engorroso escribirla de esta forma, y muy probablemente deberíamos escribir el mismo código para
varios procedimientos, lo que alargaría inútilmente el programa y el tiempo de desarrollo.
Para disponer de un sitio donde escribir parte (o la mayor parte) de su programa, puede introducir uno o
varios módulos. Expliquemos lo que es un módulo.
Un Módulo es una parte del programa donde solamente puede escribir código. Es igual que un
formulario, sin interface gráfica. Un profesor de Visual Basic lo expresaba diciendo que un Módulo es un
Formulario sin cara. En un módulo pueden existir procedimientos al igual que en los formularios, pero
como un módulo no tiene interface gráfica, esos procedimientos debe introducirlos el programador tal y
como explicamos un poco mas atrás. El módulo tiene su propia ventana de código, al igual que un
formulario, con un objeto único, el apartado General. Aquí también tenemos la sección de declaraciones,
al igual que los formularios. En esta sección de declaraciones se comporta de manera similar a la de los
formularios, pero permite algo que no nos permite la sección de declaraciones de un formulario :
Declarar variables que se pueden utilizar en todo el programa. Esto ya lo ha visto mas atrás, con la
sentencia de declaración Public.
Los módulos se emplean para la declaración de variables globales, y para escribir el código de la
aplicación que sea común a varios formularios. Esto nos evita tener que repetir código inútilmente. Ese
código común se escribirá en un procedimiento que previamente habremos insertado en este módulo, y
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 41
lo citaremos por su nombre desde cualquier parte del programa.
Los procedimientos se pueden introducir en los módulos o en los formularios. Y les pasa lo mismo que a
las variables en cuanto a su ámbito. Para agregar un procedimiento debe abrir una ventana de código
(cualquiera) perteneciente al módulo o formulario donde quiera insertar ese módulo, y a continuación
hacer click sobre Herramientas | Agregar Procedimiento de la Barra de Menú.
Fig. 1.4 Agregando un procedimiento
Nos aparecerá un cuadro donde le debemos poner el nombre de ese procedimiento y elegir el ámbito
(Alcance en la figura) que le queremos dar, público o privado.
Fig. 1.5 Cuadro para agregar un procedimiento o función
Si un procedimiento es público, se podrá acceder a él desde cualquier parte de la aplicación. Si es
privado, solamente desde el módulo o formulario donde se ha introducido.
¿Cual es el nombre por el que podemos llamar a ese procedimiento? Sigue las mismas normas que
para las variables. Si se ha declarado como público en un módulo, se le citará por su nombre cualquiera
que sea la parte del programa desde donde le citemos.
p.e. CalculaGastos
Si se ha declarado como publico en un formulario, deberemos llamarle con el nombre del formulario,
seguido del nombre del procedimiento separado por un punto
p.e.
Formulario1.CalculaGastos
Si se ha declarado como privado, se le llamará por el nombre, pero solamente desde el código del
módulo o formulario donde se insertó, puesto que desde otro módulo o formulario no se verá.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 42
Fíjese en el punto usado como separador entre el nombre del formulario y el nombre del procedimiento.
VB usa como separador un punto. Usa el separador para separar el nombre de un control y una de sus
propiedades (Label1.Caption), para separar el nombre del formulario del nombre de uno de sus
controles (Formulario1.label1.caption) Se irá familiarizando con la terminología VB según vayamos
avanzando en el curso.
Call
En Visual Basic, para ejecutar un procedimiento no hace falta usar la sentencia Call, muy propia de otros
lenguajes de programación. Hay programadores que la usan no sé si porque creen que es necesario, o
porque piensan que queda más bonito. No hace falta pero VB lo soporta. Queda a gusto del
programador usarla o no usarla.
Funciones
Al igual que introducimos Procedimientos, podemos introducir Funciones en nuestra aplicación. Una
Función es un Procedimiento al que le pasamos uno o varios parámetros. (O Ninguno) y nos devuelve
un valor. Verá los Procedimientos y funciones mas adelante (Cap. 15). Al igual que los Procedimientos,
pueden ser públicas (se verán en toda la aplicación) o privadas (se verán solamente en el formulario o
módulo donde estén. Se introducen igual que los procedimientos,
Main
Merece la pena pararse un poco para estudiar el Procedimiento Main. Para verlo con mas detalle,
comentaremos como comienza a trabajar una aplicación realizada en Visual Basic.
Imaginemos una aplicación que tiene 3 Formularios. En cada uno de ellos tiene código. Lógicamente la
aplicación tendrá que presentar uno de ellos en primer lugar. Deberemos decirle a Visual Basic cual es el
formulario inicial, y será ese por el que empiece. En ese formulario dispondremos el código necesario
para que la aplicación se ejecute en el orden deseado.
Si hacemos click en la Barra de Menú de Visual Basic, en Proyecto | Propiedades obtendremos el
siguiente cuadro de diálogo :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 43
Fig. 1.6 Cuadro de propiedades del Proyecto
Verá que tiene 5 pestañas, y actualmente tiene abierta la pestaña correspondiente a General, y tiene
desplegada una lista donde nos pide el Formulario Inicial. En esa lista figura también la expresión Sub
Main. Si ponemos como formulario inicial uno de los formularios, la aplicación comenzará por ese
formulario. Si en uno de los Módulos existentes en el proyecto, ponemos un procedimiento llamado
Main, podemos comenzar la ejecución de la aplicación justamente por ese procedimiento. En ese
procedimiento pondremos el código necesario para que, posteriormente, se muestre uno de los
formularios. Esto es muy practico cuando queremos hacer una función previa a mostrar cualquier
formulario (abrir una base de datos, por ejemplo). Para comenzar la aplicación por Main se elige esa
opción en la lista Formulario Inicial.
¡ Recuerde que Main debe estar en un Módulo !
El cuadro de diálogo anterior sirve además para otras cosas. Entre ellas poner el nombre del proyecto
(nombre que no aparecerá por ninguna parte, solo en los datos internos de la aplicación) y su
descripción.
Existe otro cuadro parecido en Herramientas | Opciones donde puede terminar de completar las
condiciones de trabajo. Observe el cuadro “Cuando Inicie sus programas”. Aquí le permite grabar el
programa antes de ejecutar, cosa que le recomiendo para evitar que, al ejecutarlo, por un código mal
puesto se le cuelgue el PC y tenga que volver a empezar. En este cuadro puede elegir también el
formato de la ventana de trabajo formato del editor, etc.
Fig. 1.7 Opciones del entorno de diseño
En la pestaña Avanzado puede cambiar el entorno de trabajo. Le recomiendo el SDI.
Si tenemos la activada la casilla Declaración de variables requerida nos pondrá automáticamente
Option Explicit en el encabezamiento de todas las secciones de declaraciones de la aplicación. Está
en la pestaña Editor (Esto es algo que le recomiendo de una forma especialmente rigurosa)
Podemos elegir también las ventanas que queremos que estén siempre visibles, y que verifique
automáticamente la sintaxis de una instrucción en el momento de escribirla.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 44
La pestaña de Editor nos permite fundamentalmente 2 cosas :
Ver solamente el código correspondiente al procedimiento que estamos escribiendo ó Ver el código del
Módulo (o Formulario) completo. En este último caso es un poco mas difícil de manejar la ventana de
código, sobre todo si el programador no está muy habituado a ello. Le presenta procedimiento tras
procedimiento, separados por una línea. Para seleccionar una u otra opción hay que seleccionar o
deseleccionar la casilla Ver módulo completo.
Cambiar el color de la letra y del fondo del código, según el tipo que sea (código, comentario, error
devuelto, etc.). Los alumnos mas aventajados y con ganas de marear al profesor, conocen la forma de
poner como invisible una parte del texto del código. Si observa comportamientos raros en el texto
donde escribe el código, revise el cuadro de Colores de Código.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 45
Ejercicios del Capítulo 1
Nota acerca de los ejercicios de cada capítulo.
Estos ejercicios se proponen a efectos académicos solamente, para facilitar al alumno la comprensión
de lo explicado y estimular el autoaprendizaje. No son perfectos y seguramente existirá una forma mejor
de realizarlos. No se ha pretendido crear programas perfectos, sino que muestren al alumno parte de lo
explicado en el capítulo correspondiente.
Se reúnen en el ejercicio Cap11 tres pequeños programas. Es importante que el alumno comprenda
perfectamente como se ha programado cada una de las líneas. Son tan sencillos estos ejemplos que
dan ganas de saltárselos. Evite esa tentación y vaya paso a paso camino de la perfección en la
programación VB (Antesala de la gloria) entendiendo y sacando consecuencias de estos pequeños
ejercicios. Habrá platos mas fuertes en pocos días.
En la parte de conversión de números a cadenas de caracteres puede ver el comportamiento de la
función Str para convertir números a cadenas de caracteres. Puede observar la longitud de la cadena
resultante contiene un carácter mas de los que cabría esperar. En la etiqueta de desglose de caracteres,
puede observar que el primer carácter es el 32 (espacio), carácter que se elimina al hacerle la función
Trim
En la sección de operadores lógicos puede jugar a aplicar uno de los operadores disponibles a una
pareja de número o a un par de datos booleanos. Observe que para invertir los bits de un byte basta con
hacer el Xor con 255
La tercera parte se parece mas a un programa real.
Veamos un ejemplo de como se puede utilizar la función Xor. Explicaremos lo que es el Cifrado Xor (Se
usó profusamente con los mensajes télex, con un sistema llamado cinta aleatoria. No entra en este
curso explicar lo que era un teletipo. Era, al correo electrónico, lo que la máquina de vapor al AVE )
Este sistema de cifrado puede utilizarlo en sus aplicaciones para, por ejemplo, cifrar el Password de
entrada y poder guardarlo cifrado en el disco duro de su PC. De cualquier forma, debo indicarle que este
sistema de cifrado al tiempo que simple, es tremendamente vulnerable, pero si lo acompaña de otras
características, lo convierte en un cifrador intrínsecamente seguro (Vigenere). La explicación mas
detallada de algoritmos cifradores se sale por completo de la intención de este curso.
Supongamos que queremos cifrar la palabra Secreto que es el Password de entrada para una
aplicación. Deberemos usar otra palabra que cifrará a la anterior, que llamaremos Clave. La clave debe
tener, al menos, tantos caracteres como la palabra a cifrar. Imaginemos que clave es ABCDEFGHIJK
Para cifrar usamos la función Xor de cada una de las letras de Secreto con las correspondientes letras
de la clave. (La primera letra de Secreto con la primera letra de la clave, la segunda con la segunda, etc.)
Pero debemos efectuar la función Xor sobre un número, no sobre una letra. Por lo tanto convertiremos la
letra en un número usando la función Asc Asc (A) = 65, ya que 65 es el número Ascii que corresponde
a la A
Para realizar el Xor del carácter introducido en la variable a, con el carácter introducido en la variable b
haremos:
Chr(Asc(a) Xor Asc(b))
De esta forma, si a = “S” y b = “A” estaremos haciendo
Resultado = 83 Xor 65
En este caso, Resultado = 18. Vamos a ver por qué
Si representamos en binario el número 83
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
83 = 0 1 0 1 0 0 1 1
Página 46
El número 65 es
Haciendo Xor bit a bit
65 = 0 1 0 0 0 0 0 1
Resultado = 0 0 0 1 0 0 1 0 = 18
Luego el resultado de realizar el Xor entre S y A es el carácter 18, que no tiene representación como una
letra.
Si ahora hacemos el Xor entre el resultado y la clave (18 con 65)
65 = 0 1 0 0 0 0 0 1
18 = 0 0 0 1 0 0 1 0
Resultado 2= 0 1 0 1 0 0 1 1 = 83 es decir la letra S
Vemos que descifra usando la misma función que para cifrar .
Si A Xor B = C

A = B Xor C
B = A Xor C
No vamos a explicar profundamente el ejercicio. El alumno debe intentar comprender códigos sencillos
como este. Verá en su trabajo profesional que es difícil meterse en la forma de programar de otra
persona. El desentrañar el código de estos ejercicios puede ser una buena práctica para ello.
El ejercicio Cap12 es un entrenamiento con fechas y formatos. Se sugiere al alumno que introduzca
nuevos formatos, utilice DateDiff, etc. También tiene una parte dedicada a la conversión de números.
Son ampliables por parte del alumno.
Visual Basic - Guía del Estudiante Cap. 2
OBJETOS VISUAL BASIC PROPIEDADES, PROCEDIMIENTOS Y METODOS
Vamos a ver en este capítulo como podemos realizar una aplicación en Visual Basic. Comencemos por
abajo.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 47
Una aplicación VB es una aplicación que, generalmente, tiene una interface gráfica. Es decir, es una
aplicación de las típicas de Windows. Y esa interface gráfica está formada por un formulario y dentro de
él, controles. Tanto al formulario como a los controles les denominamos genéricamente Objetos. Hay
objetos VB que no los podemos ver en la interface gráfica. No podemos verlos porque pese a que son
objetos VB, no tienen ninguna representación en la ventana. Son por ejemplo, los objetos de acceso a
datos que veremos profusamente más adelante.
Todos los objetos de Visual Basic tienen Propiedades. (Por ejemplo, el nombre de ese objeto es una de
sus propiedades). Los objetos que tienen parte gráfica tienen además Eventos. Y muchos de ellos
tienen también Métodos
Propiedades, Eventos, Procedimientos y Métodos
Típica pregunta de examen de VB elemental. Veamos que es cada una de estas cosas.
Las propiedades son aquellas características de un objeto que lo define "físicamente", bien por su forma
o color, por su contenido, por la forma en la que va a trabajar… Las propiedades pueden modificarse
cuando estamos diseñando la interface gráfica, mediante lo que llamamos caja de propiedades, o
durante la ejecución del programa. En este caso hay que hacerlo con código escrito en el propio
programa. Veamos ya dos definiciones que se repetirán profusamente a lo largo del curso
-
Tiempo de diseño. Es cuando realizamos una operación durante el diseño. Por ejemplo, podemos
cambiar el color de un control durante el diseño de la aplicación, accediendo a su propiedad
BackColor en la caja de propiedades.
Tiempo de ejecución. Es cuando esa operación se realiza durante la ejecución del programa. Si
tenemos una línea de código como esta
MiControl.BackColor =RGB(255,0,0)
al ejecutarse esa línea, se cambiará el color del control de nombre MiControl. Hemos cambiado la
propiedad BackColor de ese control en tiempo de ejecución.
Las propiedades pueden ser de lectura y escritura, (se puede cambiar y se puede leer el valor de la
propiedad), sólo de lectura (solamente se puede leer el valor de la propiedad) ó solo de escritura (hay
muy pocas de este tipo). Puede que una propiedad, que es de lectura y escritura en tiempo de diseño,
sea sólo de lectura en tiempo de ejecución (esto es lo que le pasa por ejemplo, a la propiedad Name Nombre)
Un evento es todo aquello que le puede ocurrir a un objeto con parte gráfica (Control o Formulario) Por
ejemplo, es un evento el hecho de hacer click sobre ese control, el hecho de pasar el ratón por encima
de él, el hecho de que un contro l cambie de tamaño…. Los controles tienen muchos eventos, unos de
ellos comunes a casi todos los controles (Evento click, por ejemplo) y otros exclusivos de un
determinado control (El evento Timer solamente lo tiene el control Timer) Puede ver los eventos de un
control haciendo doble click sobre ese control en tiempo de diseño. Le aparecerá la ventana de código.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 48
Fig. 2.1 Ventana de código
La ventana de código es el lugar donde deberá escribir el código de su aplicación. Puede ver que existen
en ella dos listas desplegables, una a la izquierda (sin desplegar) donde se ve el nombre del control del
cual estamos visualizando el código (en este caso Command1) y otra a la derecha, donde se despliegan
todos los eventos que tiene ese control. Haciendo click en la línea de uno de esos eventos, aparecerá la
ventana de código dedicada a ese evento.
Nota. Fíjese en la parte inferior izquierda de la ventana de código. Hay dos botones, uno que permite
visualizar el código correspondiente a un solo evento, (el de más a la izquierda) y otro que permiten ver
en la misma ventana el código de todos los eventos. Cada programador tiene su costumbre para ver uno
o todos. La práctica le dirá lo que es más práctico para Vd.
Un Procedimiento es el código que introducimos dentro de un evento. No pretendo hacer escuela con
definiciones, puesto que el concepto de evento y procedimiento se confunde con mucha frecuencia, y no
pasa nada por ello. El código introducido en la ventana de código del evento click será el procedimiento
click, el que se introduzca en el evento MouseUp será el procedimiento MouseUp. No se sorprenda si a
lo largo de este libro nos referimos a evento o a procedimiento de forma equivocada. En el lenguaje
coloquial es muy habitual ese error y como decíamos, no pasa nada por ello.
Estos procedimientos forman parte del programa. Podría hacerse una aplicación que no tuviese mas
código que el introducido en los procedimientos, y muchas veces esa es la realidad.
Un procedimiento puede pasar parámetros. Se dice que pasa parámetros cuando el sistema aporta
datos automáticamente al procedimiento. Por ejemplo, el procedimiento MouseUp, que se ejecuta
cuando levantamos el botón del ratón (también existe el evento MouseDown), pasa los siguientes
parámetros: Número del botón que se ha pulsado, (1=Izdo, 2=Dcho, 3=Central), si está pulsada la tecla
mayúsculas (Shift, 1 si está pulsada, 0 si no está pulsada) y los valores X e Y de la posición del cursor
del ratón. Podemos ver los parámetros que pasa en la propia definición del procedimiento, que nos da
Visual Basic
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 49
Observe que los parámetros están entre paréntesis, y que queda definido el tipo de variable que es cada
uno de ellos. Podemos usar ese valor dentro del código del procedimiento como un dato más.
Un Método es una operación que la realiza Visual Basic sin necesidad de escribir código para realizarla.
Por ejemplo, si queremos dibujar una línea en un formulario o en la impresora utilizaremos el método
Line. Si queremos dibujar una circunferencia usaremos el método Circle. Si queremos escribir texto,
utilizaremos el método Print. No necesitamos decirle como lo tiene que haver, puesto que eso ya lo sabe
hacer VB sin necesidad de que se lo expliquemos. A los métodos les tenemos que pasar datos. A eso le
llamamos también pasarle parámetros. Los métodos solo permiten introducir los parámetros que
necesita el método para ejecutarse. (En el caso de una línea, el punto inicial y el final, en el caso del
circulo, el radio y las coordenadas del centro. Pueden pedir parámetros optativos, como el puede ser el
color de la línea o circulo.
Espero que le quede claro cada una de estas definiciones. Tendrá tiempo suficiente a lo largo del curso
para verlas, y dentro de muy poco tiempo le serán muy familiares estos conceptos.
EL FORMULARIO
El primer objeto Visual Basic con que nos encontramos es el FORMULARIO. De hecho, cada vez que
iniciamos Visual Basic (VB) nos presenta en pantalla un nuevo formulario, que tiene por defecto el
nombre de Form1
El Formulario es un objeto, que sirve de soporte de otros objetos. El nombre de FORMULARIO lo
toma precisamente porque, al igual que un formulario de papel contiene textos escritos, lugares donde
podemos escribir, figuras, cajas donde podemos elegir una u otra opción, etc., en este cuadro gráfico
que llamamos formulario, podemos introducir textos escritos, lugares donde podemos escribir, figuras,
cajas donde podemos elegir una u otra opción ....
En realidad un formulario es lo que normalmente conocemos por VENTANA. El nombre de formulario le
viene muy bien cuando ese formulario es una ventana donde vamos a introducir datos alfanuméricos.
Cuando en vez de introducir datos, lo que tenemos es, por ejemplo, una ventana donde se reproducen
exactamente los controles de operación de una máquina, parece en principio que sería mas correcto el
nombre de "ventana". De alguna forma lo hay que llamar, y esa forma es FORMULARIO. Posiblemente
a lo largo de estos apuntes nos referiremos al formulario con el nombre de ventana, o incluso, pantalla.
Procuraremos usar el nombre apropiado: FORMULARIO.
Fig. 2.2 Forma inicial del formulario.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 50
Fig. 2.3 Un formulario que parece un equipo de radio (Programa realizado por el autor)
Ejemplo de un formulario para una aplicación industrial. Este formulario reproduce el panel de control de
un transmisor - receptor de radio. En este caso, parece que el nombre de ventana le viene mejor que el
de formulario. Observe que dentro del formulario existen gran cantidad de objetos. Botones, que hacen
la misma función que el botón real en el equipo de radio, y un par de displays, que muestran un texto, en
este caso las frecuencias de transmisión y recepción.
Como cualquier objeto Visual Basic, un formulario tiene propiedades, procedimientos y métodos.
Vamos a ver las propiedades del formulario, pero solo veremos las que son específicas para un
formulario. El resto las podrá ver al final del capítulo. Aquí haremos referencia a esas propiedades con
un asterisco (*) que significa que esa propiedad no tiene una notación especial para los formularios.
Seguiremos esta norma con todos los controles.
PROPIEDADES.
Name
Nombre
Define al objeto durante la ejecución del programa. Se introduce en tiempo de diseño y no se puede
variar durante la ejecución. Nombre por defecto: Form1 (Form2 y sucesivos) Este nombre por defecto
debe cambiarse, (debería cambiarse por norma en el momento de introducir el formulario), ya que de no
hacerlo corremos el riesgo de borrar el código existente de otro formulario del mismo nombre en el
momento de guardar la aplicación.
Caption
Título
Es el texto que aparecerá en la barra de Título cada vez que aparezca en pantalla este formulario. No
tiene otra función dentro del programa. El programa no accede a este formulario por el título, sino por el
nombre. Puede cambiarse en tiempo de ejecución.
NOTA .- No co nfu nd ir Nom bre (Name) con Títul o (Captio n)
Control Box
LSB
Menú de Control en la parte sup. Izda. Valor por defecto : True
Visual Basic – Guía del Estudiante
Capítulo 1
Página 51
Propiedad Booleana que admite los valores de true (verdadero) o False (Falso). Si esta propiedad es
True, aparecerá en la esquina superior izquierda el icono (el "menos" en W-3.11) para desplegar el menú
de control de este formulario. Si esta propiedad se pone como False, no aparece dicho icono y por tanto
no se puede desplegar dicho menú.
MinButton
MaxButton
Valor por defecto: True
Botones de minimizar y maximizar este formulario. Son igualmente propiedades booleanas, que admiten
el valor True o False. Si están en true, aparecerá la flecha correspondiente. Si están en False, no
aparecerá dicha flecha. Deben configurarse de una u otra forma, dependiendo si se quiere minimizar /
maximizar este formulario durante la ejecución.
Nota . En los formularios MDI child, es necesario poner a true las propiedades ControlBox , MinButton
y MaxButton para poder maximizar el formulario hijo. De no ponerlas a true, sí se pretende maximizar el
formulario hijo, (Propiedad WindowState=2) el formulario no aparece.
BorderStyle
Tipo de borde
Define el tipo de borde que tendrá el formulario durante la ejecución. No se puede cambiar en tiempo de
ejecución. Admite los siguientes valores:
0 - None
El formulario no tiene borde alrededor
1 - Fixed Single
El formulario tendrá un borde fino, y no podrá cambiarse su tamaño durante el
tiempo de ejecución. Con este valor, el formulario puede tener un menú de
control, barra de título y botones de maximizar y minimizar. Solo podrá
cambiarse de tamaño utilizando estos botones.
2-Sizable
El formulario tendrá borde grueso, y se podrá cambiar su tamaño en tiempo de
ejecución mediante los botones de maximizar y minimizar, y mediante el arrastre
de uno de los bordes con el ratón.
3 - Fixed Dialog
El formulario tendrá borde grueso, y no se podrá redimensionar durante la
ejecución. No puede tener los botones de maximizar ni minimizar.
4 - Fixed ToolWindow
En las versiones de 16 bits de Windows y Windows NT 3.51 y anteriores se
comporta como Fixed Single. No puede cambiar de tamaño. En Windows 95
muestra el botón Cerrar, y el texto de la barra de titulo aparece con un tamaño
de fuente reducido. El formulario no aparece en la barra de tareas de W95.
5 - Sizable ToolWindow
En las versiones de 16 bits se comporta como Sizable. En W95 muestra el
botón Cerrar y el texto de la barra de titulo aparece con un tamaño de fuente
reducido. El formulario no aparece en la barra de tareas de W95.
Valor por defecto: 2 . Sizable
Nota: Al cambiar a determinados valores, las propiedades MaxButton y
MinButton se ponen a False. Pueden cambiarse a True posteriormente.
Appearance
Apariencia
Valor por defecto: 3D
Admite los valores 0 (=Flat, plano) y 1 (=3D) Si tiene el valor 1 (3D), el formulario aparecerá con cierto
efecto tridimensional, y los controles que le introduzcamos a este formulario aparecerán como
esculpidos dentro de él. Con valor 0 (Flat) en esta propiedad, el formulario aparecerá durante la
ejecución como una superficie plana. El color de fondo se ve afectado al cambiar esta propiedad. Si se
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 52
cambia a 3D, el fondo (Backcolor) toma el color definido en Windows en el Panel de Control. Si se
cambia a Flat, toma el color blanco
Autoredraw
Valor por defecto: False
Propiedad Booleana. Esta propiedad, estando en True, permite actualizar el contenido del formulario y
de sus controles incluso cuando no están visibles. Imaginemos que en este formulario existe un texto,
que se haya cambiado por programa mientras este formulario no estaba visible. Si esta propiedad
Autoredraw está en False, al hacer visible este formulario, aparecerá sin reflejar ese cambio. Si esta
propiedad está en True, aparecerá actualizado.
Backcolor
Color del fondo
Establece el color del fondo del formulario. Puede cambiarse en tiempo de ejecución.
Valor por defecto: El establecido en el Panel de Control de Windows.
ClipControls
Valor por defecto: False
Propiedad Booleana. Establece si un evento Paint vuelve a dibujar el objeto entero (True) o si solamente
dibujan las partes que han sufrido cambios (False)
DrawMode
Establece un valor que determina el aspecto de la salida de un método gráfico o el aspecto de un control
Shape o Line. Verá mas adelante los efectos de esta propiedad.
DrawStile
(*)
Valor por defecto : 0
DrawWidth
(*)
Valor por defecto: 1
Enabled
(*)
ForeColor
Valor por defecto: Negro
Establece el color del primer plano del formulario. Es el color que tendrán las letras si escribimos en él, o
los dibujos, si lo que hacemos es dibujar. En tiempo de diseño, determina el color de la rejilla,.
FillStyle
Tipo de relleno (*)
FillColor
Color del relleno
Font
Tipo de letra
(*)
Valor por defecto: El determinado en la personalización.
Especifica el tipo y tamaño de la letra que se usará en el formulario al utilizar el método Print. Al
seleccionar esta propiedad en la ventana de propiedades, aparece un cuadro de dialogo donde se eligen
ambos parámetros.
Cuando introduzca nuevos controles en el Formulario, la propiedad Font de estos controles tomará el
valor que tenga esta propiedad en el Formulario. Puede servirle este pequeño truco para utilizar en
todos los controles una determinada fuente sin tener que teclearla para cada control.
FontTranparent
Texto Transparente
Valor por defecto: True
Establece si el texto o gráfico de fondo del formulario se muestra (True) o no se muestra entre los
caracteres de texto escritos en el propio formulario.
FontSize
LSB
Tamaño de letra
Visual Basic – Guía del Estudiante
Capítulo 1
(*)
Página 53
FontBold, FontItalic, FontStrikethru, FontUnderline
Height
Altura
HelpContextID
Identificador de contexto de la Ayuda
Icon
Icono
(*)
(*)
(*)
Esta propiedad define el icono que va a representar a este formulario cuando esté minimizado. Si el
formulario es el formulario padre o formulario de inicio de una aplicación, este icono es el que toma el
Asistente de Instalación para colocarlo como icono de apertura del programa en el grupo de programas
Windows correspondiente. Como valor de esta propiedad se le puede asignar directamente el icono o el
nombre de un archivo (con su path correspondiente) que lo contiene, haciéndolo directamente sobre la
caja de propiedades.
Valor por defecto: el icono que se le haya programado en la personalización.
KeyPreview
Valor por defecto: False
Propiedad Booleana. Cuando un formulario tiene dentro de sí varios controles, uno de ellos es el que
está activo. En estas condiciones, si se pulsa una tecla, esa pulsación la recibe en primer lugar el
control que esté activo, y si éste no la procesa, pasa esa pulsación al formulario. Para hacer que esa
pulsación pase previamente por formulario, debe ponerse esta propiedad en True. Esta propiedad la
usará frecuentemente cuando quiera realizar alguna función pulsando una letra. Pone KeyPreview a
True, y puede conocer que tecla se ha pulsado en el procedimiento KeyPress del formulario. Si la tiene a
False, ese procedimiento no se ejecuta ya que la pulsación “no pasa” por el formulario.
Left
Posición del Borde Izquierdo
Indica la posición del borde izquierdo del formulario respecto a la parte izquierda de la pantalla. (Lo verá
mas adelante, la pantalla será para VB el objeto Screen). Normalmente no se introduce como valor
numérico, sino que lo toma automáticamente de la posición que tenga el formulario en el tiempo de
diseño. Puede cambiarse en tiempo de ejecución, para mover el formulario.
LinkMode
Valor por defecto: 0
Permite que una aplicación destino inicie una conversación DDE con el formulario (origen de datos).
Puede tomar los siguiente valores:
0 - No hay interacción DDE
1 - Source. Indica que este Formulario es origen de una comunicación DDE. El dato que se va a
traspasar en esa comunicación DDE estará en un TextBox, en un Label o en un PictureBox de
este Formulario.
LinkTopic
Establece el tema al que este formulario va a responder a una conversación DDE, cuando funciona
como origen. Es por este tema por el que se debe llamar a este formulario cuando actúa de origen en
una conversación DDE
MDIChild
Valor por defecto: False
Establece que este formulario es un formulario Hijo dentro de un formulario MDI. No se puede cambiar
en tiempo de ejecución. Es una propiedad Booleana
True = es formulario hijo
MouseIcon
(*)
MousePointer
(*)
LSB
Visual Basic – Guía del Estudiante
False =No lo es
Valor por defecto: flecha
Capítulo 1
Página 54
Picture
Gráfico
Mediante esta propiedad podemos poner un gráfico como fondo del formulario. El gráfico puede ser un
bit-map o un fichero .ICO
ScaleHeight, ScaleWidth, ScaleMode,
Indican la unidad de medida de dimensión de altura y anchura del Formulario. ScaleMode indica en qué
unidades de medida se van a medir esas dimensiones. Acepta Twips (1), Point(2), Pixel (3), Character
(4), Pulgadas (Inch) (5), Milímetros (6), Centímetros (7). Si colocamos la propiedad ScaleMode en
cualquiera de estos valores, las propiedades ScaleHeight y ScaleWidth nos vendrán dadas
automáticamente dependiendo del ancho del Formulario, y no se extrañe si encuentra para estas
propiedades valores tan peregrinos como 4815 y 7423. Al haber elegido la unidad de medida, los
valores de ancho (ScaleWidth) y alto (ScaleHeight) serán los que tengan que ser, medidos en la unidad
que hemos elegido. Podemos elegir una cifra para el ancho y el alto del Formulario de forma que
podamos controlar mejor las distintas posiciones que van a ocupar en él los controles, los textos o los
dibujos. Podemos poner, por ejemplo, que el Formulario mida 400 de ancho (ScaleWidth = 400) y 300
de alto (ScaleHeight = 300) forzándole estas propiedades, bien en tiempo de diseño en la caja de
propiedades, o en tiempo de ejecución mediante código. Entonces sabemos que el formulario,
independientemente de las dimensiones físicas que tenga sobre la pantalla, medirá 400 de ancho y 300
de alto, y si en estas condiciones queremos colocar un control o un dibujo justo en el medio del
Formulario, sabemos que tenemos que colocarle en las coordenadas 200, 150. ¿Que unidad de medida
estaremos utilizando entonces en el Formulario ? Unas definidas por el usuario (distintas para el ancho
y el alto) que serán las necesarias para que el Formulario mida de ancho lo que le hayamos puesto en la
propiedad ScaleWidth y de alto lo que le hayamos puesto en la propiedad ScaleHeight. Observe que la
propiedad ScaleMode se ha cambiado automáticamente a User (0) al introducir las dimensiones de
ancho y alto que nosotros queremos.
Estas unidades de medida afectarán a los controles que metamos en este Formulario. Se medirán en su
ancho y alto con la unidad de medida definida para el ancho y alto del Formulario. Lógicamente también
afectará a las propiedades Left y Top de los controles, pero estas propiedades se verán afectadas
además por las propiedades ScaleLeft y ScaleTop del Formulario que se verán a continuación.
ScaleLeft, ScaleTop
Estas propiedades, medidas en la unidad de medida elegida para el ancho y alto mediante las
propiedades ScaleMode, ScaleWidth y ScaleHeight anteriores, expresan las coordenadas iniciales de
la parte izquierda y de la parte superior respectivamente del Formulario. Estas propiedades no afectan a
la posición del Formulario en la pantalla (Si está maximizado seguirá ocupando toda la pantalla, si está
en “Normal” ocupará el mismo sitio que se dio en tiempo de diseño). Supongamos que se le asigna a un
Formulario, las propiedades ScaleWidth = 400, y ScaleHeight = 300. Si colocamos un control
justamente en el centro del Formulario tendrá sus propiedades Top =150 y Left=200. Si ponemos ahora
las propiedades del Formulario ScaleLeft a 30 y ScaleTop a 10, ese control, para seguir en el centro del
Formulario deberá tener sus propiedades Top a 160 (150 + 10) y Left a 230 (200 + 30).
Recuerde que las medidas de un formulario crecen, desde la esquina superior izquierda, según
avanzamos hacia abajo y hacia la derecha.
Como aclaración de las relaciones entre distintas unidades de medida, puede ver en la siguiente table la
correspondencia entre cada una de ellas y la unidad imaginaria Twip.
1 Point=20 Twips ; 1Pixel=15 Twips : 1 Charecter=240 Twips ; 1 Inch (pulgada) =1440 Twips
1mm=56,52 Twips 1 cm=566 Twips
Tag
Top
(*)
Posición del borde superior
Esta propiedad establece la posición del borde superior del formulario respecto a la parte superior de la
pantalla (Objeto Screen). Normalmente no se introduce como valor numérico sino que lo toma
automáticamente de la posición que tenga el Formulario durante el tiempo de diseño Este valor puede
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 55
cambiarse durante la ejecución para, conjuntamente con Left, variar la posición del Formulario. Los
valores de Top y Left definen la esquina superior izquierda del Formulario.
Visible
Width
(*)
Ancho
Valor por defecto: True
(*)
WindowState
Establece el estado en el que aparecerá el formulario cuando se activa y presenta en pantalla. Admite
tres opciones:
0 - Normal El formulario recupera la posición y tamaño que tenía en el tiempo de diseño.
1 - Minimizado El formulario aparece minimizado, representado por su icono.
2 - Maximizado El formulario aparece maximizado, ocupando toda la pantalla.
EVENTOS DEL FORMULARIO
Se explican a continuación los eventos de un formulario. Recuerde que un evento es lo que le puede
ocurrir a un formulario o control (p.e. Evento Click) y un procedimiento es el código escrito en ese
evento, que se ejecutará cuando ocurra el evento.
Activación
Evento Activate
Este evento se ejecuta al convertirse el formulario en formulario activo. Esto sucede múltiples veces
cuando tenemos en el programa mas de un formulario. Sólo uno de ellos puede ser el formulario activo.
Este procedimiento no pas a parám etro s . No debe emplearse para los parámetros iniciales del
formulario. Úsese para este fin el evento Load o el Initialize.
Click
Evento Click
Este evento se ejecuta cuando hacemos Click (con cualquier botón del ratón) en una parte del formulario
que no esté ocupada por un control. Para que se ejecute el evento Click es necesario que no se ejecute
el procedimiento MouseDown. (Que no tenga código escrito en el evento MouseDown). Existe una
diferencia entre el evento click del formulario y el de cualquier control : en el formulario se ejecuta con
cualquiera de los botones del ratón, y en los controles, solamente con el botón izquierdo. Este evento no
pasa parámetros.
Doble click
Evento DblClick
Este evento se ejecuta cuando hacemos doble click con cualquier botón del ratón sobre una parte del
formulario que no esté ocupada por un control. Este evento no se ejecuta si tenemos escrito código en el
procedimiento Click. No pasa parámetros.
Desactivación
Evento Deactivate
Se produce cuando el formulario deja de ser el formulario activo. Vea Activate. No pasa parámetros.
Evento DragDrop
Evento DragOver
Acción de Soltar durante el Drag & Drop
Pasar el ratón por encima en una operación de Drag & Drop
Evento GotFocus
El formulario obtiene el foco
(*)
(*)
Este evento ocurre cuando el formulario toma el foco. Cosa un poco difícil, ya que para que el formulario
tome el foco debe ocurrir, o que no tenga ningún control capaz de tomar el foco, o que todos los
controles existentes en el formulario y que puedan tomar el foco, estén desactivados. No se suele usar
este procedimiento.
Evento Initialize
Inicialización del formulario
Se produce al cargar por primera vez el formulario. Esto significa que si en una aplicación cargamos ese
formulario una vez (la primera) se realiza este evento, pero si descargamos el formulario (con Unload
Formxx) y luego lo volvemos a cargar (con Formxx.Show), esta segunda vez (y sucesivas) no se
produce este evento
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 56
Evento KeyDown
Evento KeyPress
Evento KeyUp
Pulsar una tecla (Instante en que se ha pulsado)
Pulsar una tecla
Soltar una tecla (Instante en que se levanta)
Estos tres eventos solamente se producirán en el formulario cuando la propiedad KeyPreview está a
True. (Vea propiedad KeyPreview)
Estos tres procedimientos son excluyentes y tienen la jerarquía con el orden siguiente: KeyDown,
KeyPress y KeyUp. Si el procedimiento KeyDown tiene código que pueda realizar una operación, no se
ejecutará el procedimiento KeyPress ni el KeyUp. Si es el procedimiento KeyPress quien tiene el código
que ejecuta una operación, no se ejecutará el KeyUp. Para que realice esta exclusión es necesario que
el código pueda realizar alguna operación.
Pasa los siguientes parámetros:
K e y D o w n : KeyCode As Integer, Shift As Integer
KeyPress : KeyAscii As Integer
: KeyCode As Integer, Shift As Integer
KeyUp
KeyCode es el código ASCII de la tecla pulsada. KeyAscii es el código ASCII de la tecla pulsada.
La diferencia entre KeyCode y KeyAscii es que el primero se refiere a las teclas del teclado (Todas las
letras y números, teclado numérico, Alt, F1 a F12, etc.) mientras que KeyAscii solamente tiene valor
cuando se pulsa una tecla de letra o número. Puede observar que el KeyCode de un número tecleado en
el teclado numérico es distinto del KeyCode de ese mismo número pulsado en el teclado alfanumérico.
No se confunda con el hecho de que el KeyCode de algunas teclas coincida con el KeyAscii. No es lo
mismo.
Shift indica si está pulsada la tecla “Mayúsculas”. Contiene un 1 si está pulsada, 0 si no lo está.
Evento LinkError
Evento LinkExecute
Evento LinkOpen
Error de enlace
Ejecución de un enlace de datos
Romper el enlace
Estos tres procedimientos ocurren cuando el formulario forma parte de un enlace DDE. Vea el capítulo
del DDE para mas detalles.
Evento Load
Cargar el formulario
Este evento es se ejecuta en el momento de la carga del formulario. Es el que presenta en la ventana de
código por defecto, es decir, uno de los mas usados en el formulario. Y es el mas usado porque es el
mas apropiado para introducirle a ese formulario los valores y parámetros iniciales, abrir bases de datos,
etc.
Se ejecuta después del evento Initialize del formulario, pero este evento Load, al contrario que el
Initialize, se ejecuta cada vez que cargamos el formulario. Para introducir código de inicialización debe
utilizar este evento Load. Este evento no pasa parámetros.
Evento LostFocus
Perder el foco
Ocurre cuando el formulario pierde el foco. Y un formulario solo puede perder el foco cuando lo tenía.
Cosa que no es fácil que ocurra, tal como se explicó en el Evento GotFocus.
Pulsar un a tecla del ratón
Evento MouseDown
Ocurre cuando se pulsa cualquier botón del ratón, estando el cursor encima de un punto del formulario
libre de controles. Pasa como parámetros Button (Botón pulsado, 1 = Izquierdo, 2 = Derecho, 3 =
Central), Shift (Tecla de Mayúsculas) y la posición del puntero del ratón sobre el formulario (X e Y). Este
evento puede usarse para muchas cosas. Una de ellas, muy típica, iniciar una operación de Drag & Drop
manual, usando la particularidad de que como pasa la tecla Shift como parámetro, puede obligarse a
pulsar esa tecla para iniciar el D & D, evitando así cualquier activación accidental.
Evento MouseMove
Mover el ratón (Detecta la posición del ratón sobre el
formulario)
Se produce cada vez que se mueve el ratón sobre el formulario. Tenga cuidado al usar este evento, ya
que cualquier movimiento del ratón lo va a desencadenar. Por eso, siempre se usa con una condición
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 57
(que esté pulsada la tecla de mayúsculas, que esté pulsado uno de los botones del ratón, etc.). Los
parámetros que pasa son Button As Integer, Shift As Integer, X e Y As Single.
Soltar una tecla del ratón
Evento MouseUp
Este evento sucede cuando se levanta la tecla pulsada del ratón. Pasa como parámetros Button (Botón
pulsado, 1 = Izdo, 2 = Dcho, 3= Central) Shift (Mayúsculas), X e Y (Single) como posición del puntero
del ratón
Este evento suele usarse para mostrar PopupMenús, deshacer una operación iniciada con MouseDown,
etc.
Evento Paint
Redib ujar t ras u n c amb io de tam añ
o
Se produce al cambiar el tamaño del formulario, tras el evento Resize, excepto cuando se minimiza.
Puede aprovecharse para redibujar el contenido del formulario (de ahí su nombre) tras un cambio de
tamaño. No pasa parámetros
Evento QueryUnload
Confirmación de descarga
Este procedimiento se ejecuta cuando el formulario recibe la instrucción de descargarse. Todavía
estamos a tiempo de evitar que se descargue. Por lo tanto es aquí donde suele colocarse una caja de
mensaje donde se obliga al usuario a ratificar o revocar la orden de descarga del formulario. En caso de
que en realidad no queramos descargarlo, basta con poner Cancel = True (o Cancel = 1) y no se
producirá la descarga. Pasa como parámetros Cancel As Integer, UnloadMode As Integer.
Cancel es un parámetro que debemos introducir para abortar la descarga del formulario. Si se pone a un
valor distinto de 0, se detiene la descarga.
UnloadMode es un valor o constante que nos da el sistema, dependiendo de la causa que ha provocado
la descarga del formulario.
Constante
vbFormControlMenu
vbFormCode
vbAppWindows 2
vbAppTaskManager
vbFormMDIForm
Valor
0
El usuario eligió el comando Cerrar del menú Control del
formulario o hizo click en el X del mismo.
1
Se invocó la instrucción Unload desde el código.
La sesión actual del entorno operativo Microsoft Windows
está finalizando.
3
El Administrador de tareas de Microsoft Windows está cerrando la
aplicación.
4
Un formulario MDI hijo se está cerrando porque el
formulario MDI padre también se está cerrando.
Este procedimiento no se ejecuta cuando sale de la aplicación mediante la instrucción End. Solamente
se ejecuta cuando con la instrucción Unload, o con el comando Cerrar del menú Control del formulario, o
haciendo click en el X del mismo. El evento QueryUnload se utiliza con frecuencia para guardar la
configuración actual de la aplicación.
Evento Resize
Cambio de tamaño
Se ejecuta cuando cambia el tamaño del Formulario, bien porque le cambia con las flechas del ratón
arrastrando uno de sus bordes, bien porque lo maximizamos, ponemos a tamaño intermedio o
minimizamos. Puede usar este evento para redistribuir o cambiar el tamaño de los controles. No pasa
parámetros.
Evento Terminate
Este evento se produce al descargar el formulario, después de QueryUnload y Unload. Aquí ya no
podemos abortar la descarga. Solamente podremos, por ejemplo, guardar la configuración usada por la
aplicación, para que vuelva a arrancar con la última configuración usada.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 58
Este evento no se produce si sale de la aplicación con la instrucción End. Solamente si lo hace mediante
Unload (Unload Me, p.e.) o con el comando Cerrar o el X del formulario. Me permito recomendarle que
No termine sus aplicaciones mediante End. No podrá usar los eventos QueryUnload, Unload ni
Terminate.
Evento Unload
Descargar el formulario
Este evento se produce en el momento en el que se descarga el formulario. Pasa como parámetro
Cancel, al igual que lo hace QueryUnload. Es la última oportunidad de cancelar la descarga del
formulario, haciendo Cancel = True o Cancel = cualquier valor distinto de 0.
Este procedimiento no se ejecuta cuando sale de la aplicación mediante la instrucción End. Solamente
se ejecuta cuando con la instrucción Unload, o con el comando Cerrar del menú Control del formulario, o
haciendo click en el X del mismo.
Eventos del OLE
Existen varios eventos relacionados con el OLE de Windows. Se estudiarán cuando se estudie el OLE.
De momento se enumeran con los parámetros que pasan.
Evento OLECompleteDrag (Effect As Long)
Evento OLEDragDrop (Data As DataObject, Effect As Long, Button As Integer, Shift As _
Integer, X As Single, Y As Single)
Evento OLEDragOver (Data As DataObject, Effect As Long, Button As Integer, Shift As _
Integer, X As Single, Y As Single, State As Integer)
Evento OLEGiveFeedback (Effect As Long, DefaultCursors As Boolean)
Evento OLESetData (Data As DataObject, DataFormat As Integer)
Evento OLEStartDrag (Data As DataObject, AllowedEffects As Long)
LOS CONTROLES MAS ELEMENTALES DE VISUAL BASIC
Una vez introducido un Formulario, se pueden colocar los objetos (controles) que forman parte de la
aplicación. Estos controles se irán viendo en próximos capítulos.
Los controles, lo mismo que el Formulario, tienen Propiedades, Procedimientos y Métodos.
Para colocar un control en un Formulario, basta con “tomarlo” de la caja de herramientas existente en la
parte izquierda de la pantalla de VB y llevarlo al Formulario. Si no existiese el control deseado en la caja
de herramientas, deberemos ir a “cogerlo” a Proyecto | Compo nentes de la barra de menú de VB. Se
elige el nuevo control, marcando la caja de opción a la izquierda de su nombre, y haciendo click en
ACEPTAR. Este control ya pasa a la caja de herramientas.
No se deben introducir mas controles de los necesarios. Sobre todo, cuando vaya a compilar el proyecto.
Si tiene metido en la caja de herramientas un control que no necesita, lo introducirá en los discos de
distribución igual que si lo necesitara.
COMMAND BUTTON BOTON DE COMANDO
El Command Button es un objeto que sirve para introducir datos a través de la pantalla. El Botón de
Comando tiene la siguiente forma:
El botón de comando puede usarse para la entrada de datos con el ratón, o para validar cualquier
operación. El tamaño puede cambiarse a voluntad, pero la forma siempre es rectangular. En la figura
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 59
anterior vemos dos botones de comando, uno de ellos (el Command2) marcado con unos puntos en su
contorno. Estos puntos nos permiten variar su tamaño en tiempo de diseño. También puede cambiarse
su tamaño y posición en tiempo de ejecución.
(Las propiedades marcadas con (*) no varían de la descripción general, hecha al final del capítulo)
PROPIEDADES
Name
Nombre (*)
Caption
Título (*)
Es el texto que aparece en el botón. Puede cambiarse en tiempo de ejecución. No tiene otra función
dentro del programa.
Appearance
Apariencia
(*)
Color de fondo (*)
Backcolor
Esta propiedad permite cambiar el color del botón cuando la propiedad Style está puesta a Graphycal. Si
la propiedad Style esta puesta a Standars, esta propiedad solamente controla el color de un pequeño
cuadrado que aparece rodeando el título. Puede cambiarse en tiempo de ejecución.
Cancel
Establece un valor que indica si un botón de comando es el botón Cancelar de un formulario. Es una
propiedad booleana, y admite los valores True o False. Puede utilizar la propiedad Cancel para dar al
usuario la opción de cancelar los cambios que no se han hecho efectivos y devolver el formulario a su
estado anterior. En un formulario sólo puede haber un botón de comando con la propiedad Cancel =
True.
Causes Validation
Esta propiedad habilita o deshabilita la ejecución del evento Validate del control que tenía el foco antes
de cambiar el foco a este control. El evento Validate de un control se ejecuta inmediatamente antes de
que pierda el foco. (Se dice que un control tiene el foco cuando es ese control el que está activado) . Al
hacer click sobre el botón de comando, siempre habrá algún control que pierda el foco para que lo tome
el botón de comando. Si el botón de comando tiene la propiedad Causes Validation a True, se ejecutará
el evento validate de ese control que acaba de perder el foco. Si está a false, no se ejecutará. Observe
que esta propiedad afecta a un control diferente del que ostenta la propiedad.
Default
Establece un valor que determina el control CommandButton que es el botón de comando
predeterminado de un formulario. Sólo un botón de comando de un formulario puede ser el botón de
comando predeterminado. Cuando Default se define a True para un botón de comando, se define
automáticamente a False para el resto de los botones de comando del formulario. Cuando la propiedad
Default del botón de comando está establecida a True y su formulario primario está activo, el usuario
puede elegir el botón de comando (invocando su evento Click) presionando ENTRAR. Cualquier otro
control que tuviera el enfoque no recibe evento de teclado (KeyDown, KeyPress o KeyUp) de la tecla
ENTRAR a menos que el usuario haya movido el enfoque a otro botón de comando del mismo
formulario. En este caso, al presionar ENTRAR se elige el botón de comando que tiene el enfoque en
lugar del botón de comando predeterminado.
Estas propiedades solamente están disponibles cuando se pone
DisabledPicture, DownPicture
la propiedad Style a Graphycal. Permiten poner un icono diferente para el estado de deshabilitación del
botón (Cuando está la propiedad Enabled = False) o cuando el botón está pulsado respectivamente.
Juntamente con la propiedad Picture permite hacer un juego de imágenes sobre el botón que varían de
acuerdo a su estado o posición.
DragIcon
Icono en la operación de arrastre
(*)
DragMode
Modo de iniciar el Drag & Drop
(*)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 60
Enabled
Habilitado
(*)
Font
Fuente
(*)
Height
Altura
(*)
HelpContextID
Número de Contexto para la Ayuda
Index
Indice
Left
Posición de su parte izquierda.
(*)
(*)
(*)
Establece cual es el color de la imagen del botón que actuará como máscara para
MaskColor
producir zonas transparentes. Para ello, la propiedad UseMaskColor debe estar a true. (¡)
MouseIcon
(*)
Icono para el puntero del ratón
MousePointer Puntero ratón
(*)
Solamente está disponible cuando la propiedad Style está puesta a Graphical. Pone un
Picture.
icono sobre el botón.
Define el estilo del botón, aceptando dos valores: Graphycal y Standard. Poniendo
Style
esta propiedad a Graphycal podemos cambiar el color del botón 8con la propiedad Backcolor) e
incluso introducir un fráfico (en la propiedad Picture, DownPicture o DisabledPicture.
UseMaskColor Determina si el color asignado en la propiedad MaskColor se usa como máscara para
crear zonas transparentes. No he sido capaz de sacar partido a esta propiedad.
TabIndex
Nº de orden para tabulador
(*)
TabStop
Sale del control de la tecla TAB
(*)
Tag
Valor auxiliar
(*)
ToolTipText
Etiqueta de información (W95)
(*)
Top
Posición de la parte superior
(*)
Visible
Visible
(*)
WhatsThisHelpID
(Propiedad, Windows 95)
Ancho
Width
(*)
(*)
PROCEDIMIENTOS DEL BOTON DE COMANDO
Click
KeyDown
MouseDown
DragDrop
KeyPress
MouseMove
DragOver
KeyUp
MouseUp
GotFocus
LostFocus
¡ El botón de Com ando no tiene el proc edimiento Db Click !
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 61
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 62
LABEL
ETIQUETA
Una etiqueta es un control que nos permite presentar un texto. La etiqueta debe usarse en aquellos
casos en los que exista una información estática o dinámica que no deba ser cambiada por el operador.
Puede adoptar estas formas: con borde tridimensional, borde plano o sin borde, y el texto justificado a
la izquierda, a la derecha o centrado.
Se ha incluido la trama para poder observar los límites de la etiqueta sin borde.
PROPIEDADES
Alignment
Justificación
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta.
Appearance
Apariencia
Plana o tridimensional. (*)
Autosize
Caption
Si está a True, el tamaño de la etiqueta se ajusta al tamaño del texto de su propiedad
Backcolor
Color de fondo
(*)
BackStyle
Tipo de fondo
Opaco o transparente.
Cuando se selecciona transparente, se ve solamente el texto de la etiqueta, dejando ver como fondo
entre las letras, el color o Picture del formulario. Cuando se selecciona opaco, este texto se vé sobre un
fondo gris.
BorderStyle
Tipo de borde
Sin borde o con borde. En caso de haber elegido en la propiedad Appearance el modo tridimensional, y
eligiendo con borde en esta propiedad, el aspecto adopta una forma como incrustada en el formulario.
Caption
Título
DataSource
DataField
(*)
Establecen el control data asociado y el campo de la base de datos que se presentará en la propiedad
Caption. Estas propiedades permiten presentar los datos de una Base de Datos mediante un
procedimiento muy sencillo, con la ayuda de un control Data (Se verá mas adelante)
DragIcon
LSB
DragMode
Enabled
Visual Basic – Guía del Estudiante
Capítulo 1
Font
ForeColor
Height
Página 63
Index
Left
(*)
LinkItem LinkMode LinkTimeout LinkTopic
Estas propiedades establecen la forma en que debe llevarse a cabo una conexión DDE con otra
aplicación. Se verán con mas detalle al estudiar los enlaces DDE
MouseIcon
Top
MousePointer
(*)
Name
TabIndex
Tag
ToolTipText
UseMneumonic
Es una propiedad Booleana. Devuelve o establece un valor que indica si al incluir el signo (&) en el texto
de la propiedad Caption del control Label se define una tecla de acceso.
Los valores que puede tomar son True o False.
True (Predeterminado) Los caracteres (&) que aparezcan en el texto de la propiedad Caption definen
al carácter siguiente como tecla de acceso. El signo (&) no aparece en el Caption del control Label.
False Los caracteres (&) que aparezcan en el texto de la propiedad Caption aparecen como tales en el
Caption del control Label.
En tiempo de ejecución, al presionar ALT+ la tecla de acceso definida en la propiedad Caption del control
Label, el enfoque se desplaza al control siguiente al control Label en el orden de tabulación.
Visible
WhatsThisHelpID
Width
(*)
WordWrap
Devuelve o establece un valor que indica si un control Label con el valor True en su propiedad AutoSize
se expande vertical u horizontalmente para adaptarse al texto especificado en su propiedad Caption. Es
una propiedad Booleana.
True El control Label se expande o contrae horizontal y verticalmente para adaptarse al texto y al
tamaño de la fuente. Contempla para la expansión horizontal la colocación de los espacios del texto.
False (Predeterminado) El texto no se ajusta a la siguiente línea; el control Label se expande o contrae
horizontalmente para adaptarse a la longitud del texto y verticalmente para adaptarse al tamaño de la
fuente y al número de líneas.
Nota
Si se establece False en AutoSize, el texto siempre se ajustará a la línea siguiente,
independientemente del tamaño del control Label y del valor de la propiedad WordWrap. Esto puede
ocultar parte del texto, ya que el control Label no se expande en ninguna dirección.
PROCEDIMIENTOS DEL LABEL
Click
DragOver
TEXT BOX
Change
LinkClose
DbClick
LinkError
DragDrop
LinkNotify
CAJA DE TEXTO
Las cajas de texto son los controles en los que Visual Basic presenta o introduce textos. Es por tanto un
control bidireccional. Normalmente se usan para introdución de textos, o para la presentación de
aquellos que el operador pueda cambiar. Para cambiar o escribir un texto en una caja de texto, basta
con conseguir que esa caja de texto tenga el foco y teclear el texto en el teclado. Esto se puede lograr,
bien haciendo click con el ratón en esa caja de texto, bien con la tecla TAB, bien por programa.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 64
La caja de texto no se debe usar nunca para presentar textos que el operador de la aplicación no deba
cambiar. Úsese para ello la etiqueta, control no bidireccional, que además tiene la ventaja de ocupar
menos memoria de programa.
Las cajas de texto pueden tener una o varias líneas, según esté la propiedad Multiline. La capacidad
máxima de una caja de textos es de 64 Kbytes.
La forma de una caja de texto es la siguiente, dependiendo de las propiedades BorderStyle y
Appearance:
PROPIEDADES
Alignment
Justificación
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta. Esta propiedad
solamente tiene efecto cuando la propiedad Multiline está a True , ignorándose en caso contrario. Es
decir, permite colocar el texto justificado a la derecha cuando ese texto puede ser de varias líneas. Si la
propiedad Multiline está a False, se justifica siempre a la izquierda.
Esta propiedad no puede cambiarse en tiempo de ejecución, pero sí puede leerse en que condición está.
Appearance
Backcolor
BorderStyle
Tipo de borde
(*)
Sin borde o con borde. En caso de haber elegido en la propiedad Appearance el modo tridimensional, y
eligiendo con borde en esta propiedad, el aspecto adopta una forma como incrustada en el formulario.
DataField
Nombre de un Campo
DataSource
Nombre de un control Data
Establecen el control Data y el campo donde está el texto que se llevará a la propiedad Text. Estas
propiedades permiten presentar de una forma muy sencilla datos de una Base de Datos. Se verán
cuando se estudie el control Data y el motor de bases de datos
DragIcon
DragMode
(*)
Habilitado
Enabled
Propiedad Booleana que habilita o deshabilita la etiqueta Cuando está deshabilitado (Enabled = False),
no tienen efecto los eventos que se produzcan sobre el TextBox. No se puede escribir el él ni pasarle el
foco, pero sí se le puede cambiar el texto mediante el programa. Puede ser una buena alternativa para
impedir que el usuario pueda cambiar un determinado texto. Esta propiedad puede variarse en tiempo de
ejecución.
Font
LSB
ForeColor
Height
Visual Basic – Guía del Estudiante
Capítulo 1
HelpContextID
Index Left
(*)
Página 65
LinkItem LinkMode LinkTimeout LinkTopic
Estas propiedades establecen la forma en que debe llevarse a cabo una conexión DDE con otra
aplicación. Se verán con mas detalle al estudiar los enlaces DDE
Locked
Establece si el texto se puede editar, es decir, cambiar. Cuando se pone esta propiedad a True, el texto
existente en la caja puede resaltarse con el ratón, e incluso copiarlo al portapapeles, pero no puede
variarse tecleando un nuevo texto. Se puede cambiar por programa, cambiando la propiedad Text.
Si está en False, puede cambiarse el texto mediante teclado.
MaxLenght
Indica, si se establece, la longitud máxima del texto. Si no se establece o si se pone valor 0, permite
cualquier longitud de texto.
Puntero del ratón personalizado
MouseIcon
(*)
MousePointer Puntero ratón
Lo típico para esta propiedad es el I-Beam (barra vertical)
Name
Nombre(*)
PasswordChar
En ocasiones, es conveniente que no se pueda leer lo que se escribe en la caja de texto, caso por
ejemplo de la entrada de un password o palabra de paso. Esta propiedad nos permite indicar un carácter
que sustituye a cualquier carácter que tenga la caja de texto. (Típicos el * o ?). El texto que tenga en la
propiedad Text no cambia por el hecho de presentar en pantalla un carácter distinto. Esta propiedad
puede cambiarse en tiempo de ejecución. Para quitar el PasswordChar basta con forzarlo al carácter
nulo :
Text1.PasswordChar = “”
La propiedad PasswordChar se ignora cuando la propiedad Multiline está a True .
ScrollBars
Cuando la propiedad Multiline de la caja de texto está a True, se pueden colocar barras de
desplazamiento del texto hacia arriba y abajo, o hacia los lados. Esto nos permite tener una caja de texto
de tamaño reducido y poder leer en ella un texto mayor que la propia caja. Esta propiedad puede tomar
los siguiente valores :
0 - No salen barras
1 - Barras de desplazamiento horizontal
2 - Barras de desplazamiento vertical
3 - Ambas barras.
TabIndex
Tag
(*)
Texto
Text
La caja de texto no tiene la propiedad Caption. Su equivalente es la propiedad Text que es el texto que
tiene en su interior.
Top
Visible
WhatsThisHelpID
Width
(*)
PROCEDIMIENTOS DE LA CAJA DE TEXTO
Click
KeyDown
FRAME
Change
KeyPress
DblClick
KeyUp
DragDrop
LinkClose
DragOver
GotFocus
RECUADRO
Se obtiene directamente de la caja de herramientas
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 66
Tiene la siguiente forma :
Un control Frame proporciona un agrupamiento identificable para controles. También puede utilizar un
Frame para subdividir un formulario funcionalmente por ejemplo, para separar grupos de controles
OptionButton.
Para agrupar controles, en primer lugar trace el control Frame y, a continuación, meta los controles
dentro de Frame. De este modo podrá mover al mismo tiempo el Frame y los controles que contiene. Si
traza un control fuera del Frame y, a continuación, intenta moverlo dentro de éste, el control se colocará
sobre el Frame, pero no pertenecerá a el. Es decir, si es un OptionButton este se comportará como si
estuviese fuera del Frame, aunque físicamente esté dentro de el.
Cuando un control Frame tiene dentro otros controles, y hacemos invisible al Frame, mediante su
propiedad Visible = False, los controles interiores al Frame quedan también invisibles. Los controles
Frame se utilizan para poner dentro de ellos diversos controles, que solo aparecerán en el programa
cuando se cumpla una determinada condición. Cuando esa condición se cumpla, se pone la propiedad
Visible del Frame a True y se verán todos los controles que tiene dentro. Si no se cumple esa condición,
se pone la propiedad Visible del Frame a False y no se verá ni el Frame, ni los controles que contiene.
PROPIEDADES
Las señaladas con (*) no presentan novedades respecto a las ya comentadas
para los controles precedentes.
Appearance
Backcolor
Caption
(*).
ClipControls
Si esta propiedad está a True, los métodos gráficos en eventos Paint vuelven a dibujar el objeto entero.
Antes del evento Paint se crea una zona de recorte alrededor de los controles no gráficos del formulario.
Si esta propiedad está a False dibujarán solamente las áreas últimamente expuestas. En tiempo de
ejecución, esta propiedad es de sólo lectura.
DragIcon
DragMode
(*)
Enabled
Cuando esta propiedad está a False, tanto los procedimientos asociados al propio control Frame como
todos los controles dentro del Frame estarán inhabilitados. Si esta propiedad está a True, todos ellos
están habilitados.
(*)
Font
ForeColor
Color de las letras del título del Frame.
Height
LSB
HelpContextID
Visual Basic – Guía del Estudiante
Index
Capítulo 1
Left
MouseIcon
MousePointer
Página 67
Name
TabIndex
Tag
Top
(*)
Visible
Cuando un Frame está con la propiedad Visible = False, tanto el propio Frame como todos los controles
interiores a el serán invisibles.
WhatsThisHelpID
Width
(*)
PROCEDIMIENTOS DEL FRAME
Click
MouseMove
LSB
DblClick
MouseUp
DragDrop
Visual Basic – Guía del Estudiante
Capítulo 1
DragOver
MouseDown
Página 68
CHECK BUTTON Y OPTION BUTTON (BOTONES DE ELECCION Y OPCION)
Se obtienen directamente de la caja de herramientas.
Dada la similitud de ambos controles, se comentan conjuntamente.
El control CheckBox, o casilla de verificación, permite elegir una opción (activada/desactivada,
True/False) que el usuario puede establecer o anular haciendo click. Una X en una casilla de
verificación indica que está seleccionada, activada, o con valor True. Cada casilla de verificación es
independiente de las demás que puedan existir en el formulario, pudiendo tomar cada una de ellas el
valor True o False, a voluntad del operador.
Un control OptionButton muestra una opción que se puede activar o desactivar, pero con dependencia
del estado de otros controles OptionButton que existan en el formulario.
Generalmente, los controles OptionButton se utilizan en un grupo de opciones para mostrar opciones
de las cuales el usuario sólo puede seleccionar una. Los controles OptionButton se agrupan
dibujándolos dentro de un contenedor como un control Frame, un control PictureBox o un formulario.
Para agrupar controles OptionButton en un Frame o PictureBox, dibuje en primer lugar el Frame o
PictureBox y, a continuación, dibuje dentro los controles OptionButton. Todos los controles
OptionButton que están dentro del mismo contenedor actúan como un solo grupo, e independientes de
los controles OptionButton de otros grupos distintos.
Aunque puede parecer que los controles OptionButton y CheckBox funcionan de forma similar, hay
una diferencia importante: Cuando un usuario selecciona un OptionButton, los otros controles del
mismo grupo OptionButton dejan de estas disponibles automáticamente. Por contraste, se puede
seleccionar cualquier número de controles CheckBox.
En el ejemplo de la figura, existen tres grupos de OptionButton, uno en un PictureBox, que actúa, al
tiempo que como cuadro de imagen, como contenedor de controles OptionButton. Otro grupo está en
el interior de un control Frame, y el otro grupo está en el formulario. Los tres grupos son independientes
entre sí, pero interiormente al grupo solamente puede seleccionarse uno de los OptionButton que lo
componen.
En el formulario también existen tres CheckBox, que como puede verse, se pueden seleccionar los que
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 69
se desee, sin ningún tipo de exclusión entre ellos.
PROPIEDADES
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya
comentadas para los controles precedentes.
Alignment
Común a ambos controles.
Admite los siguientes valores :
0 - Left Justify
1 - Right Justify
Cuando se elige el valor 0, justificado a la izquierda, el título del control aparece a la derecha del botón,
pegado a la figura del botón. Cuando se elige el valor 1, justificado a la derecha, el título (Caption)
aparece a la izquierda del botón, comenzando en la parte izquierda del cuerpo total del control, es decir,
no tiene porqué aparecer con su parte derecha pegado al botón, caso que el cuerpo total del control se
haya hecho mas largo que la palabra del título.
Appearance
Backcolor
Caption
(*).
Propiedades del CheckBox solamente.
DataField DataSource
Establecen el control Data asociado y el campo donde están los datos (True / False) que se llevarán a la
propiedad Value . Al igual que en los controles Label y TextBox esta propiedad nos permite visualizar
datos de una base de datos de una forma muy sencilla. En este caso, el CheckBox solamente permite
presentar (logicamente) datos de tipo Booleano.
DragIcon
DragMode
Enabled
Font
ForeColor
(*)
Height
Común a ambos controles.
La altura del control solamente afecta a la colocación del Titulo (Puede ponerse un título largo en varias
líneas), no al tamaño del botón, que es invariable.
HelpContextID
TabIndex
Index
TabStop
Left
Tag
MouseIcon
Top
MousePointer
(*)
Name
Value
Común a ambos controles
El valor de esta propiedad indica si el control está seleccionado (Value = 1) o no seleccionado (Value = 0
ó Value = False). Esta propiedad puede cambiarse en tiempo de ejecución. Mediante esta propiedad,
podemos tanto forzar el valor como leerlo.
Atención. Presenta una diferencia entre uno y otro control respecto a la forma de expresarse respecto a
su valor cuando está seleccionado. Para forzar que el control NO esté seleccionado, o para leer el Value
cuando no está seleccionado, podemos utilizar tanto Value = 0 como Value = False. Sin embargo,
cuando lo que se quiere es poner la propiedad a True hay una diferencia entre ambos controles.
Para el OptionButton podemos utilizar indistintamente las siguiente formas :
Option1.Value = True
Option1.Value = 1
Con cualquiera de ellas seleccionaremos ese control por programa.
Para el CheckBox solamente se podrá usar para este propósito la instrucción :
Check1.value = 1
El poner como Value el valor True nos dará en este control un error.
Para la lectura del Value, existe una diferencia entre el valor devuelto por el CheckBox y el devuelto por
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 70
el OptionButton.
Para leer el dato existente en un CheckBox es necesario utilizar la forma :
variable = Check1.Value donde variable tomará el valor 1 (no True)
Para el control OptionButton emplearemos una instrucción igual :
variable = Option1.Value
Visible
WhatsThisHelpID
donde variable tomará el valor True (no 1)
Width
(*)
PROCEDIMIENTOS
Click
KeyDown
LSB
DblClick (Solo OptionButton)
KeyPress
KeyUp
Visual Basic – Guía del Estudiante
Capítulo 1
DragDrop
LostFocus
DragOver
GotFocus
Página 71
LIST BOX Y COMBO BOX
Estos dos controles, debido a su similitud, se estudian conjuntamente.
Se obtienen directamente de la caja de herramientas :
Un control ListBox muestra una lista de elementos en la que el usuario puede seleccionar uno o más. Si
el número de elementos supera el número que puede mostrarse, se agregará automáticamente una
barra de desplazamiento al control ListBox.
Un control ComboBox combina las características de un control TextBox y un control ListBox. Los
usuarios pueden introducir información en la parte del cuadro de texto y seleccionar un elemento en la
parte de cuadro de lista del control. En resumen, un ComboBox es la combinación de un ListBox, que
se comporta como si de un ListBox se tratase, y de un TextBox, con comportamiento análogo a un
TextBox sencillo, con la particularidad aquí de que el texto se le puede introducir por teclado, o elegir
uno de los que figuran en la parte ListBox del Combo.
Estos controles toman la siguiente forma :
Puede verse en la figura un ejemplo de presentación de un ListBox (izquierda), un ComboBox con la
lista desplegada (Centro) y un ComboBox con la lista sin desplegar (Combo2 a la derecha).
La lista tiene varios elementos. Cada línea de esta lísta es un elemento de la lista. Como el número de
elementos de la lista tiene mas elementos de los que le podían caber, generó automáticamente la barra
de desplazamiento vertical.
El ComboBox está normalmente sin desplegar. Se despliega cuando se hace click con el ratón en la
flecha que tiene en su parte derecha (véase fig. Anterior). Al desplegarse, muestra la lista con todos sus
elementos. Haciendo click con el ratón en cualquiera de sus elementos, el elemento elegido pasa a la
parte TextBox del Combo y la lista vuelve a replegar.
El ListBox (y por tanto el ComboBox) tiene unas propiedades y métodos particulares que solamente se
pueden aplicar durante el tiempo de ejecución :
Propiedades
ListCount - Indica el número de elementos que tiene la lista
ListIndex - Indica el número de orden del elemento seleccionado dentro de la lista.
Text - Obtiene el elemento seleccionado.
List (n) - Obtiene el elemento cuyo orden dentro de la lista es n.
Métodos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 72
AddItem - Añade un elemento a la lista.
RemoveItem - Elimina un elemento de la lista.
Clear – Borra todos los elementos de la lista
ListCount valdrá 0 si la lista no tiene ningún elemento, y n si tiene n elementos.
Para seleccionar un elemento de la lista, basta con hacer click con el ratón sobre él. Ese elemento se
resaltará con fondo en azul. Una vez seleccionado un elemento, la propiedad ListIndex tomará el valor
del número de orden que ocupa ese elemento en la lista, comenzando por el 0 para el elemento que
ocupa el primer lugar. Si no se selecciona ningún elemento, el valor de la propiedad ListIndex será -1. El
primer elemento de la lista es ListIndex 0, y el valor de la propiedad ListCount siempre es uno más que
el valor mayor de ListIndex.
En el ComboBox la propiedad Text contiene el texto que contenga la parte TextBox del Combo, bien
haya sido introducida desde teclado o mediante la recuperación de un elemento la parte ListBox del
mismo.
Ejemplos
Supongamos que tenemos un ListBox llamado List1, y un ComboBox llamado Combo1. Se enumeran
distintas formas de obtener información de ellos.
Variable = List1.Listcount
Variable contendrá un número con el número total de elementos de la lista List1.
Variable = List1.ListIndex
Variable contendrá un número con el número de orden del elemento de la lista
seleccionado en ese momento.
List1.AddItem “ELEMENTO NUEVO”
Añade un elemento a List1. En este caso, el elemento añadido es la palabra
ELEMENTO NUEVO.
Variable = “VISUALBASIC”
List1.AddItem Variable
Añade un elemento a List1. En este caso, el elemento añadido es la palabra
VISUALBASIC.
Variable = List1.Text
Variable contendrá el elemento que estaba seleccionado en List1. (Variable será una
cadena de caracteres)
Variable = List1.List (n)
Variable contendrá el elemento que ocupa el número de orden n dentro de la lista.
Variable = List1.List (List1.ListIndex)
Variable contendrá el elemento que estaba seleccionado en List1. Se ha utilizado la
propiedad List para obtener el elemento, y en vez de introducir un número para definir el
elemento que se desea, se introdujo el valor ListIndex de List1, que es concretamente, el
número de orden del elemento seleccionado en ese momento. Observe que poner
List1.List (List1.ListIndex) es idéntico a poner List1.Text.
List1.RemoveItem (n)
Elimina el elemento n de List1.
List1.RemoveItem (List1.ListIndex)
Elimina el elemento que estaba seleccionado en ese momento.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 73
List1.listIndex = n
Selecciona el elemento n de List1 (Se resalta en azul el elemento n)
PROPIEDADES DE ListBox y de ComboBox
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya
comentadas para los controles precedentes.
Appearance
Backcolor
Columns
Propiedad de ListBox solamente.
(*)
Determina si los elementos se presentan en una sola columna o en varias columnas, y la forma de
presentar los elementos en el ListBox. Si esta propiedad se pone a 0 la lista tendrá solamente una
columna, y presentará los elementos uno debajo de otro. Cuando los elementos sean mas que los que
se pueden presentar en la lista, aparecen automáticamente unas barras de desplazamiento vertical.
Si la propiedad se pone a un número distinto a 0, el ListBox es de tipo multicolumna, presentará en
cada columna los elementos que le quepan dependiendo de su dimensión vertical, y tendrá tantas
columnas como sea necesario para albergar el número de elementos que tenga. Presentará en su
cuadro tantas columnas como se le indique en el valor de esta propiedad, y si no puede presentar todos
los elementos en las columnas que muestra, le aparecerán barras de desplazamiento horizontales para
poder movernos por todas las columnas que tenga.
Recuerde : El número que se le asigna a la propiedad Columns no indica el número de columnas que
tendrá el ListBox sino el número de columnas que presenta.
Esta propiedad puede asignarse en diseño, mediante la caja de propiedades, o en tiempo de ejecución
mediante una instrucción como esta :
Nombrelista.Columns = número
.
Esta propiedad no puede definirse a 0 o cambiada desde 0 en tiempo de ejecuciones decir, no se puede
convertir en tiempo de ejecución un ListBox de múltiples columnas en un ListBox de columna única o un
ListBox de columna única en un ListBox de múltiples columnas. Sin embargo, sí es posible cambiar
durante la ejecución el número de columnas de un ListBox de múltiples columnas.
.
DataField DataSource
Establecen el control Data asociado y el campo donde están los datos que se llevarán al TextBox o
ComboBox para presentar datos procedentes de una Base de Datos.
DragIcon
ItemData
DragMode
Enabled
Font
(*)
Propiedad muy importante.
ForeColor
Height
HelpContextIDIndex
Devuelve o establece un número específico para cada elemento de un control ComboBox o ListBox.
Sintaxis
NombreDeLaLista.ItemData(índice) [= número]
NombreDeLaLista
Nombre del ListBox o ComboBox.
índice
El número de un elemento concreto del objeto.
número
El número que se asocia con el elemento especificado.
La propiedad ItemData es una matriz de valores enteros largos cuyo número de elementos es el valor de
la propiedad ListCount del control. Los números asociados con cada elemento se pueden usar para
cualquier fin. Por ejemplo, se puede usar en la confección de una lista de teléfonos, el número de
identificación de un empleado, etc. Cuando se rellena el ListBox, también se rellena los elementos
correspondientes de la matriz ItemData con los números correspondientes.
La propiedad ItemData se usa a menudo como índice de una matriz de estructuras de datos asociados
con los elementos de un control ListBox.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 74
Nota Cuando se inserta un elemento en una lista con el método AddItem, el elemento también se
inserta automáticamente en la matriz ItemData. Sin embargo, el valor no se reinicializa a cero; retiene el
valor que estaba en esa posición antes agregar el elemento a la lista. Cuando se usa la propiedad
ItemData, asegúrese de establecer su valor al agregar nuevos elementos a la lista.
Left
(*)
List
Es el contenido de la lista.
Si la lista de elementos es corta e invariable, pueden introducirse los elementos en el cuadro de
propiedades durante el diseño.
MouseIcon
MousePointer
(*)
Name
Sorted
Establece o devuelve un valor que indica si los elementos de un ListBox o ComboBox se
colocan automáticamente en orden alfabético. Los valores que puede adoptar son True o
False.
True Los elementos de la lista se ordenan alfabéticamente (sin distinguir entre mayúsculas y
minúsculas).
False (Predeterminado) Los elementos de la lista no se ordenan alfabéticamente.
Cuando esta propiedad tiene el valor True, Visual Basic se encarga de casi todo el
procesamiento de cadenas necesario para mantener el orden alfabético, incluyendo el cambio
de los números de índice cuando se agregan o eliminan elementos.
Nota El uso del método AddItem para agregar un elemento en una posición específica de la
lista puede romper el orden alfabético, y los elementos agregados con posterioridad pueden no
ordenarse correctamente.
TabIndex
TabStop
Tag
Top
Visible
WhatsThisHelpID
Width
(*)
PROCEDIMIENTOS
Click
Change (Solo ComboBox)
DblClick
DropDown (Solo ComboBox)
GotFocus
KeyUp
LostFocus
MouseDown (Solo ListBox)
MouseUp (Solo ListBox)
DragDrop
DragOver
KeyDown
KeyPress
MouseMove (Solo ListBox)
NOTA MUY IMPORTANTE
El procedimiento Change del ComboBox solamente se efectúa cuando el cambio se produce mediante
la entrada de un texto DESDE EL TECLADO, no por un cambio en la parte Text de este control,
producido al llevar un elemento desde la parte List a la parte Text.
CONTROLES HScrollBar y VScrollBar
Son dos controles similares, para introducir un dato cuasi-analógico en una aplicación. Se toman
directamente de la caja de herramientas, y tienen un aspecto parecido al de un control de volumen de un
equipo de música. El HScrollBar está en posición horizontal, y el VScrollBar en posición vertical.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 75
Mediante estos controles se pueden introducir datos variando la posición del cursor.
PROPIEDADES de HScrollBar y VScrollBar
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya
comentadas para los controles precedentes.
DragIcon
DragMode
Enabled
Height
HelpContextID
Index
(*)
LargeChange
Esta propiedad establece la variación de la propiedad Value cada vez que se hace click en el interior de
la barra de desplazamiento, en la parte por donde pasa el cursor.
Left
(*)
Max
Esta propiedad establece el valor máximo para la propiedad Value, es decir, el valor de esta propiedad
cuando el cursor está en su parte máxima. (Recuerde que el cursor está en el máximo, cuando está mas
a la derecha, caso del HScrollBar, o cuando está en la parte mas baja, caso del HScrollBar.
Min
Esta propiedad establece el valor mínimo para la propiedad Value, es decir, el valor de esta propiedad
cuando el cursor está en su parte mínima. (Recuerde que el cursor está en el mínimo, cuando está mas
a la izquierda, caso del HScrollBar, o cuando está en la parte mas alta, caso del HScrollBar.
MouseIcon
MousePointer
Name
(*)
SmallChange
Esta propiedad establece la variación de la propiedad Value cada vez que se hace click en las flechas
superior o inferior de la barra de desplazamiento.
TabIndex
TabStop
Tag
Top
(*)
Value
Esta propiedad lee o establece el valor dado por la posición del cursor. Este valor tiene un mínimo,
establecido por Min y un máximo, establecido por Max. Esta propiedad es la que se debe leer para
conocer la posición del cursor.
Visible
WhatsThisHelpID
Width
(*)
PROCEDIMIENTOS DE HScrollBar y VScrollBar
Change
KeyUp
LSB
DragDrop
LostFocus
DragOver
Scroll
Visual Basic – Guía del Estudiante
Capítulo 1
GotFocus
KeyDown
KeyPress
Página 76
El Procedimiento Change se produce cuando, tras mover el cursor, se suelta el botón
Comentario
del ratón. Esto produce el efecto de que el cambio que se tenga que producir con el movimiento del
cursor no se realiza de una manera continua. El procedimiento Scroll se realiza en el instante que se
está moviendo el cursor. Por lo tanto, es este procedimiento el que se debe usar para conseguir el efecto
de un cambio continuo mientras se está moviendo el cursor.
TIMER
TEMPORIZADOR
Este objeto permite establecer temporizaciones. Presenta una novedad respecto a los controles
estudiados hasta ahora. El control Timer solamente se ve durante el tiempo de diseño. En tiempo de
ejecución, el control permanece invisible.
La temporización producida por el Timer es independiente de la velocidad de trabajo del ordenador.
(Casi independiente. El timer no es un reloj exacto, pero se le parece)
Se toma directamente de la caja de herramientas, y tiene el aspecto siguiente :
PROPIEDADES
Enabled
Index
(*)
Interval
El valor de esta propiedad nos dará el intervalo de tiempo (en milisegundos) en que se producirá un
evento Timer y consecuentemente, realizará el procedimiento asociado a este evento. Si el valor de la
propiedad Interval está a 0 (Predeterminado), no se produce el evento Timer. (El control Timer está
deshabilitado cuando la propiedad Interval = 0)
Left
Name
Tag
Top
(*)
PROCEDIMIENTOS
Timer
Se produce cada vez que se cumple un intervalo completo.
CONTROL
SHAPE
Se toma directamente de la caja de herramientas :
Shape es un control gráfico que se muestra como un rectángulo, un cuadrado, una elipse, un círculo, un
rectángulo redondeado o un cuadrado redondeado.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 77
Un control Shape no actúa como contenedor de controles. (Esto quiere decir que un control Shape
nunca le servirá, por ejemplo, para albergar varios OptionButton y pretender que sean independientes
de otros controles OptionButton que se encuentren fuera del control Shape.
Este control no tiene Procedimientos. En realidad, solamente sirve para mostrar un determinado gráfico,
envolver gráficamente a otros controles, pero no tiene ninguna aplicación en cuanto a programa. Es un
“adorno ” para sus aplicaciones.
PROPIEDADES
Backcolor
(*)
BackStyle
Esta propiedad establece si Shape permite ver a su través (Transparent) o n lo permite (Opaque)
BorderColor
Establece el color del borde.
BorderStyle
Establece el tipo de borde. Puede ser : Transparent, (No se ve el borde), Solid, (Borde de línea
continua),Dash, (línea a rayas), Dot, (línea a puntos), Dash-Dot, (línea de raya - punto), dash-Dot-Dot,
(línea de raya - punto - punto), InsideSolid, (raya continua)
El efecto de establecer la propiedad BorderStyle depende del valor de la propiedad BorderWidth. Si
BorderWidth no es 1 y BorderStyle no es 0 o 6, BorderStyle se establece como 1.
BorderWidth
Establece el ancho de la línea.
DrawMode
FillColor
FillStyle
Height
Index Left
Name (*)
Shape
Establece la forma del control. Puede ser : Rectangular, cuadrado, redondo, ovalado, cuadrado con
esquinas redondeadas y rectangular con esquinas redondeadas.
Tag
Top
PROCEDIMIENTOS
Visible
Width
(*)
No tiene.
CONTROL LINE
Se toma directamente de la caja de herramientas
Line, al igual que Shape, es un control gráfico que solamente sirve para poner una línea en un
formulario. Del mismo modo, no tiene procedimientos, por lo que no sirve para aportar código al
programa. Solo sirve para aportar una característica gráfica, es un adorno.
PROPIEDADES
BorderColor
Establece el color de la línea.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 78
BorderStyle
Establece el tipo de línea : Puede ser : Transparent, (No se ve la línea), Solid, (Línea continua),Dash,
(línea a rayas), Dot, (línea a puntos), Dash-Dot, (línea de raya - punto), dash-Dot-Dot, (línea de raya punto - punto), InsideSolid, (raya continua)
BorderWidth
Establece el ancho de la línea.
DrawMode
X1, X2
Index
Y1, Y2
Left
Name
Tag
Visible
Establece las coordenadas y del inicio y final
(*)
No tiene.
PROCEDIMIENTOS
AÑADIR CONTROLES A LA CAJA DE HERRAMIENTAS
Los controles descritos hasta ahora son parte de los que aparecen en la caja de herramientas mas
elemental de Visual Basic. Estos, otros que se estudiarán en el capítulo 4 (Controles para mostrar
imágenes), el control Data y el contenedor OLE que se estudiarán en la segunda parte del curso, son los
que están incluidos en la caja de herramientas mas elemental. La razón es que estos controles vienen
como lo más elemental de Visual Basic, como lo que es imprescindible para que funcione una aplicación
realizada en VB. La pregunta es ahora, ¿qué es lo más elemental de VB?
Son tres DLLs, Visual Basic For Aplications (MSVBVM60.DLL), Visual Basic Runtime Objets And
Procedures (MSVBVM60.DLL\3) y Visual Basic Objets And Procedures (VB6.OLB). Una aplicación, por
muy elemental que sea, necesita esos tres ficheros. Pero posiblemente no haya ninguna aplicación
práctica que se pueda realizar con esos controles. Hay más. Lo que ocurre es que hay que introducirlos
en la caja de herramientas. Para ello, basta con desplegar el menú de Proyecto de la barra de menú:
Eligiendo el elemento Componentes de este menú desplegado nos muestra todos los componentes
existentes en el disco, que podremos sacar a nuestra caja de herramientas para poder utilizarlos. En la
siguiente figura puede ver el cuadro con los controles existentes en el PC del autor. Puede observarse
que está seleccionado el control Calendar, y en la parte de abajo puede verse la ubicación y nombre del
fichero que contiene ese control (MSCAL.OCX). No todos los controles son de Microsoft. Observe que
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 79
hasta Kodak realiza (o le realizan) controles. Existen muchas empresas que venden controles, unas con
mejor calidad que otras. En este tema debe tener especial precaución con los controles que se
distribuyen de forma gratuita por Internet. No utilice nunca un control adquirido por este procedimiento si
no tiene plena confianza en el origen del mismo y lo ha probado concienzudamente. Suelen fallar con
bastante frecuencia y, lógicamente, no tienen ninguna garantía. Sea prudente y utilice solamente
aquellos controles de firmas de reconocido prestigio, y que le puedan aportar garantía de
funcionamiento. Obviamente estos controles suelen ser de pago.
Estos controles que adquiere con posterioridad a la instalación del Visual Basic hay que registrarlos.
No se asuste. No se trata de registrarlos ante el fabricante para poder utilizarlos. Se trata de introducirlos
en el registro de Windows. Con ello Windows conoce el CLSID de ese control, su ubicación en el disco
duro (los controles suelen estar en C:\Windows\System, pero pueden estar en cualquir otra carpeta).
Windows necesita registrarlos para poder encontrarlos. Para registrar un control se utiliza el programa
Regsvr32.exe. Para registrar un control basta con ejecutar este programa, pasandole como parámetro el
nombre y ubicación del control a registrar. Esto se hace en Inicio | Ejecutar. Por ejemplo, para registrar
el conjunto de controles VB_GuiaEst.Ocx introduciríamos ese fichero Ocx en C:\Windows\System y a
continuación ejecutamos:
regsvr32 c:\windows\system\ VB_GuiaEst.Ocx
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 80
El conjunto de todos los controles es la colección Controls
Verá a lo largo del curso que Visual Basic utiliza mucho las colecciones. Una de ellas es la colección
Controls, que es el conjunto de todos los controles existentes en un formulario.
Visual Basic trata a las colecciones como un objeto más. Así, las colecciones tienen sus propiedades.
No vamos a entrar en demasiados detalles de momento, pero una de las propiedades de todas las
colecciones en Count, que es precisamente el número de elementos que componen esa colección.
La numeración de los elementos de una colección siempre va del 0 al n-1, siendo n el número de
elementos de esa colección.
Vamos a ver una expresión que nos puede ayudar mucho. Sirve para saber a que tipo de control
pertenece un determinado elemento. Esa expresión es TypeOf y siempre se debe usar con una
sentencia condicional If y aplicarla solamente sobre una variable tipo objeto. (No se preocupe al leer
esto, es muy fácil) (No se puede utilizar con Select Case)
Una variable tipo objeto es una variable que no contiene un dato numérico o string. Contiene un objeto.
Por ejemplo, un control.
Podemos declarar una variable como Control
Dim Pepe as Control
Pepe será un control. Ahora podemos poner
For Each Pepe in Controls
‘ Para cada valor que tome Pepe haciedole recorrer todos
‘ los elementos de la colección Controls
' Si pepe es un TextBox ….
If TypeOf Pepe Is TextBox Then
Pepe.Locked = True
End If
Next Pepe
' lo bloquea
Puede usar este código para bloquear todos los TextBox de un formulario. Se mete en un procedimiento
llamado Bloquear (p.e.) y cada vez que queramos bloquear todos los TextBox del formulario basta con
citar a este procedimiento. Un código similar sería
Dim I As Integer
For I = 0 To Controls.Count - 1
If TypeOf Controls(I) Is TextBox Then
Controls(I).Locked = True
End If
Next
(Observe que en la segunda versión, trabajamos directamente sobre los elementos de la colección, que
se distinguen unos de otros mediante el Indice colocado entre paréntesis. En este caso, la variable I que
tomará los valores entre 0 y n-1)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 81
Resumen de Propiedades de los controles Visual Basic
Caption
Título
Es el texto del control o lo que figura en la barra de menú del formulario. Puede cambiarse en tiempo de
ejecución.
DragMode
Modo de iniciar una operación de Drag & Drop
Establece un valor que determina si se usa el modo de arrastre manual o automático en una operación
de arrastrar y colocar. Los valores posibles de esta propiedad son:
0
1
DrawStile
Manual
Automático
Estilo de dibujo
Establece el estilo de línea de la salida de métodos gráficos:
Valores:
0 - Línea continua
1 - Rayas
2 - Puntos
3 - Raya - Punto
4 - Raya - Punto - Punto
5 - Transparente
6 - Continuo interior.
DrawWidth
Ancho de la línea
Establece el ancho de una línea dibujada. El valor debe expresarse en pixeles.
Enabled
Activado
Propiedad Booleana. Si está en True, el formulario o control está activado y se puede interactuar con él.
Si está en False, se desactiva, impidiendo de esta forma, que se pueda trabajar con él. Puede variarse
en tiempo de ejecución. Cuando un control está deshabilitado (Enabled = False), el control no tiene
efecto, y su apariencia varía, presentando un tono pálido tanto en su cuerpo como en su título.
FillStyle
Tipo de relleno
Establece el modo de rellenar controles Shape, o figuras (círculos o cuadrados) creados con los
métodos gráficos Circle y Line.
Valores:
FillColor
0 - Continuo
1 - Transparente
2 - Línea Horizontal
3 - Línea Vertical
4 - Diagonal hacia arriba
5 - Diagonal hacia abajo
6 - Cruzado
7 - Diagonal cruzada
Color de relleno
Especifica el color del relleno contemplado en FillStyle.
Font
Fuente
Es el tipo de letra para el título o el texto del control. Puede cambiarse en tiempo de ejecución.
FontSize
LSB
Tamaño de letra
Visual Basic – Guía del Estudiante
Capítulo 1
Página 82
Establece el tamaño de la letra que se usará en ese formulario o control (U otro objeto VB, p.e. el
Printer). Esta propiedad puede variarse en tiempo de ejecución. El tamaño debe expresarse en puntos.
Máximo, 2160 puntos.
FontBold, FontItalic, FontStrikethru, FontUnderline
Permiten, en tiempo de ejecución, cambiar un texto a negrita, cursiva, tachado y subrayado. Son
propiedades Booleanas True / False
Height
Altura
Define la altura de un formulario o control. El valor de esta propiedad no se introduce normalmente como
un dato numérico, sino que toma el valor automáticamente, dependiendo de las dimensiones del objeto
durante el tiempo de diseño. Puede cambiarse durante el tiempo de ejecución.
HelpContextID
Número de Contexto
Establece un número de contexto asociado para este formulario. Este número se aplica para determinar
la ayuda interactiva asociada a este formulario o control. Vea mas adelante, el tema Ayuda de Windows.
Puede tomar los siguientes valores :
Index
0 - No se especifica número de contexto
>0 Un entero que especifique un contexto válido.
Indice
En el caso de que se tengan varios controles que realicen una función similar (Las teclas numéricas de
una calculadora, p.e.) puede hacerse un array con estos controles. Todos tendrán el mismo nombre, y se
diferencian por un índice. La propiedad Index de ese control toma el número de ese índice.
Left
Posición de su parte izquierda.
Indica la posición del control, concretamente de la parte izquierda del mismo. Normalmente esta
propiedad no se introduce numéricamente, sino que la toma automáticamente de la posición que se le
de al control en tiempo de diseño. Puede cambiarse en tiempo de ejecución.
MouseIcon
Valor por defecto: ninguno
Establece un icono personalizado para el puntero del ratón cuando esté encima del Formulario o control.
Este icono puede ser un Bitmap de los existentes en el directorio Icons de Visual Basic o cualquiera que
tengamos. Si se pone 99 como valor de la propiedad MousePointer (siguiente), cada vez que el puntero
del ratón pase por este Formulario o control, cambiará su forma y adoptará la del icono elegido.
MousePointer
Valor por defecto: flecha
Determina la forma del puntero del ratón cuando se coloca encima del formulario o control. Puede
elegirse uno de los punteros preestablecidos (15 en total) o el personalizado visto en la propiedad
anterior. Para elegir ese icono personalizado, debemos poner en esta propiedad el valor 99.
TabIndex
Nº de orden para tabulador
Cuando disponemos de varios controles en un mismo formulario, solamente uno de ellos tiene el foco.
Esta expresión de tener el foco significa que ese control está remarcado y en esa condición, si pulsamos
la tecla ENTER haría el mismo efecto que hacer click con el ratón en ese control, o, en el caso de un
TextBox, las letras pulsadas en el teclado van a ese TextBox.
Podemos variar el foco de un control a otro mediante la tecla TAB (TABulador).Esto es necesario, ya que
existen ordenadores que no disponen de ratón (típico de algunos portátiles). En estos casos, para elegir
uno u otro control debemos pulsar repetidas veces la tecla TABulador. El foco irá cambiando de uno a
otro control (pueden ser controles de distinto tipo) cada vez que pulsemos la tecla TABulador. Esta
propiedad TabIndex marca el orden que seguirá el foco a través de cada control.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 83
TabStop
Sale del control de la tecla TAB
Propiedad Booleana. Cuando esta propiedad está a False, el botón no tomará el foco cuando se pulse la
tecla del Tabulador. Sin embargo sigue manteniendo el índice de la propiedad TabIndex descrita
anteriormente. Puede cambiarse en tiempo de ejecución. Esto nos permite descartar algún botón de
tomar el foco, cuando por facilidad para el usuario, sea conveniente en determinados puntos del
programa.
Tag
Valor auxiliar
Esta propiedad no la usa directamente Visual-Basic. Sirve para asociar al formulario información
adicional para fines externos a la programación. Pero también le puede servir para almacenar en ella
una variable para que la use un código ajeno al formulario. El autor de esta Guía del Estudiante tiene por
costumbre utilizar la propiedad Tag del formulario inicial para guardar el parámetro que se le pasa a
algunos programas para acceder a ellos con unos determinados privilegios. Resumiendo, está ahí para
lo que el programador quiere.
Top
Posición de la parte superior
Indica la coordenada de la parte superior del control. Puede variarse durante el tiempo de ejecución.
Esta propiedad, juntamente con Left definen la esquina superior izquierda del botón de comando.
Normalmente esta propiedad no se introduce numéricamente, sino que la toma automáticamente de la
posición que se le den al botón en tiempo de diseño. Puede cambiarse, cambiando el valor a esta
propiedad, en tiempo de ejecución.
Visible
Propiedad Booleana. Asignándole el valor True al control o formulario, será visible, y asignándole el
valor False, no se verá. Este valor puede cambiarse durante el tiempo de ejecución para ocultar y hacer
visible el formulario o control correspondiente.
WhatsThisHelpID
(Propiedad, Windows 95)
Devuelve o establece un número de contexto asociado a un objeto. Se utiliza para dotar a las
aplicaciones de Ayuda interactiva con el menú emergente ¿Qué es esto? de la Ayuda de W 95.
Ancho
Width
Define la anchura del formulario o control. Normalmente no se introduce como valor numérico sino que lo
toma automáticamente del tamaño que tenga el formulario o control durante el tiempo de diseño.
Juntamente con Height define el tamaño del objeto. Puede cambiarse durante el tiempo de ejecución
RESUMEN DE LOS EVENTOS DE LOS OBJETOS VISUAL BASIC
Evento Click
Hacer Click con el botón izquierdo del ratón
Lo tienen casi todos los controles y el formulario. Es el evento habitual para introducir el código que
queremos que realice el programa al hacer click sobre un determinado control. No es el único evento
donde podemos hacerlo, pues también tenemos otros muy parecidos (MouseDown, MouseUp), pero que
funcionan de distinta forma. El evento Click en el formulario se efectúa cada vez que pulsamos uno de
los botones del ratón. En los controles, sólo con el botón izquierdo.
Si un control tiene el foco, se ejecutará su evento Click al pulsar ENTER o la barra espaciadora.
El evento Click no pasa parámetros
Evento DragDrop
LSB
Acción de Soltar durante el Drag & Drop
Visual Basic – Guía del Estudiante
Capítulo 1
Página 84
Se produce cuando se ‘suelta’ el ratón sobre un formulario o control, durante una operación de Drag &
Drop. Pasa los parámetros Source As Control, X As Single, Y As Single, donde Source es el control
donde se originó el Drag & Drop, y X e Y las coordenadas del puntero del ratón en el momento de soltar.
Vea el capítulo de Drag & Drop
Arrastrar por encima
Evento DragOver
Ocurre cuando se pasa por encima de un formulario o control durante la operación de Drag & Drop.
Pasa los parámetros Source As Control, X As Single, Y As Single, State As Integer. Los parámetros son
los mismos que en el procedimiento anterior. State es un entero que indica el estado de transición del
puntero sobre el formulario. Toma los siguientes valores :
0 = Entra (El puntero del ratón está entrando al formulario o control).
1 = Deja (El puntero del ratón está saliendo del formulario o control).
2 = Sobre (El puntero del ratón se desplaza de una posición a otra dentro del formulario o
control). Vea el capítulo de Drag & Drop
Evento GotFocus Tomar el Foco
Ocurre este evento cuando el control toma el foco. Tomar el foco significa que se acaba de convertir en
el control activo. (por ejemplo, cuando llevamos el cursor y hacemos click sobre un Text Box. Hay
algunos controles que no tienen procedimiento GotFocus porque nunca toman el foco (Label, p.e.)
Evento KeyDown Pulsar una tecla (Ocurre cuando el control tiene el foco)
Se produce sobre el control que tiene el foco al pulsar una tecla, justo en el instante que llega a su
posición inferior. Pasa como parámetros el KeyCode As Integer y el Shift As Integer. El KeyCode es el
código de la tecla (no confundir con Keyascii, que es el código de la letra. Hay teclas que no tienen
Keyascii y sí tienen KeyCode F1, F2, ...Insert, ) Shift es la posición de la tecla Mayúsculas (1=pulsada,
0=levantada)
Evento KeyPress Pulsar una tecla (Ocurre cuando el control tiene el foco)
Este evento se produce después del KeyDown, y pasa como parámetro el KeyAscii As Integer, que es el
código Ascii de la letra cuya tecla se ha pulsado.
Evento KeyUp Levantar la tecla pulsada (Ocurre cuando el control tiene el foco)
Ocurre al levantar la tecla, después del KeyPress. Pasa como parámetros los mismos que KeyDown,
KeyCode As Integer, Shift As Integer
Estos tres eventos se producen también en el formulario (y antes que en el control), si el formulario tiene
la propiedad KeyPreview = True
LinkClose
LinkError
LinkNotify
LinkOpen
Son eventos relacionados con el DDE (Intercambio Dinámico de Datos). Ocurren respectivamente
cuando se cierra el enlace DDE, cuando ocurre un error en el enlace, cuando han cambiado los datos en
origen y en destino se ha establecido la propiedad LinkMode a Notify, y cuando se inicia una
conversación DDE. Vea el capítulo dedicado al DDE para mas detalles.
LostFocus
Ocurre cuando el control pierde el foco. Este evento es muy importante, por ejemplo en un Text Box,
para dar el formato adecuado al texto contenido en ese Text Box, o para comprobar que es correcto, etc.
MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Se ejecuta en el instante de apretar el botón de mouse, cuando está el puntero encima del formulario o
control correspondiente. Pasa como parámetros el botón pulsado (1= izquierdo, 2 = derecho, 3 = centro),
la tecla mayúsculas (Shift=1 significa pulsada, =0 no pulsada) y las coordenadas X e Y del puntero del
ratón.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 85
MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Se ejecuta cuando pasa por encima del formulario o0 control el puntero del ratón
MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Similar a MouseDown, pero cuando se levanta el botón.
Existen mas eventos. No se van a mencionar aquí todos, pues se irán viendo según avance el curso.
Y no se preocupe si este capitulo le ha resultado muy pesado. Les pasa a todos. El próximo va a ser
mas divertido.
Visual Basic - Guía del Estudiante Cap. 3
Controles (Continuación) El CommonDialog
CONTROLES DE BUSQUEDA DE FICHEROS
El CommonDialog es un control del que se libran muy pocas aplicaciones. Dada la importancia de este
control, se le dedicaba en versiones anteriores de la Guía del Estudiante un capitulo único. En esta
edición se le a anexado el estudio sobre los controles para la búsqueda de ficheros. El conocimiento de
este capítulo es fundamental si desea llegar a ser un buen programador de VB.
CUADRO DE DIALOGO
CommonDialog
Normalmente se encuentra en la caja de herramientas
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 86
Este control no se presenta en tiempo de diseño mas que con un simple icono :
El cuadro de diálogo, CommonDialog se utiliza para varias funciones :

Abrir Ficheros
Guardar Ficheros
Elegir colores
Seleccionar Impresora
Seleccionar Fuentes
CommonDialog mostrando la función Abrir. Nótese el icono para crear nueva carpeta, objeto del
comentario siguiente.
En realidad el cuadro de diálogo permite conocer datos con los cuales, y mediante el código adecuado,
abriremos o guardaremos ficheros, elegiremos colores o seleccionaremos fuentes. Es decir, el
CommonDialog NO realiza mas funciones que mostrar ficheros existentes, fuentes disponibles, colores,
para que, mediante código, abramos esos ficheros o usemos una determinada fuente.
La expresión anterior se ha recuadrado porque ya no es completamente cierta. El CommonDialog no es
un control propio de Visual Basic, sino de Windows. Y la versión de este control que Windows pone en
W98 permite que pueda crear una nueva carpeta. Ya hace algo directamente . No se extrañe que el
CommonDialog empleado en su aplicación pueda crear una nueva carpeta sin que Vd. lo haya diseñado
para eso. Al introducir el control en la aplicación está introduciendo la versión más moderna del mismo.
Dependiendo de la aplicación para la que vaya a usarse se deberá activar de distintas formas. Si el
cuadro de diálogo se va a usar para seleccion ar la impreso ra y para otras aplicacio nes, es
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 87
recom endable usar uno exclusivam ente para seleccionar la imp resora.
Esta última recomendación se debe a que, para el control de la impresora, el CommonDialog SI realiza
las funciones de selección de impresora predeterminada. Esta diferencia operativa hace que si usamos
el mismo CommonDialog para seleccionar impresora y abrir ficheros, por ejemplo, se “cuelgue” el
CommonDialog.
El control CommonDialog es un control personalizado (Microsoft CommonDialog Control
COMDLG32.OCX), y como casi todos los controles personalizados presenta un asistente de
propiedades propio. Puede accederse a las propiedades mediante el cuadro de propiedades típico de
otros controles, o mediante el asistente, pulsando el botón derecho del ratón con el puntero colocado
encima del icono del cuadro de diálogo.
Analizando las propiedades, vemos que tiene gran cantidad de ellas. Esto es porque agrupa todas las
propiedades correspondientes a la cinco funciones que puede desarrollar. Se detalla a continuación la
forma de usar el CommonDialog para cada aplicación.
Se entiende que el nombre - Name - que se ha puesto para el cuadro de diálogo en todos los ejemplos
es CD1 )
CUADRO DE DIALOGO MOSTRANDO FUENTES
Para mostrar el cuadro de diálogo correspondiente a Tipos de Letra ( Fonts ), debe ejecutarse la
instrucción:
CD1.ShowFont
y haber puesto, en la propiedad Flags del cuadro de diálogo, el valor de 1, 2 ó 3, correspondiente
respectivamente a los tipos de letra de la pantalla, de la impresora o ambos. (Véase la propiedad Flags
mas adelante) Si no pon e uno de estos valores, le diráque no tiene fuentes ins taladas.
Los valores que se pueden obtener de este cuadro de dialogo son:
CD1.FontName
Indica el nombre de la fuente
CD1.FontSize
Indica el tamaño de la fuente
CD1.Color
Indica el color de la fuente (Abrir con Flags=256+1, 2 ó 3)
CD1.FontBold = (True / False) Si es True, se ha elegido "Negrita"
CD1.FontItalic = (True / False) Si es True, se ha elegido "Cursiva"
CD1.FontStrikethru = (True / False)
Si es True, se ha elegido "Tachada "
CD1.FontUnderline = (True / False)
Si es True, se ha elegido "Subrayada"
Si se elige una versión Negrita Cursiva serían True las opciones FontBold y FontItalic
El cuadro de diálogo que se presenta es el siguiente: (CommonDialog Mostrando fuentes, con la
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 88
propiedad Flags = 263)
El objeto Font no puede aplicarse al CommonDialog. Es decir, no podemos poner :
Variable = CD1.Font.Size
sino
Variable = CD1.Fontsize
En el ejemplo que acompaña a este capítulo, puede ver como se introducen las características de una
determinada fuente elegida en un cuadro de texto.
Programa de ejemplo. Mediante un CommonDialog elegimos el tipo de letra de un TextBox (TbPrueba)
y escribimos un texto de prueba con todas las letras del abecedario.
Private Sub BMostrarFonts_Click()
CD1.Flags = 259
'Muestra las fuentes de la pantalla (1), las de la impresora (2)y muestra las opciones de
'tachado, subrayado y color (256) 1 + 2 + 256 = 259
CD1.ShowFont
TbPrueba.FontName = CD1.FontName
TbPrueba.FontSize = CD1.FontSize
TbPrueba.FontBold = CD1.FontBold
TbPrueba.FontItalic = CD1.FontItalic
TbPrueba.FontUnderline = CD1.FontUnderline
TbPrueba.FontStrikethru = CD1.FontStrikethru
If TbPrueba = "" Then
TbPrueba = "Texto de prueba" & vbCrLf & vbCrLf
TbPrueba = TbPrueba & "The Quick Brown Fox Jumps Over The Lazy Dog 1234567890"
End If
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 89
CUADRO DE DIALOGO MOSTRANDO COLOR
Para mostrar el cuadro de diálogo correspondiente al color, se deberá ejecutar la instrucción:
CD1.ShowColor
El cuadro de diálogo puede tener una de estas dos formas (Dependiendo de su propiedad Flags):
(Si la parte derecha del cuadro no sale, se saca haciendo click en Definir colores personalizados.)
El número correspondiente al color elegido se puede conocer analizando la propiedad color de cuadro de
diálogo. En nuestro ejemplo, lo obtendríamos con
Variablecolor = CD1.Color
donde Variablecolor contendrá un número correspondiente al color elegido. Variablecolor debe
declararse como tipo Long
Programa de ejemplo. Mediante un CommonDialog elegimos el color de fondo de un TextBox
(TbPrueba).
Private Sub BColores_Click()
CD1.Flags = 2
'Hace que el cuadro de diálogo se muestre completo
CD1.ShowColor
TbPrueba.BackColor = CD1.Color
End Sub
Nota acerca del número del color.
Para establecer un color por medio de código, se pondrá un valor de color a la propiedad
correspondiente de ese objeto. El valor del color puede establecerse de tres formas que se comentan a
continuación.
Colores en Visual Basic.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 90
Visual Basic acepta para especificar un color, tres procedimientos: Mediante el número de color,
mediante la sentencia RGB ( rojo, verde, azul ) o mediante la función QBColor.
Por número
El número que representa el color en VB está formado por la suma de la componente roja, la
componente verde y la componente azul. Podríamos verlo muy bien en numeración Hexadecimal:
Color = Hex XX YY ZZ
Donde ZZ es un número Hexadecimal que representa la cantidad del color rojo. El mínimo estaría en 0
(H00) y el máximo en 255 (HFF)
YY representaría la cantidad de color verde y XX la de color azul, ambos con los mismos límites
explicados para el rojo.
Por ejemplo:
el rojo puro sería:
el verde puro sería:
el azul puro sería:
Hex(0000FF) = 255
Hex(00FF00) = 652280
Hex(FF0000) = 16711680
Una mezcla de un poco de rojo (HB1), otro poco de verde (H56) y otro poco de azul (H1F) daría el
siguiente número:
Hex(1F56B1) = 2053809
El número de color puede estar comprendido entre 0 (correspondiente al negro) y el 16777215
(correspondiente al blanco. Observe que esa cantidad, 16.777.215 (FFFFFF en hexadecimal)
corresponde a los famosos 16 millones de colores de las tarjetas gráficas.
Si queremos poner el color de fondo a un control Label, usaremos la propiedad Backcolor. Si el Label se
llama Label1, pondríamos la instrucción
Label1.Backcolor = 12345678
Por la sentencia RGB
Se puede expresar el color, poniendo simplemente RGB (rojo, verde, azul), donde rojo es un número
entre 0 y 255 que indica la cantidad de color rojo que se aporta al color, verde un número comprendido
entre 0 y 255 indicando la cantidad de verde, y lo mismo para azul.
Esta es la forma mas sencilla de poner la propiedad color, y con la que mejor controlaremos el mismo.
Si queremos poner al Label anterior un color mediante la sentencia RGB, ejecutaríamos la sentencia :
Label1.Backcolor = RGB (128, 30, 100)
Mediante la Función QBColor (Obsoleta. Se introduce por motivos de com patibilidad)
Esta función se ha puesto en Visual Basic para compatibilidad con los colores que se usan en QuickBasic y Qbasic. Mediante esta función se obtienen solamente 16 colores.
Sintaxis
Objeto.QBColor(color)
El argumento color es un número entero entre 0 a 15, según la siguiente lista:
Número Color
Número Color
0
1
2
8
9
10
LSB
Negro
Azul
Verde
Gris
Azul claro
Verde claro
Visual Basic – Guía del Estudiante
Capítulo 1
Página 91
3
4
5
6
7
Aguamarina
Rojo
Fucsia
Amarillo
Blanco
11
12
13
14
15
Aguamarina claro
Rojo claro
Fucsia claro
Amarillo claro
Blanco brillante
Para el mismo Label anterior, usaríamos la sentencia :
Label1.Backcolor = QBColor (12)
Fin de la nota acerca del número del color
CUADRO DE DIALOGO MOSTRANDO IMPRESORAS
Nota: Si utiliza un CommonDialog para impresoras y otras aplicaciones, puede tener problemas. Utilice
un Com mon Dialog exclusivamente para impresoras .
Para presentar el cuadro de elección de impresora, ejecute la instrucción:
CD2.ShowPrinter
(A este cuadro de dialogo le hemos llamado CD2 para evitar los problemas referidos en la nota).
Aparecerá el siguiente cuadro de diálogo:
La impresora elegida puede conocerla llamando a la propiedad DeviceName de un objeto que aún no
hemos visto: el objeto Printer. Este objeto es el encargado de pasar al Administrador de Impresión todos
los trabajos de impresión que generen las aplicaciones Visual Basic:
Nombredelaimpresora = Printer.DeviceName
Para que la impresora quede como impresora por defecto de Windows, debe tener a True la propiedad
PrinterDefault del cuadro de diálogo.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 92
El cuadro mostrado para la impresora dependerá de la impresora que tenga instalada en su ordenador,
por lo puede observar diferencias respecto a la figura mostrada anteriormente.
Programa Ejemplo. Muestra el cuadro de dialogo de impresoras
Private Sub BImpresora_Click()
CD1.ShowPrinter
End Sub
EL COMMONDIALOG PARA ABRIR Y GUARDAR ARCHIVOS
Posiblemente las opciones mas usadas del cuadro de diálogo. Para presentar el cuadro de diálogo
correspondiente a Abrir Archivo, debe ejecutar la instrucción:
CD1.ShowOpen
Si lo que necesita es abrir el cuadro de diálogo para guardar un fichero, debe ejecutar la instrucción :
CD1.ShowSave
pero antes deberá introducir el filtro o filtros de archivos que necesite. Ojo, ¡ ANTES !
Un filtro sirve para que en el cuadro de diálogo se presenten solamente los ficheros de nuestro interés.
Se pueden seleccionar por el nombre, la extensión o las dos cosas. La sintaxis para introducir un filtro es
la siguiente:
CD1.Filter = "Descripción del fichero|nombre.extensión"
donde "nombre" puede ser un nombre o usar caracteres comodín. Lo mismo para "extensión"
Por ejemplo, para buscar archivos ejecutables, con cualquier nombre y extensión .EXE
CD1.Filter = "Ficheros ejecutables |*.exe"
Observe el carácter separador entre la descripción de los ficheros (Ficheros ejecutables) y el parámetro
de busca (*.EXE). No ponga ningún espacio entre el separador y los caracteres de busca. El separador
es el carácter ASCII 124.
Puede buscar varios tipos de ficheros, separando los caracteres de busca por medio del carácter punto y
coma (;)
CD1.Filter = "Ficheros ejecutables |*.EXE;*.COM;*.BAT"
Puede también introducir dos filtros, separados por el separador | (En una línea solamente).
CD1.Filter=”Ficheros de un tipo |*.EXE |Ficheros de otro |*.COM |Otros ficheros |*.BAT”
Por ejemplo :
CD1.Filter = "Ficheros Word |*.DOC|Ficheros Write |*.WRI"
¡ No s e pu eden po ner d os líneas c on filtr os , se qu edaría so lamen te co n la últim a !
En este caso, cuando se presente el cuadro de diálogo, solamente presentará uno de los filtros, y deberá
seleccionar manualmente el otro en un cuadro situado en la parte inferior izquierda del cuadro de
diálogo. Para predeterminar cuál de los dos filtros saldrá sin tener que seleccionarlo, deberá ejecutar
esta instrucción, ANTES de invocar el cuadro de diálogo
CD1.FilterIndex = 2
En este caso, aparecerá por defecto el filtro escrito en segundo lugar. El orden de los filtros comienza
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 93
por 1.
El cuadro de diálogo deberá presentar un directorio. Este directorio con el que, por defecto, aparece el
cuadro de diálogo, se puede introducir mediante la propiedad InitDir, que deberá contener el nombre del
directorio y su path. Si no se especifica, comenzará por el directorio actual.
Para conocer el nombre del fichero elegido, se emplea la propiedad FileName :
Nombrefichero= CD1.filename
El nombre del fichero, Nombrefichero en la sentencia anterior, viene con su path, es decir, nombre y
dirección completa, por lo que puede emplearse directamente la salida del CommonDialog para abrir un
fichero.
El cuadro de diálogo de abrir o cerrar tiene esta forma :
El cuadro de guardar es similar. Observe que en este caso hemos desplegado la segunda opción de
filtro de ficheros :
Como ve ambos cuadros son prácticamente iguales. Solamente se difieren en que uno pone Abrir y el
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 94
otro Guardar como en su barra de título. También en que el cuadro Guardar como presenta los
nombres de los ficheros con un tono apagado. Funcionalmente difieren. Por ejemplo, si quiere guardar
un fichero con un nombre ya existente, y dependiendo de la propiedad Flags que verá mas adelante, le
aparecerá la siguiente advertencia :
Si desea otra leyenda en la barra de título, puede cambiarla usando el asistente de propiedades, que lo
obtendrá colocando el cursor del ratón sobre el icono del CommonDialog y pulsando el botón derecho.
Haga click sobre Propiedades en el popmenú que se presenta. Aparecerá esto :
PRESENTAR AYUDAS
Mediante el CommonDialog se puede presentar un fichero de ayuda. (Ficheros del tipo .HLP de
Windows)
Pese a que se pueden present ar estos fich eros basándo nos en el Comm onDialog , es preferible
usar directament e el prog rama WinHelp.Exe, que pu ede ejecutarlo m ediante la func ión Shell :
VariableID = Shell (“WinHelp.Exe FicheroAyuda.hlp”,1)
Para mostrar el fichero de ayuda debe poner el nombre (y Path) del fichero de ayuda en la propiedad
HelpFile del CommonDialog
CD1.HelpFile = "C:\MiCarpeta\MiFicheroAyuda.HLP"
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 95
Puede mostrar el índice, o una página concreta de ese fichero. Para ello debe jugar con la propiedad
HelpCommand, que le va a indicar al CommonDialog qué ayuda debe mostrar.
CD1.HelpCommand =Valor
Las opciones para valor son:
1
2
3
3
4
5
5
8
9
257
258
261
&H1 cdlContext
Muestra la Ayuda de un contexto determinado. Cuando se usa esta valor, también se debe
especificar un contexto con la propiedad HelpContext.
&H2 cdlQuit
Notifica a la aplicación Ayuda que el archivo de Ayuda especificado ya no se está utilizando.
&H3 cdlContents
Muestra el tema de contenido de ayuda, definido con la opción Contents de la sección
[OPTION] del archivo .HPJ.
&H3 cdlIndex
Muestra el índice del archivo de Ayuda especificado. Las aplicaciones sólo deben utilizar este
valor para un archivo de Ayuda con índice único.
&H4 cdlHelpOnHelp
Muestra la Ayuda para utilizar la propia aplicación Ayuda.
&H5 cdlSetContents
Determina el tema de contenido a mostrar cuando el usuario presiona la tecla F1.
&H5 cdlSetIndex
Establece el contexto especificado en la propiedad HelpContext como índice actual para el
archivo especificado en la propiedad HelpFile. Este índice seguirá siendo el actual hasta que el
usuario acceda a un archivo de Ayuda distinto. Utilice este valor sólo para los archivos de Ayuda
con más de un índice.
&H8 cdlContextPopup
Muestra en una ventana emergente un tema de Ayuda determinado, identificado por un número
de contexto definido en la sección [MAP] del archivo .HPJ.
&H9 cdlForceFile
Asegura que WinHelp muestre el archivo de Ayuda correcto. Si se muestra el archivo correcto,
no sucede nada. Si se muestra un archivo incorrecto, WinHelp abrirá el correcto.
&H101 cdlKey
Muestra la Ayuda sobre una palabra reservada determinada. Al usar esta opción, deberá
especificar también una palabra reservada con la propiedad HelpKey.
&H102 cdlCommand
Ejecuta una macro de Ayuda.
&H105 cdlPartialKey
Muestra el tema de la lista de palabras claves que coincide con la palabra pasada en el
parámetro dwData, si sólo se encuentra uno. Si se encuentra más de uno, aparecerá el cuadro
de diálogo Buscar mostrando los temas encontrados en el cuadro de lista Ir a. Si no se
encuentra ninguno, se mostrará el cuadro de diálogo Buscar. Para que aparezca el cuadro de
diálogo Buscar sin pasar una palabra reservada, utilice un puntero largo a una cadena vacía.
Si queremos que se muestre el índice de la ayuda, pondríamos esta propiedad de la forma :
CD1.HelpCommand = cdlHelpIndex
Para mostrar la página que se ha puesto en el fichero de ayuda como Contexto 2 (En Sección [MAP] del
fichero .HPJ (Vea Creación de Ficheros de Ayuda),
CD1.HelpCommand = cdlHelpContext
CD1.HelpContext = 2
Para mostrar la Ayuda de la Ayuda de Windows :
CD1.HelpCommand = cdlHelpHelpOnHelp
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 96
Una vez establecidas estas propiedades, mostraremos la ayuda con el Método ShowHelp
CD1.ShowHelp
Repitiéndole que no se debe usar el CommonDialog para mostrar ayudas, pero para cumplir el objetivo
de plasmar en este texto la mayor información acerca de cada control, se enumeran a continuación el
resto de propiedades que afectan a la presentación de ayuda :
HelpFile
HelpContext
HelpKey
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 97
PROPIEDADES DEL CommonDialog
La Propiedad Action
La propiedad Action se incluye en la versión 4 de VB solamente por motivos de compatibilidad con
anteriores versiones. Realiza las mismas funciones que ShowFont, ShowColor, ShowPrinter,
ShowOpen y ShowSave. No debe usarse esta propiedad, sino los equivalentes citados, en previsión de
que pueda ser eliminada en futuras versiones.
La sintaxis de Action es :
Nombre.Action [= valor]
Valor
Descripción
0
1
2
3
4
5
6
Ninguna acción.
Muestra el cuadro de diálogo Abrir.
Muestra el cuadro de diálogo Guardar como.
Muestra el cuadro de diálogo Color.
Muestra el cuadro de diálogo Fuente.
Muestra el cuadro de diálogo Impresora.
Ejecuta WINHELP.EXE.
NO utilice la propiedad Action. Utilice en su lugar ShowFont, ShowPrinter, ShowSave, ShowOpen ,
ShowColor y ShowHelp
CancelError
Devuelve o establece un valor que indica si se genera un error cuando el usuario elige el botón
Cancelar.
Sintaxis :
True
False
objeto.CancelError = (True / False)
Se genera un error.
(Predeterminado) No se genera ningún error.
Cuando se establece True en esta propiedad, se producirá el error número 32755 (cdlCancel)
cada vez que el usuario elija el botón Cancelar.
Debe poner esta propiedad a true cuando quiera detectar que se ha pulsado el botón
CANCELAR. Luego, debe detectar con la rutina de detección de errores adecuada, si el error
producido ha sido el 32755. De ser así, es que han pulsado ese botón, y Vd. procederá en
consecuencia.
Color
Esta propiedad es de lectura / escritura
De escritura :Establece el color predeterminado con que aparecerá el CD para elegir
color. Puede introducirse como RGB o numéricamente, como se explicó mas atrás. Para que
aparezca este color predeterminado, debe poner la propiedad Flags a 1.
De lectura : Entrega el color elegido, bien en el cuadro de elección de color, bien en el
cuadro de elección de fuente.
Copies
Establece el valor predeterminado para número de copias que aparecerá en el CD cuando se
abra para elegir impresora.
DefaultExt
Devuelve o establece la extensión de archivo predeterminada para el cuadro de diálogo.
Sintaxis
LSB
objeto.DefaultExt [= cadena]
Visual Basic – Guía del Estudiante
Capítulo 1
Página 98
Puede utilizar esta propiedad para especificar una extensión de archivo predeterminada, como
por ejemplo .TXT o .DOC.
Important e para el Com mo nDialog de Guardar: Cuando se guarde un archivo sin extensión,
se le agregará automáticamente la especificada en esta propiedad.
DialogTitle
Devuelve o establece la cadena mostrada en la barra de título del cuadro de diálogo.
Sintaxis
Nombre.DialogTitle [= título]
Esta propiedad puede introducirse en la ventana de propiedades, o por programa. Puede utilizar
esa propiedad para mostrar el nombre del cuadro de diálogo en la barra de título.
Nota El control CommonDialog ignora el valor de la propiedad DialogTitle cuando muestra los
cuadros de diálogo Color o Fuente.
El título predeterminado para un cuadro de diálogo Abrir es Abrir, y para un cuadro de diálogo
Guardar como es Guardar como.
FileName
Devuelve o establece la ruta y el nombre de archivo de un archivo seleccionado. La lectura de
esta propiedad devuelve el nombre del archivo seleccionado actualmente en la lista. Si no hay
ningún archivo seleccionado, FileName devuelve una cadena vacía.
Filter
(Explicada mas atrás)
Devuelve o establece los filtros que aparecen en el cuadro de lista Tipo de un cuadro de diálogo.
Sintaxis
CD1.Filter [= descripción1 |filtro1 |descripción2 |filtro2...]
Utilice el símbolo de canalización ( | , (ASCII 124) ) para separar los valores de descripción y de
filtro. No incluya espacios antes ni después del símbolo de canalización, pues aparecerían en los
valores de descripción y valor.
Al especificar más de un filtro en un cuadro de diálogo, utilice la propiedad FilterIndex para
especificar el filtro predeterminado.
Nota para los que no tiene teclado de 102 teclas. Para obtener el carácter ASCII 124, pulse la tecla ALT
y, sin dejar de pulsarla, teclee 124 en el teclado numérico.
FilterIndex
Devuelve o establece un filtro predeterminado para un cuadro de diálogo Abrir o Guardar Como.
Sintaxis
CD1.FilterIndex [= número]
Esta propiedad indica el filtro predeterminado cuando se han especificado varios filtros para un
cuadro de diálogo Abrir o Guardar. El índice del primer filtro definido es 1.
Flags Propiedad que tiene distintos significados para cada tipo de cuadro de diálogo.
Tiene la misma sintaxis para todos los cuadros.
Sintaxis
CD1.Flags [= valor]
El parámetro valor establece distintas alternativas, dependiendo de cada cuadro.
Para el cuad ro d e diálog o Co lor
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 99
Las opciones para valor son:
1
&H1& cdlRGBInit
Establece como valor de color inicial para el cuadro de diálogo el indicado en su propiedad
Color.
2
&H2& cdlFullOpen
Hace que el cuadro de diálogo se muestre completo al crearlo, incluyendo la sección que
permite al usuario crear colores personalizados. Sin esta opción, el usuario debe elegir el botón
de comando Definir colores personalizados para mostrar tal sección.
4
&H4& cdlPreventFullOpen
Desactiva el botón de comando Definir colores personalizados, evitando que el usuario defina
colores.
8
&H8& cdlShowHelp
Hace que el cuadro de diálogo muestre un botón Ayuda.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de
cada una de las condiciones a poner.
Para los cuadros Abrir y Guardar
Las opciones para valor son:
1
2
4
8
16
256
512
1024
2048
4096
LSB
&H1& cdlReadOnly
Hace que la casilla de verificación Sólo lectura aparezca marcada inicialmente al crear el cuadro
de diálogo. Este indicador también señala el estado de la casilla Sólo lectura cuando el cuadro
de diálogo está cerrado.
&H2& cdlOverwritePrompt
Hace que el cuadro de diálogo Guardar como genere un cuadro de mensaje si el archivo
seleccionado ya existe. El usuario deberá confirmar que desea sobrescribir el archivo.
&H4& cdlHideReadOnly
Oculta la casilla de verificación Sólo lectura.
&H8& cdlNoChangeDir
Hace que el cuadro de diálogo restablezca como directorio actual el que lo era en el momento de
abrirse.
&H10& cdlShowHelp
Hace que el cuadro de diálogo muestre el botón Ayuda.
&H100&
cdlNoValidate
Especifica que el cuadro de diálogo común permita caracteres no válidos en el nombre de
archivo devuelto. Funciona tanto con el cuadro de Abrir como con el de Cerrar. Tenga cuidado a
la hora de crear un archivo con nombre no válido !
&H200&
cdlAllowMultiselect
Especifica que el cuadro de lista Nombre de archivo admita selecciones múltiples. El usuario
puede seleccionar más de un archivo en tiempo de ejecución presionando la tecla MAYÚS y
utilizando las teclas FLECHA ARRIBA y FLECHA ABAJO para seleccionar los archivos
deseados. Al hacerlo, la propiedad FileName devolverá una cadena con los nombres de todos
los archivos seleccionados. Los nombres están delimitados en la cadena con espacios.
&H400&
cdlExtensionDifferent
Indica que la extensión del nombre de archivo devuelto es distinta de la especificada en la
propiedad DefaultExt. Este indicador no estará activado si la propiedad DefaultExt es Null, si las
extensiones coinciden, o si el archivo no tiene extensión. El valor de este indicador puede
comprobarse al cerrar el cuadro de diálogo.
&H800&
cdlPathMustExist
Especifica que el usuario sólo pueda introducir una ruta de acceso válida. Si se establece este
indicador y el usuario introduce una ruta no válida, aparecerá un mensaje de advertencia.
&H1000&
cdlFileMustExist
Visual Basic – Guía del Estudiante
Capítulo 1
Página 100
Especifica, para el cuadro de Abrir, que el usuario sólo pueda escribir en el cuadro de texto
Nombre de archivo nombres de archivos existentes. Si este indicador está activado y el usuario
introduce un nombre de archivo no válido, aparecerá una advertencia. Este indicador activa
automáticamente cdlPathMustExist.
8192 &H2000&
cdlCreatePrompt
Especifica, para el cuadro de diálogo de abrir, que si no existe el fichero consulte al usuario
antes de crear un archivo que no existe actualmente. Esta advertencia dice : Este Archivo no
existe ¿desea crearlo ? y aparecen los botones de ACEPTAR y CANCELAR. Si el usuario pulsa
aceptar el CommonDialog se cierra normalmente, si se le pulsa CANCELAR desaparece esta
advertencia y el CommonDialog espera a que se le escriba o seleccione otro fichero. Este
indicador establece automáticamente los indicadores cdlPathMustExist y cdlFileMustExist.
16384 &H4000&
cdlShareAware
Especifica que se ignoren los errores al compartir archivos.
32768 &H8000&
cdlNoReadOnlyReturn
Especifica que el archivo devuelto no tenga el atributo de Sólo lectura ni esté en un directorio
protegido contra escritura. Presenta un aviso (tanto en el cuadro de abrir como en el cerrar) que
impide elegir un fichero de estas características.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de
cada una de las condiciones a poner.
Para el cuadro Mostrar Fuentes:
Las opciones para valor son:
1
2
3
4
256
1024
2048
&H1& cdlScreenFonts
Hace que el cuadro de diálogo muestre solamente las fuentes de pantalla que admite el sistema.
&H2& cdlPrinterFonts
Hace que el cuadro de diálogo muestre solamente las fuentes que admite la impresora,
especificadas por la propiedad hDC.
&H3& cdlBoth
Hace que el cuadro de diálogo muestre las fuentes de impresora y de pantalla disponibles. La
propiedad hDC identifica el contexto de dispositivo asociado a la impresora
&H4& cdlShowHelp
Hace que el cuadro de diálogo muestre un botón Ayuda.
&H100&
cdlEffects
Especifica que el cuadro de diálogo permita efectos de tachado, subrayado y color.
&H400&
cdlANSIOnly
Especifica que el cuadro de diálogo sólo permita seleccionar las fuentes que utilizan el juego de
caracteres de Windows. Si se establece este indicador, el usuario no podrá seleccionar una
fuente que sólo contenga símbolos.
&H800&
cdlNoVectorFonts
Especifica que el cuadro de diálogo no permita seleccionar fuentes vectoriales.
4096
&H1000&
cdlNoSimulations
Especifica que el cuadro de diálogo no permita simulaciones de fuente de interfaz de dispositivo
gráfico (GDI).
8192
&H2000&
cdlLimitSize
Especifica que el cuadro de diálogo seleccione sólo los tamaños de fuente comprendidos en el
rango especificado por las propiedades Min y Max.
16384 &H4000&
cdlFixedPitchOnly
Especifica que el cuadro de diálogo seleccione sólo fuentes de espaciado fijo.
32768 &H8000&
cdlWYSIWYG
Especifica que el cuadro de diálogo permita seleccionar solamente fuentes disponibles al la vez
en la pantalla y en la impresora. Si se establece este indicador, también deben establecerse
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 101
cdlBoth (sume 3 a este número) y cdlScalableOnly (sume 131072 a este número)
65536 &H10000&
cdlForceFontExist
Especifica que aparezca un cuadro de mensaje cuando el usuario intente seleccionar una fuente
o un estilo que no existan.
131072 &H20000&
cdlScalableOnly
Especifica que el cuadro de diálogo permita seleccionar solamente fuentes escalables.
262144 &H40000&
cdlTTOnly
Especifica que el cuadro de diálogo permita seleccionar solamente fuentes TrueType.
Nota Antes de mostrar el cuadro de diálogo Fuentes, debe establecer cdlScreenFonts,
cdlPrinterFonts o cdlBoth en la propiedad Flags. En caso contrario, se producirá el error No hay fuentes.
(O dicho de otra forma, Flags=1, 2 ó 3)
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de
cada una de las condiciones a poner.
Para el Cuadro de Diálogo Imprimir
(Observará seguramente que lo que se describe a continuación no se cumple siempre. Depende de las
impresoras que tenga Vd. instaladas)
Las opciones para valor son:
0
1
2
4
8
16
32
64
128
&H0& cdlAllPages
Devuelve o establece el estado del botón de opción Todas las páginas.
&H1& cdlSelection
Devuelve o establece el estado del botón de opción Selección. Si no se especifica
cdlPageNums ni cdlSelection, el botón de opción Todas estará seleccionado.
&H2& cdlPageNums
Devuelve o establece el estado del botón de opción Páginas.
&H4& cdlNoSelection
Desactiva el botón de opción Selección.
&H8& cdlNoPageNums
Desactiva el botón de opción Páginas y el control de edición asociado.
&H10& cdlCollate
Devuelve o establece el estado de la casilla de verificación Intercalar.
&H20& cdlPrintToFile
Devuelve o establece el estado de la casilla de verificación Imprimir a un archivo.
&H40& cdlPrintSetup
Hace que el sistema muestre el cuadro de diálogo Configurar impresora en lugar de
Imprimir. Use este Flag cuando lo que desea es cambiar la impresora predeterminada.
&H80& cdlNoWarning
Evita que aparezca una advertencia cuando no hay una impresora predeterminada.
256
&H100&
cdlReturnDC
Devuelve un contexto de dispositivo para la impresora seleccionada en el cuadro de
diálogo. El contexto se devuelve en la propiedad hDC del cuadro de diálogo.
512
&H200&
cdlReturnIC
Devuelve un contexto de información para la impresora seleccionada en el cuadro de
diálogo. Un contexto de información proporciona un método rápido de obtener
información sobre el dispositivo sin crear un contexto de dispositivo. El contexto de
información se devuelve en la propiedad hDC del cuadro de diálogo.
2048 &H800&
cdlShowHelp
Hace que el cuadro de diálogo muestre el botón Ayuda
262144
&H40000&
cdlUseDevModeCopies
Si un controlador de impresora no admite copias múltiples, al establecer este indicador
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 102
se desactiva el control de edición de número de copias. Si el controlador sí admite
múltiples copias, al establecer este indicador el cuadro de diálogo almacenará el número
de copias solicitado en la propiedad Copies.
524288
1048576
&H80000&
cdlDisablePrintToFile
Desactiva la casilla de verificación Imprimir a un archivo.
&H100000&
cdlHidePrintToFile
Oculta la casilla de verificación Imprimir a un archivo.
Propiedades que afectan al tipo de letra.
Las seis propiedades siguientes nos dan las características especiales de la fuente elegida (negrita,
cursiva, etc.). Una vez seleccionado el tipo de letra, el valor de estas propiedades contiene la opción
elegida para la letra (si FontBold=True es que hemos elegido negrita, etc.)
FontBold
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Negrita.
Sintaxis
Variable = CD1.FontBold
Los valores de Variable son:
True
Se ha elegido negrita
False (Predeterminado) No se ha elegido negrita.
FontItalic
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Cursiva.
Sintaxis
Variable = CD1. FontItalic
Los valores de Variable son:
True si se ha elegido cursiva, False (Predeterminado) en caso contrario.
FontStrikethru
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Tachada.
Sintaxis
Variable = CD1. FontStrikethru
Los valores de Variable son:
True si se ha elegido tachado, False (Predeterminado) en caso contrario.
FontUnderline
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Subrayado.
Sintaxis
Variable = CD1.FontUnderline
Los valores de Variable son:
True, si se ha elegido subrayado, False (Predeterminado) en caso contrario
FontName
Devuelve el nombre de la fuente elegida. Es una variable tipo String
Sintaxis
LSB
Variable = CD1.FontName
Visual Basic – Guía del Estudiante
Capítulo 1
Página 103
(Variable toma el valor del nombre de la fuente. Por ejemplo, Variable = “Arial”
En general, deberá modificar FontName antes de establecer los atributos de tamaño y estilo con
las propiedades FontSize, FontBold, FontItalic, FontStrikethru y FontUnderline.
Nota En tiempo de ejecución puede obtener información sobre las fuentes disponibles a través
de las propiedades FontCount y Fonts. Lo verá mas adelante
FontSize
Devuelve de la fuente elegida. Debe ser una variable tipo Integer o Long
Sintaxis
Variable = CD1.FontSize
donde Variable será una expresión numérica que especifica el tamaño de fuente a utilizar, en
puntos.
Nota Las fuentes disponibles en Visual Basic varían dependiendo de la configuración del
sistema y de los dispositivos de presentación e impresión. En las propiedades relacionadas con
las fuentes sólo pueden establecerse valores para los que exista una fuente.
En general, deberá modificar FontName antes de establecer los atributos de tamaño y estilo con
las propiedades FontSize, FontBold, FontItalic, FontStrikethru y FontUnderline. Sin
embargo, cuando especifique un tamaño inferior a 8 puntos para una fuente TrueType, primero
deberá establecer el tamaño en puntos con la propiedad FontSize, luego especificar la
propiedad FontName y después establecer de nuevo el tamaño con FontSize. El entorno
operativo Microsoft Windows utiliza una fuente distinta para las fuentes TrueType con un
tamaño inferior a 8 puntos.
Index
Igual que el ya estudiado para otros controles.
InitDir
Devuelve o establece el directorio de archivos inicial.
Sintaxis
objeto.InitDir [= cadena]
La sintaxis de la propiedad InitDir consta de las siguientes partes:
objeto Nombre que define al CommonDialog
cadena Expresión de cadena que especifica el directorio de archivos inicial.
Si no se especifica esta propiedad, se utilizará el directorio actual.
Left y Top
Estas propiedades solamente afectan a la colocación del icono en el formulario. No afectan a la
colocación del CommonDialog durante la ejecución. La posición del CommonDialog en tiempo
de ejecución no puede controlarse.
Esta afirmación de que la posición del CommonDialog no es controlable es válida para
sistemas a 32 bytes. En VB 4 de 16 bits, el CommonDialog aparece aproximadamente en la
parte superior izquierda del formulario que lo contiene. Algunos programadores han optado por
poner un formulario para contener solamente al CommonDialog, y así, controlando la posición de
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 104
ese formulario, poder controlar la posición (aproximada) en la que aparece el CD.
Esto no ocurre para sistemas a 32 bytes, en los que el CD aparece siempre en la parte superior
izquierda de la pantalla, independientemente de donde esté el formulario que lo contiene.
MaxFileSize
Devuelve o establece el tamaño máximo del nombre de archivo abierto con el control
CommonDialog.
Sintaxis
objeto.MaxFileSize [= valor]
La sintaxis de la propiedad MaxFileSize consta de las siguientes partes:
objeto = Nombre que define al CommonDialog
valor = Número entero que especifica el tamaño máximo del nombre de archivo en bytes. El
rango de esta propiedad es 132KB. El valor predeterminado es 256.
Name
Nombre que define al CommonDialog
PrinterDefault
Devuelve o establece una opción que determina si la configuración elegida por el usuario en el
cuadro de diálogo Imprimir se utiliza para modificar la configuración predeterminada de
impresora del sistema.
Sintaxis
CD1.PrinterDefault = True / False
True Las opciones que elija el usuario en el apartado Configurar del cuadro de diálogo
Imprimir (selección de la impresora, orientación, etcétera) se utilizan para modificar la
configuración de impresora almacenada en el Registro).
False Las opciones que elija el usuario no se utilizan para modificar la configuración de
impresora predeterminada del sistema.
Utilice esta propiedad, que por defecto está a True, para poner o no poner como impresora
predeterminada, la impresora seleccionada con el CommonDialog. Puede por ejemplo, querer
imprimir un texto en una impresora determinada, pero solo ese texto, y no quiere cambiar la
impresora predeterminada por el hecho de haber seleccionado en este momento otra impresora.
Ponga esta propiedad a False (recuerde que por defecto está a True) para que la impresora
seleccionada no se quede como impresora por defecto.
Tag
Lo mismo que se ha explicado para otros controles.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 105
CONTROLES DE BUSQUEDA DE FICHEROS
CONTROLES DE BUSQUEDA DE FICHEROS Y DIRECTORIOS
Estos controles apenas si se usan. La razón es que el CommonDialog ya estudiado sustituye con creces
a estos tres controles en su conjunto. Sin embargo, para determinadas necesidades sí son muy
prácticos. Estúdieselos con el mismo entusiasmo que si no existiese el CommonDialog.
Al tratarse de controles tipo Lista, le recomiendo que lea el capítulo correspondiente al ListBox.
Le aclarará sobre todo los términos empleados para definir los elementos de la lista, que en este
caso, son los ficheros de una carpeta, las carpetas de un disco o los discos visibles desde la
máquina.

DriveListBox, DirListBox Y FileListBox.
Se obtienen directamente de la Caja de Herramientas, en los iconos siguientes:



DriveListBox permite elegir una unidad de disco.
DirListBox muestra los directorios existentes en un árbol.
FileListBox muestra los ficheros existentes en un determinado directorio.
Tal como indica su nombre, estos controles son listas. Repase el control ListBox para recordar sus
propiedades.
DriveListBox
Este control permite elegir una unidad de disco válida en tiempo de ejecución. Utilice este control para
mostrar una lista de todas las unidades válidas del sistema de un usuario. Puede crear cuadros de
diálogo que permitan al usuario abrir un archivo de una lista en cualquier unidad disponible.
DriveListBox desplegado y sin desplegar Name (nombre) por defecto List1
Posee las propiedades típicas de cualquier control VB respecto a su geometría y color. Las propiedades
mas destacables de este control son : Drive, List, ListCount y ListIndex
Drive devuelve el nombre de la unidad de disco seleccionada :
Variable = List1.Drive
Variable = a :
(ó c :[MS-DOS_6] ó D )
Este control se trata de una lista como su nombre indica, y posee las propiedades List, ListCount y
ListIndex para permitir al usuario tener acceso a elementos de la lista.
List (n) devuelve el texto que define a la unidad colocada en el lugar n. El número n comienza por 0. Por
ejemplo, en la figura anterior, List1.list(1) devolverá c :[MS-DOS_6]
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 106
ListCount proporciona información acerca del número de unidades de disco disponibles (En el ejemplo,
List1.ListCount será 3, que corresponde a los tres discos disponibles - disco C :, disco A : y disco D : )
ListIndex devuelve el índice del disco seleccionado en la lista (0 para el primero, n-1 para el último)
Utilizando el control DriveListBox en combinación con DirListBox y FileListBox, podrá realizar un
explorador de ficheros en cualquier disco de su ordenador.
DirListBox.
Presenta un cuadro de la siguiente forma:
donde puede verse el árbol completo de un directorio. El DirListBox solamente presenta directorios. No
presenta ficheros.
Aparte de las propiedades geométricas de todos los controles, el DirListBox presentas las siguientes
propiedades particulares :
Path
Devuelve o establece la ruta de acceso actual. No está disponible en tiempo de diseño.
Sintaxis
Nombre.Path [= pathname]
donde
Nombre
es el nombre del DirListBox
pathname Una expresión de cadena que evalúa en el nombre de vía de acceso del directorio por
defecto del DirListBox..
El valor de la propiedad Path es una cadena que indica una ruta de acceso, como
C:\WINDOWS\SYSTEM. El valor predeterminado es la ruta de acceso actual
Cuando se cambia la propiedad Path en tiempo de ejecución se genera un evento Change.
Nota El valor que devuelve Path es distinto del de List (ListIndex). Path devuelve siempre un mismo
camino, bien el que se le haya impuesto mediante esta misma propiedad Path, y si no se le ha impuesto
con anterioridad, el que tenga por defecto. List (ListIndex) devuelve el camino completo del directorio
seleccionado, y, como era de esperar, cambia cada vez que cambiamos la selección del directorio.
List, ListCount y ListIndex
Al igual que cualquier lista, el DirListBox tiene las propiedades List, ListCount y ListIndex.
ListIndex devuelve el valor del índice del directorio seleccionado. El valor devuelto es cero cuando está
seleccionado el primer directorio de los situados al final del árbol, 1 para el siguiente, etc. Toma el valor
-1 cuando se selecciona el directorio inmediatamente superior al último nivel, el valor -2 cuando se
selecciona el directorio situado 2 niveles jerárquicos por encima del último nivel, etc.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 107
ListCount devuelve un valor numérico igual al número de directorios existentes en el último nivel,
independientemente de los directorios que tuviesen por arriba.
List (n) devuelve una cadena de caracteres con el camino completo del elemento cuyo orden sea el
señalado entre paréntesis. Si en vez de n colocamos el ListIndex nos devolverá, logicamente, el camino
del elemento seleccionado.
FileListBox
Esta lista nos presenta los ficheros existentes en un directorio.
Como se puede apreciar, cuando el número de ficheros supera el número que puede presentar,
aparecen automáticamente las flechas de scroll verticales.
Esta lista de ficheros tiene las siguientes propiedades destacables :
Path
Devuelve o establece la ruta de acceso de su directorio actual. No está disponible en tiempo de diseño.
Este directorio puede ser el que se le haya impuesto mediante esta propiedad Path, o el que tenga por
defecto. (El directorio por defecto sería el del ejecutable de la aplicación)
Si le ponemos el nombre por defecto, List1, para todos los ejemplos :
variable = List1.Path
Variable = C:\Archivos de programa\Microsoft Visual Basic32
(p. e.)
ListCount
Devuelve el número total de ficheros que hay en ese directorio.
Variable = List1.ListCountVariable = 19
(p. e.)
ListIndex
Devuelve un número con el índice del elemento seleccionado. Como todas las listas, devuelve -1 si no
hay ningún elemento seleccionado. El primer elemento de una lista tiene el índice = 0.
Filename
Devuelve el nombre del fichero seleccionado.
List (n)
Devuelve el nombre del fichero que ocupa el lugar n en la lista.
Variable = List1.List (5)
Variable = nombre del fichero que ocupa el 5º lugar en la lista.
Si en lugar de n ponemos el valor de ListIndex :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 108
variable = List1.List (List1.ListIndex)
obtendremos el nombre del fichero seleccionado.
Observe que en este último caso, el resultado es el mismo que el de List1.Filename
Veamos otras propiedades del FileListBox
Pattern
Devuelve o establece un valor que indica los nombres de archivo mostrados en un control
FileListBox en tiempo de ejecución.
Sintaxis
objeto.Pattern [= valor]
La sintaxis de la propiedad Pattern consta de las siguientes partes:
objeto : Nombre del Control FileListBox
valor: Expresión de cadena que indica una especificación de archivo, como *.* o *.FRM. La cadena
predeterminada es *.*, que obtiene una lista de todos los archivos. Además de utilizar caracteres
comodín, también puede especificar varios modelos, separándolos
con caracteres punto y coma
(;). Por ejemplo, con *.EXE; *.BAT se obtendría una lista con todos los archivos ejecutables y todos los
archivos por lotes de MS-DOS.
Comentarios
La propiedad Pattern juega un papel clave en el diseño de las funciones de examen y tratamiento de
archivos de una aplicación. Puede utilizar Pattern en combinación con otras propiedades de control de
archivos para proporcionar al usuario formas de explorar archivos o grupos de archivos similares. Por
ejemplo, en una aplicación dedicada a iniciar otros programas, podría hacer que sólo apareciesen los
archivos .EXE en el cuadro de lista de archivos (*.EXE).
Al modificar el valor de la propiedad Pattern se genera un evento PatternChange.
Archive, Hidden, Normal, System
Devuelven o establecen un valor que determina si un control FileListBox presenta los archivos con los
atributos Archive, Hidden, Normal o System.
El atributo Archive de un fichero indica si se ha variado ese fichero después de la última copia de
seguridad.
El atributo Hidden indica si el fichero se trata de un fichero oculto.
El atributo Normal indica que el fichero es un fichero “normal” (No está oculto ni es de sistema).
El atributo System de un fichero indica que el fichero es un fichero de sistema.
Sintaxis
objeto.Archive [= booleano]
objeto.Hidden [= booleano]
objeto.Normal [= booleano]
objeto.System [= booleano]
Las sintaxis de la propiedades Archive, Hidden, Normal y System tiene la siguiente partes:
objeto :Nombre del FileListBox
booleano :Una expresión booleana (True / False) que especifica el tipo de archivos presentados.
El valor booleano puede presentar los siguientes valores :
True :(Predeterminado para Archive y Normal) Presenta archivos con el atributo de la propiedad en el
control FileListBox.
False : (Predeterminado para Hidden y System) Presenta archivos sin el atributo de la propiedad en el
control FileListBox.
Use estas propiedades para especificar el tipo de archivos a presentar en un control FileListBox,
basándose en los atributos de archivos estándar usados en el entorno operativo. La definición de estas
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 109
propiedades en el código en tiempo de ejecución hace que el control FileListBox presente sólo aquellos
archivos con los atributos especificados.
Por ejemplo, en una operación de buscar y reemplazar se podrían presentar solamente archivos del
sistema estableciendo la propiedad System a True y las demás propiedades a False. También, como
parte del procedimiento de copia de seguridad, se podría establecer la propiedad Archive a True para
relacionar solamente aquellos archivos modificados a partir de la última copia de seguridad.
PROCEDIMIENTOS del FileListBox
Click
KeyDown
Change
KeyPress
DragDrop
KeyUp
DragOver
GotFocus
SENTENCIAS DE MANEJO DE DIRECTORIOS Y FICHEROS
El Directorio Actual
Se llama directorio Actual al directorio que está actualmente en uso, bien porque haya sido forzado el
control correspondiente a tener ese directorio en su propiedad Path, bien porque, al no haberse forzado
ninguno, utilice el directorio por defecto.
El directorio por defecto es el último que se ha seleccionado por algún procedimiento. Por ejemplo, al
arrancar una aplicación, el directorio por defecto será el mismo donde se encuentra el ejecutable. Pero si
a lo largo de la aplicación cambiamos el directorio, seleccionando otro mediante un CommonDialog, ese
directorio es el que queda por defecto. Asegúrese en sus aplicaciones que siempre elige la propiedad
Path antes de presentar ficheros o directorios a través de los controles anteriores, para evitar que pueda
mostrarle ficheros de un directorio no deseado.
Puede comprobar cual es el directorio actual. La función CurDir nos devuelve el directorio actual.
Ejemplo : Introduzca una línea de código con la siguiente sentencia
Variable = CurDir
Al ejecutarla la variable Variable contendrá la información :
Variable = C:\Archivos de programa\Microsoft Visual Basic32
(p. e.)
Puede darse el caso de que desee conocer el directorio actual de varias unidades de disco. Por ejemplo,
puede estar trabajando en el directorio C:\CursoVB\Ejemplos y ser este el directorio actual en el disco
C :, y tener un disquete en la unidad A : en el que la última vez que trabajó fue en el directorio
A :\ApVB\Tema1 y ese es su directorio por defecto en el disco A. Para conocer el directorio actual del
disco C : no necesitó especificar la unidad, ya que era precisamente la unidad C la unidad actual. Para
conocer el directorio actual de la unidad A emplearía la expresión :
Variable = CurDir (“A”)
Variable tomará entonces el valor Variable = “A :\ApVB\Tema1”
Decíamos que el disco C era la unidad actual. También podemos cambiar la unidad actual, mediante la
sentencia ChDrive seguida de una letra (entre comillas dobles)
Ejemplo
cambia la unidad actual a la unidad A. Observe que el
parámetro A no tiene que llevar los dos puntos ( : ), aunque si
lo desea, puede ponerlos. También es indiferente que la letra
sea mayúscula o minúscula.
ChDrive “A”
También podemos forzar a que un directorio sea el directorio por defecto. La sentencia que tendremos
que usar en ChDir.
Ejemplo : ChDir “C :\Windows\System” cambiaría el directorio actual al especificado.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 110
Podemos incluso crear un directorio. Usaremos para ello la sentencia MkDir. Esta sentencia crea el
directorio con el nombre indicado, sobre el directorio actual.
Si el directorio actual es el C:\VB\Icons y ejecutamos la sentencia :
MkDir “Varios”
crearíamos el directorio C:\VB\Icons\Varios
Podemos incluso eliminar un directorio. La sentencia para eliminar un directorio es RmDir
¡ Cuidado ! Visual-Basic no le advertirá que puede borrar algo que no desea. Asegúrese muy bien
mediante un aviso al usuario cada vez que elimine un directorio.
Vamos a ver ahora como podemos ver los nombres de los ficheros existentes en un determinado
directorio. Muy sencillo, con un FileListBox. Efectivamente, así podría ser para presentarlos en pantalla.
Sin embargo, si deseamos imprimir la lista de ficheros existentes, guardarla en un fichero, etc., tenemos
una forma que facilita esta labor. Igual que en DOS. La función Dir
A esta función le debemos añadir como parámetro el criterio de búsqueda, criterio formado por los
caracteres o comodines que deseemos. Dir devuelve solamente el nombre de un fichero, por lo que
tendremos que repetirla tantas veces como ficheros tenga el directorio. Pero solamente tendremos que
introducir el criterio de búsqueda la primera vez.
En el siguiente ejemplo, sacaremos por impresora los nombres de los ficheros existentes en el directorio
actual : (Este código lo meteremos en el procedimiento click de un botón de comando)
‘Le decimos que imprima todos (*.*)
fichero = Dir("*.*")
Do Until fichero = "" ‘Hasta que fichero sea una cadena de longitud cero..
Printer.Print fichero
‘Imprime la variable fichero en la impresora
‘Toma el nombre de otro fic hero
fichero = Dir
Loop
‘Vuelve a Do Until .....
Printer.EndDoc
‘Termina la impresión y saca la hoja de la impresora
Ya sabemos sacar el directorio. Vamos a ver que otras cosas se pueden hacer con ficheros.
Función Kill. A poco Inglés que sepa se habrá dado cuenta que esta función sirve para quitarse algo de
enmedio. Esta función borra un fichero del disco.
Kill “C:\CursoVB\Ejemplos\Ejemplo1.txt”
borra el fichero Ejemplo1.txt, que se encuentra en el disco C, directorio \ CursoVB\Ejemplos
Función FileCopy. Copia un fichero. La sintaxis de esta función es la siguiente :
FileCopy Origen, Destino
Si tenemos un TextBox llamado Text1 donde vamos a introducir el nombre (con su Path) del fichero
origen, otro TextBox donde introduciremos el nombre (con su Path) que queremos dar a la copia, para
copiar ese fichero ejecutaremos la sentencia :
FileCopy Text1.Text, Text2.Text
Si queremos copiar un fichero del disco A, en el directorio CursoVB y de nombre Ejemplo1 al disco y
directorio C:\CursoVB\Ejemplos y con el mismo nombre que tenía en el disco A, es decir, Ejemplo1,
ejecutaremos la sentencia :
FileCopy “A :\CursoVB\Ejemplo1” , “C:\CursoVB\Ejemplos\Ejemplo1”
Observe la necesidad de dobles comillas para especificar que es, precisamente lo escrito en el código, lo
que indica el origen y el destino. En el caso anterior no llevaba dobles comillas, debido a que era el
contenido de un TextBox lo que se usaba para indicar el origen y el destino.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 111
La instrucción Name cambia el nombre de un fichero. No solamente puede cambiar un nombre, puede
incluso moverlo de sitio, pero siempre en la misma unidad de disco.
La sintaxis de Name es la siguiente :
Name nombrerutaantiguo As nombrerutanuevo
Donde nombrerutaantiguo es una expresión de cadena que indica el nombre del fichero (con su path)
al que se le quiere cambiar el nombre, y nombrerutanuevo es una expresión de cadena que especifica
el nombre nuevo y, si se desea mover de directorio, la nueva ubicación del archivo y la unidad de disco.
El nombre y ubicación especificados en nombrerutanuevo no pueden ser los de un archivo existente.
Tanto nombrerutanuevo como nombrerutaantiguo deben encontrarse en la misma unidad de disco. Si
la ruta de acceso especificada en nombrerutanuevo existe y es distinta de la ruta de acceso especificada
en nombrerutaantiguo, la instrucción Name coloca el archivo en el nuevo directorio o carpeta y cambia el
nombre del archivo, de ser necesario. Si nombrerutanuevo y nombrerutaantiguo tienen distintas rutas de
acceso y el mismo nombre de archivo, Name coloca el archivo en la nueva ubicación, sin cambiar el
nombre del archivo. Por medio de Name se puede mover un archivo de un directorio o carpeta a otro,
pero no se puede mover un directorio o carpeta.
Si se utiliza Name con un archivo abierto se produce un error. Antes de cambiar el nombre de un
archivo, se debe cerrar.
En el ejemplo, vamos a cambiar el nombre del fichero C:\CursoVB\Ejemplos\Ejemplo1 por el de
C :\CursoVB\Ejemplos\Prueba1
Name “C:\CursoVB\Ejemplos\Ejemplo1” As “C :\CursoVB\Ejemplos\Prueba1”
En el siguiente, aparte de cambiarlo de nombre, le cambiamos de directorio.
Name “C:\CursoVB\Ejemplos\Ejemplo1” As “C :\CursoVB\Ejercic \Prueba1”
Existe una función que le permite conocer el volumen de un fichero : FileLen. Mediante esta instrucción
podrá saber, por ejemplo, si un fichero le va a caber en lo que le queda libre de un disquete, el tiempo
previsto para enviarlo por módem, etc.
La sintaxis es la siguiente :
Variable = FileLen("C:\CursoVB\Ejemplos\Ejemplo1")
Variable tomará un valor numérico igual al número de bytes del fichero.
Otra función para el tratamiento de ficheros es FileDateTime, que le permite conocer la fecha y hora de
creación o de la última modificación de un fichero.
La sintaxis es, para el caso del ejemplo :
Variable = FileDateTime ("C:\CursoVB\Ejemplos\Ejemplo1")
Variable puede tomar un valor como el siguiente : Variable = 13/02/97 14:59:20
(Observe que de esta función se obtiene una variable de cadena.) Puede aprovechar esta función para
borrar o hacer Backup de determinados ficheros que tengan mas de un tiempo de permanencia, sustituir
ficheros por versiones mas recientes, etc.
Podemos obtener y modificar los atributos de un fichero. Los atributos de un fichero se refieren a si son
de solo lectura, ficheros ocultos, de sistema, si ha sido modificado desde la última vez que se ha
realizado un Backup,
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 112
Para conocer los atributos de un fichero, utilizaremos la función GetAttr. Esta función devuelve un
número, que representa la suma de los atributos de un archivo, directorio o carpeta o una etiqueta de
volumen.
Sintaxis
Variable = GetAttr (nombreruta)
Donde nombreruta es una expresión de cadena que especifica un nombre de archivo, con su Path y
unidad de disco.
El valor devuelto por GetAttr es un número, igual a la suma de los siguientes valores de atributos:
Valor
Constante
Descripción
0
1
2
4
16
32
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Sólo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado después de efectuar la última copia
de seguridad.
Si la expresión nombreruta representa un directorio, se lo indicará devolviendo el valor 16.
Para cambiar un atributo utilizaremos la función SetAttr. La sintaxis de esta función es la siguiente
Sintaxis
SetAttr nombreruta , atributos
Donde nombreruta es una expresión de cadena que especifica un nombre de archivo, con su Path y
unidad de disco, y atributos es una o varias de las constantes o valores anteriores, cuya suma especifica
los atributos de archivo.
Dado que el valor 16 indica que lo expresado en nombreruta es un directorio, no puede pretenderse
darle a ese directorio atributos que solamente se pueden aplicar a un fichero, ni puede pretender darle a
un fichero un valor en el que entre el 16 como sumando. Estos casos le producirán un error en tiempo de
ejecución.
Si pretende establecer los atributos de un archivo abierto, se producirá un error en tiempo de ejecución.
Existe una función, que no tiene nada que ver con la anterior, aunque puede parecerlo por su parecido
semántico y que también devuelve atributos, pero de otro tipo. Esta función es FileAttr
Función FileAttr
Devuelve el modo de apertura de un archivo. Logicamente debe referirse a un archivo abierto en el
momento de ejecutar esta función. Vea para mas detalles la sentencia Open.
Sintaxis
variable = FileAttr (numerocanal , tipoinformación)
Donde numerocanal es el número del canal de apertura de ese archivo, y tipoinformación es el tipo de
información que deseamos de ese fichero. Si tipoinformación = 1 nos devuelve el modo de apertura del
fichero, según la siguiente lista
LSB
Valor
Modo del archivo
1
2
4
8
32
Entrada
Salida
Aleatorio
Añadir
Binario
Visual Basic – Guía del Estudiante
Capítulo 1
Página 113
La Ayuda de VB dice que tipoinformación puede ser =2 para que FileAttr devuelva información sobre el
selector de archivos del sistema operativo. Algunas veces la información de ayuda de VB promete cosas
que, sin dudar de que sean ciertas, son difíciles de comprobar.
Esta función no tiene una gran aplicación práctica, ya que comprueba la forma en la que hemos abierto
un archivo. Información que conocemos desde el mismo momento de abrirlo.
Visual Basic - Guía del Estudiante Cap. 4
CONTROLES PARA MOSTRAR IMÁGENES
CREAR CONTROLES EN TIEMPO DE EJECUCIÓN
EL EXAMINADOR DE OBJETOS
_________________________________________________________________
Una imagen representa una figura, bien natural (tipo fotografía) o sintética. Para presentar una imagen
es necesario hacerlo sobre un objeto que la admita. Los objetos que admiten una imagen son:



Formularios
PictureBox
Image
Existen mas controles gráficos que se irán viendo a lo largo del curso. Estos tres son los mas usados y
con los que comenzaremos a trabajar.
Para mostrar una imagen en cualquiera de estos objetos, es necesario especificarlo en su propiedad
Picture. La forma de especificarle al objeto la imagen que debe presentar puede hacerse de dos
formas:


En la caja de propiedades, si no se va a variar la imagen durante la aplicación.
Mediante una instrucción para cambiar esta propiedad. La instrucción es la siguiente:
Nombreobjeto.Picture = LoadPicture (Path, Fichero)
Por ejemplo, si tenemos un formulario llamado Form1 y queremos rellenarlo con una imagen contenida
en el fichero de Windows metafile DOLLAR.WMF que se encuentra en el directorio
C:\VB\METAFILE\BUSINESS, deberemos ejecutar la instrucción:
Form1.Picture = LoadPicture (“C:\VB\METAFILE\BUSINESS\ DOLLAR.WMF”)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 114
Para "descargar" esa imagen de ese formulario, basta con ejecutar la misma instrucción sin fichero
alguno:
Form1.Picture = LoadPicture ( )
También pueden tomar la imagen desde otro control de imagen, mediante un procedimiento de
Intercambio Dinámico de Datos (DDE) (Solo el PictureBox)
Puede también meter una imagen en una variable, y luego poner en uno de los controles citados
anteriormente la imagen guardada en la variable. Este método es muy rápido, ya que no necesita
acceder al disco para buscar una imagen, pero emplea mucha memoria RAM, ya que la variable )o
variables conteniendo la(s) imágenes están en la RAM.
Para ello debemos declarar una o varias variables tipo Picture, y meter en ellas una imagen mediante el
método LoadPicture. Vea en el capitulo 7 (Métodos Gráficos - Método LoadPicture) un ejemplo muy
ilustrativo.
EL FORMULARIO
Ya hemos visto lo que es el Formulario. Simplemente podemos añadir a lo ya dicho, que un formulario
tiene la propiedad Picture, con lo que podemos poner como fondo un bit-map, un fichero de icono ( .ICO)
o un Metarchivo (.WMF). Un fondo gráfico sobre el Formulario puede convertir una aplicación de buena
a excelente. No intente nunca mejorar una aplicación mediocre con un fondo artístico en un Formulario.
Además de presentar imágenes, se puede escribir texto en un formulario. Para ello se utiliza el método
gráfico Print que veremos en el capítulo de métodos gráficos
CONTROL PICTURE BOX
Este objeto se encuentra en la caja de herramientas estándar:
Este objeto permite presentar todo tipo de ficheros gráficos (.BMP, WMF, .ICO, .CUR)
Las dimensiones del PictureBox se establecen en el diseño o mediante programa, variando las
propiedades Height y Width. También puede cambiarse su posición mediante las propiedades Top y
Left. Dispone de una propiedad, Align que permite colocarlo adosado en la parte superior. Inferior o a
uno de los lados del formulario que lo contiene.
El Control PictureBox puede ser destino de los datos de un enlace DDE. (Los datos serán, lógicamente,
gráficos. Por ello, tiene las propiedades LinkMode, LinkItem, LinkTimeout y LinkTopic.
También puede tomar el dato del gráfico de una Base de Datos. (A través de un control Data o un objeto
Recordset o rdoResultset)
Las propiedades de un PictureBox son:
Align
ClipControls
DrawWidth
ForeColor
LinkMode
Negotiate
ScaleWidth
LSB
Appearance
DataField
Enabled
Height
LinkTimeout
Picture
TabIndex
Autoredraw
Autosize
DataSource
DragIcon
FiilStyle
FillColor
HelpContextID Index
LinkTopic
MouseIcon
ScaleHeight ScaleLeft
TabStop
Tag
Visual Basic – Guía del Estudiante
Capítulo 1
Backcolor
DragMode
Font
Left
MousePointer
ScaleMode
Top
BorderStyle
DrawStile
Fontransparent
LinkItem
Name
ScaleTop
Visible
Página 115
WhatThisHelp Width
Un PictureBox puede disponer de los siguientes procedimientos :
Click
KeyDown
Change
KeyPress
DblClick
DragDrop
DragOver
GotFocus
Al igual que en el formulario, se puede escribir texto en un PictureBox, utilizando el método Print.
El control Picture puede ser contenedor de otros controles. Esto quiere decir que puede poner otros
controles dentro del picture, y esos controles tendrán un comportamiento especial en ciertos casos. (Verá
más adelante el control Option)
CONTROL IMAGE
Este control se encuentra en la caja de herramientas estándar:
Este control permite presentar todo tipo de ficheros gráficos (.BMP, WMF, .ICO, .CUR)
El control Image no puede ser destino de una comunicación DDE. Puede tomar la imagen de una base
de datos, bien a través de un control Data o a través de un objeto Recordset.
El control Image utiliza menos recursos del sistema y repinta con más rapidez que un control PictureBox,
pero sólo admite una parte de las propiedades, los eventos y los métodos de PictureBox. Use la
propiedad Stretch para determinar si el gráfico se escala para que se ajuste al control o viceversa.
Poniendo esta propiedad a True el gráfico se adaptará a las dimensiones del control Image. Si se pone a
False, el control Image tomará las medidas del gráfico que contenga. Si el gráfico es un bit-map (Fichero
.BMP), con la propiedad Stretch a True podemos variar el tamaño del bit-map, variando las propiedades
Width y Height del control Image, propiedades que se pueden cambiar en tiempo de ejecución. Si esta
propiedad está a False, el tamaño del bit-map no cambiará, presentándose solamente una porción del bitmap, caso que el control Image sea menor que el tamaño del bit-map, o sobrará espacio en el control, en
caso contrario.
Un Image es transparente, es decir, deja ver el fondo del formulario en las partes no ocupadas por su
gráfico. Por lo tanto, no tendrían sentido en este control propiedades como Backcolor, FillColor, o
FillStyle.
Las propiedades de un Image son:
Appearance BorderStyle
Enabled
Height
Picture
WhatThisHelp Width
Datafield
Index
Stretch
DataSource
Left
Tag
DragIcon
MouseIcon
Top
DragMode
MousePointer Name
Visible
GotFocus
MouseDown
Un Image puede disponer de los siguientes procedimientos :
Click
MouseMove
LSB
DblClick
DragDrop
MouseUp
Visual Basic – Guía del Estudiante
Capítulo 1
DragOver
Página 116
PROPIEDADES DE LOS CONTROLES PictureBox e Image
(PictureBox solamente)
Align
Permite colocar el control en el borde superior (Align Top), en el inferior (Align Bottom), en
el izquierdo (Align Left) o en el derecho (Align Right) del formulario que lo contiene. Para
no alinearlo con ningún borde basta con poner la propiedad Align a 0-None.
Cuando se adosa a uno de los bordes, el tamaño del control se ajusta automáticamente a la
anchura o altura del formulario.
Sintaxis
NombrePictureBox.Align [= número]
número
Un entero que especifica cómo se presenta el control. Puede tomar los
siguientes valores :
(Predeterminado cuando el control se coloca en un formulario no MDI).
0-None
Con este valor, el control mantiene el tamaño y la posición asignada en
tiempo de diseño.
1-Top
(Predeterminado cuando el control se coloca en formularios MDI) El control
se coloca en la parte superior del formulario y su anchura es igual a la
anchura del formulario.
2-Bottom El control se coloca en la parte inferior del formulario y su anchura es igual
a la anchura del formulario.
3-Left
El control se coloca en la parte izquierda del formulario y su altura es igual
a la altura del formulario.
4-Right
El control se coloca en la parte derecha del formulario y su altura es igual a
la altura del formulario.
Se puede usar propiedad Align para crear rápidamente una barra de herramientas o una
barra de estado en la parte superior o inferior de un formulario. Cuando un usuario cambie el
tamaño del formulario, un control con la propiedad Align establecida a 1 ó 2 modificará su
tamaño de forma automática para ajustarse a la anchura del formulario.
De la misma forma se puede crear barras de herramientas a los lados izquierdo o derecho
de un formulario. Si en un formulario hay dos barras de herramientas, una en la parte
superior (o inferior) y otra en un lateral, la de la parte superior o inferior es la que se extiende
hasta la esquina, teniendo preferencia sobre las colocadas verticalmente a la izquierda o a la
derecha.
Al ser el PictureBox un contenedor, puede poner un PictureBox en la parte superior de un
Formulario, y colocar en este PictureBox varios controles Image, a los que se les puede
poner un icono. De esta forma realizamos una barra de herramientas.
Negotiate
(PictureBox solamente)
Esta propiedad le permite mostrar o no mostrar el PictureBox dentro de un formulario donde
tiene una barra de herramientas. No está disponible en tiempo de ejecución.
Esta propiedad no es muy usual, por lo que omitimos una mayor explicación. Recurra a la
ayuda para obtener mas detalles
Appearance
(PictureBox e Image) 3D o Flat, como en otros controles
Autoredraw
(PictureBox solamente)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 117
Permite que el Formulario o PictureBox (El control Image no tiene esta propiedad), mantenga
siempre la imagen o el texto presente. Si Autoredraw está a False, el control no presentará
las imágenes o texto que no se hayan dibujado realmente (caso por ejemplo de un formulario
minimizado) o que se hayan borrado por haber sido puestas tras otro control.
Autosize
(PictureBox solamente)
Si esta propiedad es True se cambia automáticamente el tamaño del PictureBox para
acomodarse al tamaño de la imagen. Si es False, si la imagen es mayor que el PictureBox
la recortará, y si es menor, presentará una zona sin imagen.
BackColor
(PictureBox solamente)
Color de fondo. Igual que otros controles
BorderStyle
(PictureBox e Image)
Tipo de borde. Ninguno o fijo. Igual que otros controles.
ClipControls
(PictureBox solamente)
Devuelve o establece un valor que determina si los métodos gráficos en eventos Paint
vuelven a dibujar el objeto entero o solamente las áreas últimamente expuestas. Si esta
propiedad es True, un método gráfico repintará todo el Picture. Si es False, solamente
repintará la zona de la imagen que ha variado.
DataField
DataSource
(PictureBox e Image)
(PictureBox e Image)
Verá con mas detalles estas propiedades cuando estudie los Objetos enlazados a Datos. Le
van a permitir presentar una imagen desde una base de datos. Le permitirá también
introducirla de una forma muy sencilla en la base de datos.
DragIcon
DragMode
(PictureBox e Image)
DrawMode
DrawStyle
DrawWidth
(PictureBox solamente)
(PictureBox solamente)
(PictureBox solamente)
Enabled
Igual que otros controles
Formas de responder a los métodos gráficos. Lo verá en el capítulo correspondiente
(PictureBox e Image)
Habilitado. Igual que otros controles.
FillColor, FillStyle, Font, Fontransparent, ForeColor (PictureBox solamente)
Igual que otros controles.
Height, Width , Left, Top
(PictureBox e Image)
Definen el tamaño y la posición del control. En el control Image el tamaño puede depender
del gráfico que se introduzca y del valor de la propiedad Stretch.
HelpContextID
(PictureBox solamente)
Igual que otros controles
Index
(PictureBox e Image)
Igual que otros controles
LinkItem, LinkMode, LinkTimeout, LinkTopic
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
(PictureBox solamente)
Página 118
Propiedades que afectan al comportamiento de este control como DESTINO de una
conversación DDE. Se estudiará con mas detalles al estudiar el Intercambio Dinámico de
Datos.
MouseIcon, MousePointer
(PictureBox e Image)
MouseIcon Establece un icono de mouse personalizado.
(Una vez que comenzamos a estudiar las propiedades gráficas, se comenta cómo se puede cambiar el
icono de la propiedad MouseIcon de todos los controles)
Sintaxis
objeto.MouseIcon = LoadPicture(ruta)
objeto.MouseIcon = imagen
ó
donde :
objeto
Nombre del objeto PictureBox o Image
ruta
Expresión de cadena que especifica la ruta y el nombre del archivo que contiene
el icono personalizado. Así podemos cargar un icono de los existentes en el disco. Ej.
Image1.MouseIcon = LoadPicture("C:\vb\icons\computer\disk05.ico")
imagen
Propiedad Picture de un objeto Form, de un control PictureBox o de un control
Image, o nombre de una variable tipo Picture. De esta forma podemos cargar como un icono
el gráfico que tengamos en otro objeto o en una variable tipo Picture.
Ej. Image1.MouseIcon = Picture1.picture
La propiedad MouseIcon proporciona un icono de mouse personalizado que se utiliza
cuando el valor de la propiedad MousePointer es 99.
MousePointer. Establece el tipo de puntero de mouse que aparece cuando se pasa el
puntero del ratón por encima de un objeto en tiempo de ejecución.
Sintaxis
objeto.MousePointer [= valor]
objeto
Nombre del objeto PictureBox o Image
valor
Número entero que especifica el tipo de puntero de mouse que aparece, según
se describe mas adelante.
Las opciones para valor son:
0 (Predeterminado) Forma que determine el objeto.
1 Flecha.
2 Cruz (puntero en forma de cruz).
3 Forma de I.
4 Icono (pequeño cuadrado dentro de otro cuadrado).
5 Tamaño (flecha de cuatro puntas: norte, sur, este y oeste).
6 Tamaño NE SO (flecha doble apuntando al nordeste y al sudoeste).
7 Tamaño N S (flecha doble apuntando al norte y al sur).
8 Tamaño NO SE (flecha doble apuntando al noroeste y al sudeste).
9 Tamaño O E (flecha doble apuntando al oeste y al este).
10 Flecha hacia arriba.
11 Reloj de arena (espera).
12 No soltar.
13 Flecha y reloj de arena.
14 Flecha e interrogación.
15 Tamaño de todo (personalizable en Microsoft Windows NT 3.51)
99 Icono personalizado especificado en la propiedad MouseIcon explicada anteriormente.
Name
LSB
(PictureBox e Image)
Visual Basic – Guía del Estudiante
Capítulo 1
Nombre del control
Página 119
Picture
(PictureBox e Image)
Devuelve o establece un gráfico mostrado en un control.
Ya se ha estudiado mas atrás como cambiar la propiedad Picture.
ScaleHeight, ScaleWidth, ScaleLeft, ScaleTop, ScaleMode
Propiedades del PictureBox solamente.
¡Todas las propiedades Scale ? ? ? afectan a la medida de las coordenadas, no a la escala !
ScaleHeight, ScaleWidth
Establecen el número de unidades de medida horizontal (ScaleWidth) y vertical
(ScaleHeight) del interior de un objeto al utilizar métodos gráficos o al colocar controles.
Sintaxis
objeto.ScaleHeight [= valor]
objeto.ScaleWidth [= valor]
objeto
valor
Nombre del Control
Expresión numérica que especifica la medida horizontal o vertical.
Nota Las propiedades ScaleHeight y ScaleWidth son distintas de las propiedades Height y
Width.
ScaleLeft, ScaleTop
Devuelven o establecen las coordenadas horizontal (ScaleLeft) y vertical (ScaleTop) de los
bordes izquierdo y superior de un objeto al utilizar métodos gráficos o al situar controles.
Estas coordenadas están medidas de acuerdo con la unidad de medida establecida en las
propiedades ScaleHeight y ScaleWidth
ScaleMode
Devuelve o establece un valor que indica la unidad de medida de las coordenadas de un
objeto al utilizar métodos gráficos, o al situar controles.
Sintaxis
objeto.ScaleMode [= valor]
Nombre del Control
objeto
Nombre del Control
valor
Número entero que especifica la unidad de medida, según se describe a
continuación.
0 Indica que una o más de las propiedades ScaleHeight, ScaleWidth, ScaleLeft y ScaleTop
tienen valores personalizados. Se usa entonces una unidad de medida definida por el
usuario (User)
1 (Predeterminado) Twip (1440 twips por pulgada lógica; 567 twips por centímetro lógico).
2 Punto (72 puntos por pulgada lógica).
3 Píxel (la unidad mínima de la resolución del monitor o la impresora).
4 Carácter (horizontal = 120 twips por unidad; vertical = 240 twips por unidad).
5 Pulgada.
6 Milímetro.
7 Centímetro.
Utilizando las propiedades relacionadas ScaleHeight, ScaleWidth, ScaleLeft y ScaleTop,
puede configurar un sistema de coordenadas completo, con coordenadas positivas y
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 120
negativas. Estas cuatro propiedades de escala se relacionan con la propiedad ScaleMode de
la siguiente forma:
Al establecer un valor en cualquier otra propiedad de escala, en ScaleMode se establece
automáticamente 0.
Al establecer en ScaleMode un número mayor que 0, ScaleHeight y ScaleWidth cambian a la
nueva unidad de medida, y en ScaleLeft y ScaleTop se establece 0. Además, los valores de
CurrentX y CurrentY cambian para reflejar las nuevas coordenadas del punto actual.
Stretch
(Solo control Image)
Devuelve o establece un valor que indica si un gráfico cambia su tamaño para ajustarlo al de
un control Image.
Sintaxis
objeto.Stretch [= lógico]
objeto
Nombre del control Image
lógico
Expresión booleana que especifica si el gráfico adapta su tamaño, según se
describe a continuación.
True
False
El gráfico cambia su tamaño para ajustarlo al del control.
(Predeterminado) El control cambia su tamaño para ajustarlo al del gráfico.
Si Stretch tiene el valor True, al cambiar el tamaño del control también se cambiará el del
gráfico que contenga. Cuando aumenta el tamaño del control, mantiene las nuevas medidas
aunque se le introduzca un gráfico de menor tamaño. Debe controlarse por programa el
tamaño del mismo.
TabIndex, TabStop
(Solo control PictureBox)
Igual que otros controles
Tag
Top
Visible
WhatsThisHelpID
Width
Comunes a ambos. Igual que resto de controles.
Otros controles que pueden manejar imágenes
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 121
IMAGE LIST
Lo verá mucho mas ampliamente en un capítulo posterior. Se incluye en este capítulo para que lo pueda
ir usando.
Este control no está normalmente en la caja de herramientas. Hay que introducirlo mediante los
Proyecto | Componentes y pertenece al grupo Microsoft Windows Common Controls
(COMCTL32.OCX) (Vea Nota 1)
Este control nos permite almacenar varias imágenes. Es, tal como indica su nombre, como un ListBox
pero que en vez de contener textos, contiene imágenes.
La utilidad de este control es para almacenar en él distintas imágenes, y servirlas desde él a otro control,
un PictureBox o un control Image, sin necesidad de tener que acceder a leerlas en el disco, que
conllevaría una importante pérdida de tiempo si el cambio de imágenes debe ser rápido.
Este control es necesario para almacenar las imágenes que se mostrarán en los iconos de la barra de
herramientas. Verá mas adelante como se realiza una barra de herramientas (La barra de herramientas
solo está disponible para la versión de 32 Bits)
Un ImageList permite tener varias imágenes dentro de él, pero este control no las presenta. Solamente
sirve de “almacén” para pasarlas rápidamente a otro control ( PictureBox, p.e.) que será el que las
presenta en pantalla.
En la siguiente figura, pueden verse las propiedades de un ImageList con varias imágenes cargadas.
Nota 1. El grupo de controles Microsoft Windows Common Controls (COMCTL32.OCX) incluye
además de este los controles TabStrip, Toolbar, StatusBar, ProgressBar, TreeView, ListView y Slider. Se
verá con más detalle en un próximo capítulo (Cap. 16)
Para introducir imágenes en el control ImageList deberemos acceder a sus propiedades, bien mediante
F4 y luego haciendo click sobre Personalizado, bien pulsando el botón derecho del ratón sobre el icono
del control. Aparecerá un cuadro donde podemos insertar imágenes
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 122
El tipo de imágenes pueden ser mapas de bits :BMP o iconos .ICO
El control ImageList tiene una colección llamada ListImages. Esta colección contiene todas las
imágenes introducidas en el ImageList y las propiedades de cada imagen. Como toda colección, será un
array donde podemos elegir uno de sus elementos designándolo por su nombre seguido de su número
(Index) encerrado entre paréntesis. Así la imagen número 3 será :
ImageList1.Listimages (3)
Si tenemos un control Picture llamado Picture1 y queremos poner en su propiedad Picture la imagen
cargada en el ImageList1, en su posición 3, usaríamos la expresión :
Set Picture1.Picture = ImageList1.ListImages (3) . Picture
Observe que tras ListImages ( ) es necesario poner la propiedad Picture, ya que Picture es una propiedad
de la colección ListImages
Como cualquier colección, ListImages tiene la propiedad Count, que nos servirá para contar el número de
imágenes que guarda.
Numerodeimágenes = ImageList1. ListImages.Count
Dado que al guardar imágenes en un ImageList, estas imágenes están guardadas en la memoria RAM,
es fácil realizar una animación. Para ello necesitamos varias imágenes que poniendo una tras otra, dé la
sensación de movimiento. Imaginemos un número indeterminado de imágenes dentro de un ImageList, y
un control Picture llamado Picture1 donde queremos presentar la animación. En el procedimiento Timer
de un Timer pondríamos
Static pepe As Integer
pepe = pepe + 1
If pepe > ImageList1.ListImages.Count Then pepe = 1
Set Picture1.Picture = ImageList1.ListImages(pepe).Picture
Una de las mayores aplicaciones del ImageList es proporcionar imágenes para otros controles. Entre
ellos el TOOLBAR
Barra de Herramientas. Control Toolbar
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 123
Este control permite realizar una barra de herramientas. La barra de herramientas es, como ya conocerá,
una barra donde existen varios iconos. Estos iconos realizan una determinada función. Normalmente se
ponen en la barra de herramientas los iconos que representan las acciones mas frecuentes de una
aplicación. Esto facilita la operación al no tener que desplegar menús para buscar la operación a realizar.
Como el espacio que ocupan los iconos es grande, es también bastante normal que no estén
representados en la barra de herramientas todas las funciones posibles de la aplicación, sino como
decíamos, solamente las mas frecuentes. Pero ocurre que la función que para un usuario es muy
frecuente, para otro no lo es, por lo que también es habitual poder programar los iconos que aparecen en
la barra de herramientas.
Todo ello lo puede hacer el control Toolbar.
Para introducir el Toolbar es necesario que esté presente en la caja de herramientas el control
personalizado Microsoft Windows Common Controls (COMCTL32.OCX).
El control Toolbar es un contenedor de un array de iconos. Estos iconos forman botones sobre los que
se puede insertar código en sus procedimientos. A cada botón se le denomina Button y a la colección
de botones se le denomina Buttons. Cada Button es un elemento de la colección Buttons y por lo tanto
podemos referirnos a cada uno de ellos por el índice que tiene dentro de la colección.
Los iconos de cada uno de los botones del Toolbar debe introducirse previamente en un control
ImageList. Como se recordará, un control ImageList es un almacén de imágenes, que podemos usar
en cualquier parte de la aplicación. Una de esas partes es la confección de la barra de herramientas. Por
lo tanto, es necesario introducir un control ImageList en cualquier aplicación que use un control Toolbar.
Todas las imágenes del Toolbar deben estar en un único ImageList. Y este ImageList debe estar en el
mismo formulario que el Toolbar
La barra de herramientas puede realizarse en tiempo de diseño (este sería el caso para cuando no
existiese variación ni elección de botones a lo largo de la ejecución de la aplicación)
o en tiempo de ejecución (caso que correspondería con una aplicación que tuviese una barra de menú
programable o que variase esta barra de menú dependiendo de cada operación que se esté ejecutando
en la aplicación).
Para realizar la barra de herramientas en tiempo de diseño, basta con visualizar el cuadro de
propiedades que aparece pulsando el botón derecho del ratón sobre el control Toolbar. Aparecerá un
cuadro de diálogo como este :
Puede ver que en el cuadro ImageList aparece el nombre de un ImageList. Al desplegar la lista
aparecerán todos los ImageList que existan en el formulario. El ImageList debe estar en el mismo
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 124
formulario que el Toolbar. Deberá elegirse el ImageList que contenga las imágenes de los iconos que
queremos introducir en el Toolbar.
Este cuadro nos permite también introducir la forma que adoptará el puntero del ratón cuando entre en el
Toolbar (MousePointer), si el Toolbar aparece por defecto habilitado o deshabilitado (Enabled) y si
muestra o no un rótulo programable al pasar el ratón por encima de cada botón del Toolbar. (ShowTips).
(El uso de estos pequeños rótulos pueden hacer una aplicación muy bonita) La propiedad
AllowCustomize permite, si es True, cambiar el orden de los botones e introducir separadores (vea
evento DobleClick).
En el cuadro botones podemos introducir los datos deseados para cada uno de los botones que
compondrán la colección Buttons.
Para insertar un nuevo botón hay que hacer click sobre Insertar botón e insertará un nuevo botón
inmediatamente después del que figura en la propiedad Index (en la figura del ejemplo, lo insertaría en
segundo lugar, no en el último lugar como podría creerse). También podemos eliminar un botón
haciendo click sobre Eliminar botón.
El Caption (opcional) es la palabra que figurará debajo del icono del botón.
Un botón se identifica por su índice. ( Toolbar1.buttons(1) )
La propiedad Key es un nombre que se puede añadir a cada botón. Esta propiedad sirve para identificar
el botón que se ha pulsado, pero no para nombrar al botón.
La propiedad Value es el valor por defecto, con el que aparecerá el botón al comienzo de la aplicación.
(Unpressed, no pulsado, Pressed, pulsado).
La propiedad Style define el tipo de botón :
0 - Default
1 - Check
2 - Button Group
3 - Separator
4 - PlaceHolder
Botón monostable. (Se pulsa, pero no se mantiene pulsado)
Botón Biestable. (Se mantiene pulsado y se levanta con otro click)
Solo uno de los botones del grupo puede estar pulsado. Esta
propiedad lleva implícito que los botones que forman un grupo son
biestables. Pueden hacerse varios grupos independientes introduciendo
un botón que no pertenezca a un grupo (tipos 0, 1, 3 ó 4) entre los dos
grupos que se independientes que se pretenden formar
El botón se convierte en un separador de anchura fija.
El botón se convierte en un separador de anchura variable.
ToolTipText es el texto que aparecerá al lado del botón cada vez que se ponga el cursor del ratón sobre
el botón. Para que aparezca debe estar habilitada la propiedad ShowTips.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 125
Image es el número de la imagen en el ImageList.
El control Toolbar también puede realizarse en tiempo de ejecución. Para introducir u botón en el Toolbar
hay que crear el botón y añadirlo a la colección Buttons de Toolbar. Podemos hacerlo en una sola
instrucción :
Set NombreBotón = NombreToolbar.Buttons.add ( [Indice], [Key], [Caption], [Style], [Imagen])
NombreBotón puede ser cualquier nombre (es el nombre del objeto botón)
NombreToolbar es el nombre del Toolbar
Indice es el número de orden de ese botón dentro del Toolbar
Key es el valor de la propiedad Key del botón. Este valor debe ser único para cada botón.
Style es un número del 0 al 4 con el tipo de botón. Vea lista mas arriba
Imagen es el número de la imagen para ese botón, dentro del ImageList que las contiene.
Los botones pueden habilitarse y deshabilitarse usando la propiedad Enabled (True / False). Recuerde
que los botones se identifican por su índice :
Toolbar1.Buttons(Indice).Enabled = False
Para saber que botón se ha pulsado, puede leerse la propiedad Key :
Text1.Text = Button.Key
presenta en Text1 el texto introducido en la propiedad
Key del último botón pulsado.
Con la lectura de la propiedad Key, y la sentencia Case o If ... Then podemos iniciar la parte de la
aplicación asociada a cada botón.
El control Toolbar tiene los siguientes eventos :
ButtonClick
Este evento se produce cada vez que se hace click sobre un botón del Toolbar. Pasa como parámetro el
índice del botón pulsado. Podremos saber que botón se ha pulsado mediante sentencias condicionales :
Private Sub Toolbar1_ButtonClick(ByVal Button As Button)
If Button.Index = 1 Then . . . .
If Button.Index = 2 Then . . . .
También podríamos usar la propiedad Key como se dijo mas atrás.
Click
Este evento se produce cuando se hace click sobre cualquier botón del Toolbar, pero no pasa
parámetros. (No distingue sobre que botón se ha hecho click) Podemos utilizarlo cuando se quiera
realizar una operación común para todos los botones (Que suene un Beep, por ejemplo)
DobleClick
Este evento solamente se produce cuando se hace doble click en la parte del Toolbar donde no hay
botones, y la propiedad AllowCustomize esté a True. Si se hace doble click sobre un botón se produce
solamente el evento click (dos veces). Haciendo doble click en una zona libre de botones, con la
propiedad AllowCustomize = True nos permite cambiar el orden de los botones e introducir separadores.
Change
Se produce solamente cuando se ha realizado algún cambio del orden por el procedimiento anterior.
DragDrop, DragOver
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 126
Igual que cualquier control.
MouseMove, MouseUp, MouseDown
Igual que el resto de los controles Pasa como parámetro el índice del botón, la tecla de mayúsculas, y las
posiciones x e y del ratón.
Private Sub Toolbar_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Este control solamente funciona en la versión de VB de 32 Bits. Pero para 16 bits puede hacerse una
cosa parecida (y mas sencilla) utilizando un control Picture como contenedor de tantos controles Image
como necesitemos. Dado que el control Picture dispone de propiedad Align y puede servir como
contenedor de otros controles, puede realizarse una barra de herramientas similar a esta, y posiblemente
de forma mas sencilla.
¡ El control Toolbar NO sirve de contenedor de otros controles, a excepción de sus botones ! ! !
LA BARRA DE ESTADO
Este control es muy parecido a la barra de herramientas, y suele usarse, colocándolo en la parte inferior
de la ventana, para indicar el proceso que está en curso en la aplicación. La barra de estado, control
StatusBar se introduce en la caja de herramientas al mismo tiempo que el control Toolbar, mediante el
control personalizado múltiple Microsoft Window s Common Controls (COMCTL32.OCX).
La barra de estado puede albergar hasta 16 paneles, que pueden contener texto o gráficos. También
pueden contener información del Hardware, tal como el estado de la tecla Bloqueo de Mayúsculas,
Bloqueo del teclado numérico, tecla Insert activada, tecla Scroll Lock activada, o mostrar la fecha y
la hora
La barra de estado puede configurarse como de un solo panel o de múltiples paneles. (Propiedad Style.
0=múltiples paneles, 1= panel único)
Las dimensiones de cada panel pueden configurarse como fijas o ajustadas al tamaño del texto o
imagen que presentan.
Las propiedades pueden establecerse en tiempo de diseño, mediante el siguiente cuadro.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 127
En este control las imágenes no es necesario introducirlas previamente en un ImageList. Pueden
introducirse directamente sobre el cuadro de diálogo que sale pulsando el botón derecho del ratón propiedades - en la ventana correspondiente a paneles. Acepta imágenes tipo Bit-map o .ICO. Los
paneles pueden combinar una gráfico y un texto.
La barra de estado puede realizarse en tiempo de diseño o en tiempo de ejecución. Para realizarla en
tiempo de ejecución basta con visualizar la ventana de propiedades, muy similar a la del control Toolbar.
Para añadir un panel en tiempo de ejecución basta con añadirlo a la colección Panels del control
StatusBar mediante la sentencia :
Set PanelNuevo = Nombrebarraestado.Panels.Add.( [índice],[key],[Text],[estilo],[gráfico]
Donde PanelNuevo es el nombre con el que se va a conocer ese panel que acabamos de crear.
PanelNuevo debe declararse como variable objeto Panel donde sea necesario según el ámbito que le
queramos dar. De esta forma, una vez creado, nos podremos referir a ese panel simplemente citándolo
por su nombre (En este caso, PanelNuevo)
Los términos [índice],[key],[Text],[estilo],[gráfico] que entran a formar parte en la sintaxis de creación
del panel se explican a continuación.
Indice - Necesario. Es el índice que define al panel dentro del StatusBar.
Key - Opcional. Es la propiedad Key de ese panel (El contenido de esta propiedad lo podemos
leer desde cada panel
Variable = statusbar1.Panels(Panel.Index).Key
Text - El texto que queremos figure en el panel (Solo si la propiedad Estilo está en sbrText
Estilo - Propiedad estilo del panel.
0 - sbrText
El panel mostrará el Texto de la propiedad Text de ese panel
1 - sbrCaps
El panel muestra el estado de la tecla Bloqueo Mayúsculas
2 - sbrNum
El panel muestra el estado de la tecla Bloq. Números
3 - sbrIns
El panel muestra el estado de la tecla Insert
4 - sbrScrl
El panel muestra el estado de la tecla Scroll / Lock
5 - sbrTime
El panel muestra la hora
6 - sbrDate
El panel muestra la fecha
Gráfico - Es el gráfico que va a tener el panel. Este gráfico puede obtenerse desde un ImageList,
ImageList1.ListImages(n).Picture - o directamente desde el disco duro, mediante el
método LoadPicture - LoadPicture("C:\vb\icons\comm\net09a.ico") -
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 128
Si no se pone alguna de las propiedades opcionales intermedias, deben mantenerse las comas
separadoras.
Como ejemplo, podemos añadir varios paneles de la siguiente forma :
Dim PanelNuevo As Panel
Dim pepe As Integer
‘Donde deba declararse a efectos del ámbito
Set PanelNuevo = statusbar1.Panels.Add(pepe, "Contenido del Key " & Str(pepe), "Texto " & Str(pepe), ,
LoadPicture("C:\vb\icons\comm\net09a.ico"))
Estos son los controles gráficos mas importantes. Verá a lo largo del curso que existen otros, y más que
podrá encontrar entre diferentes suministradores de controles, ya que VB ha dejado una puerta abierta
para realizar controles a medida. Existen varias empresas de software dedicadas a la fabricación de
controles personalizados, y en el aspecto de controles gráficos, podrá encontrar una amplia gama de
fabricantes y controles. Puede obtener muchos controles en el CD-ROM que acompaña a varias revistas
especializadas en programación VB, y a través de Internet.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 129
Visual Basic - Guía del Estudiante - Ademdum 1 al Capitulo 4
CREAR CONTROLES EN TIEMPO DE EJECUCIÓN
Los ademdums se fueron introduciendo una vez que la Guía del Estudiante estuvo “casi” terminada. Los
temas tratados en los ademdums no constituyen en sí mismos materia suficiente para un nuevo
capítulo, ni se acoplan lógicamente a ninguno de los capítulos escritos. Por lo tanto, se ha decidido
alojarlos en capítulos que no eran demasiado “gruesos”, aunque el contenido de los ademdums no
encaje ni por su contenido, ni por los conocimientos anteriores. No se preocupe que algunos ademdums
no los entienda. Posiblemente estemos usando un lenguaje que no se ha visto todavía en los capítulos
estudiados. Los podrá repasar cuando lo considere oportuno, una vez vaya avanzando en el curso.
Desde mis comienzos en la actividad educativa de esta asignatura, los alumnos siempre me preguntaron
por la posibilidad de crear controles en tiempo de ejecución. Supongo que exista alguna razón que yo
desconozco para ello. Y digo esto porque no he tenido la necesidad de ello en ninguno de mis proyectos,
y no han sido precisamente pocos.
Quiero decir con esto que la creación de controles en tiempo de ejecución es algo muy llamativo, pero de
escaso sentido práctico. Sean los alumnos los que busquen utilidad a ello, y yo me limito a mi obligación
de enseñárselo.
En anteriores versiones de VB era un proceso un poco tedioso. Había que crear una matriz de controles
y añadir en tiempo de ejecución tantos controles nuevos a esa matriz como necesitemos. Era
complicado. Había que meter un control y ponerle Index = 0. Se le pone la propiedad Visible = False y ya
tenemos una matriz de controles. Una matriz de un solo control, pero al tener la propiedad Index = 0 ya
era una matriz. Ya en ejecución, se utilizada el método Load para crear los controles que necesitamos.
Los nuevos elementos de la matriz tendrán todas las propiedades del elemento inicial, es decir, las del
elemnto que tienen indice 0. Al ser una matriz, todos los controles comparten el código de sus
procedimientos.
Para crear por ejejmplo, varios botones de comando, introduciremos primero uno con Index = 0
cmdBotonInicial(0) y cuando queramos crear un botón nuevo, invocamos el método Load. Recuerde que
el nuevo botón tendrá las mismas propiedades que el objeto inicial, por lo tanto sus mismas propiedades
Left y Top. Resultado: el nuevo botón queda completamente solapado con el inicial, por lo que habrá que
cambiarle de posición y coocarlo en las coordenadas deseadas.
Una de las propiedades que no se pasan al nuevo control es la propiedad Visible. Esta siempre
comienza a False. Por lo tanto también hay que ponerla a True para que veamos el nuevo control. Este
podría ser un código para crear un botón de comando
Load cmdBotonInicial(1)
cmdBotonInicial(1).Visible = True
cmdBotonInicial(1).Left = cmdBotonInicial(0).Left + 1000
Es un poco complicado. Se suele hacer esto para que aparezca un control justamente donde hacemos
clic con el ratón sobre el formulario. Dejo al alumno la posibilidad de jugar con este método.
Veamos un método más sencillo.
Add (Método de la colección Controls)
Agrega un control a la colección Controls y devuelve una referencia al mismo.
Sintaxis
Set NombredelControl = NombredelFormulario.Controls.Add (progID, name, container)
Donde:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 130
NombredelControl
Es la referencia del nuevo control devuelta por el método Add. Debe ser
una variable tipo Control declarada previamente. Le recomiendo que esta
variable tipo objeto tenga el mismo nombre que le va a dar al control en su
parámetro Name. Le ahorrará muchas confusiones.
NombredelFormulario
Es el formulario donde se va a meter el nuevo control. (Puede ser Me)
ProgID
Es una cadena que identifica al control. Se obtiene del Examinador de
Objetos de Visual Basic. Consiste en una cadena que indica la biblioteca
donde se encuentra, seguido del nombre que puede ver en el citado
analizador de Objetos, separados ambos por un punto.
Es el nombre que va a tener el control. Le repito lo de más atrás. Ponga aquí la
misma cadena que en NombredelControl.
Es el nombre del contenedor de ese control si es que se quiere meter
Container
dentro de un contenedor que a su vez está dentro del formulario. Un
contenedor de controles puede ser un PictureBox o un Frame. Aquí se
pondría el nombre del ese contenedor que debe existir en el formulario.
Name
Vamos a ver como se puede declarar una variable tipo Control. Puede hacerlo según estos tres
ejemplos, en el primero se declara que NuevoBoton es un control, (declaración suficientemente válida
ya que posteriormente al crearlo, le diremos que ese control es precisamente un CommandButton) , en
la segunda ya lo declaramos como objeto CommandButton, y la tercera es la declaración de un Objeto
TextBox:
Dim NuevoBoton As Control
Dim NuevoBoton As CommandButton
Dim NuevoTextBox As TextBox
Esta declaración es suficiente si no va a poner código en los procedimientos de ese control. El problema
es que con esa declaración no se puede introducir código. Para ello debe declararse de otra forma:
Private WithEvents NuevoBoton As CommandButton
Mediante esta declaración (Que debe ponerse en la sección de declaraciones del formulario), no
solamente estamos declarando que NuevoBoton es un CommandButton, sino que tendrá los mismos
eventos (WithEvents) que un CommandButton.
El código para crear estos dos controles es el siguiente:
(En el ejemplo se ha puesto en el procedimiento click de un botón de comando)
Set NuevoBoton = Me.Controls.Add("VB.CommandButton", "NuevoBoton1", Picture1)
Set NuevoTextBox = Me.Controls.Add("VB.TextBox", "NuevoTextBox", Picture1)
NuevoBoton.Visible = True
NuevoBoton.Left = 100
NuevoBoton.Top = 120
NuevoBoton.Caption = “Soy un Botón”
NuevoTextBox.Visible = True
NuevoTextBox.Left = 2000
NuevoTextBox.Top = 100
Ahora vamos a introducir el código en el procedimiento Click del botón de comando. Para ello vamos a
Herramientas | Agregar Procedimiento y tecleamos el nombre del procedimiento: NuevoBoton_Click.
Continuamos escribiendo el código deseado en ese nuevo procedimiento que acabamos de crear.
MsgBox "Esto Funciona"
Ejecutamos el programa y vemos que efectivamente, una vez creado el botón, al hacer click sobre él
sale el Mensaje Box. Volvamos a ver el código. Cuando introducimos un procedimiento nuevo creado por
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 131
nosotros, ese procedimiento aparece en el desplegable de la derecha de la ventana de código. En el
desplegable de la parte izquierda aparecen solamente los nombres de los controles existentes en el
formulario. Pero ¡Oh sorpresa!, el procedimiento NuevoBoton_Click no está en el desplegable de la parte
derecha. Está en la parte izquierda, y como si fuese un botón que realmente existe en tiempo de diseño.
Ya hemos introducido código en el botón recién creado.
Para el TextBox no ha hecho falta declararlo con la segunda declaración, ya que no va a contener
código. Podemos cambiarle las propiedades, estre ellas su propiedad Text:
NuevoTextBox.Text = "Hola Mi Amor, yo soy tu Lobo"
Texto que aparecerá en el TextBox como si se tratase de un TextBox introducido durante el diseño.
Lógicamente, si ejecutamos la linea anterior antes de crear el TextBox dará un error.
Hay formas más complicadas de crear controles, pero creo que con esta le basta. E insisto que nunca
me he visto en la necesidad de crear controles (lo cual no demuestra nada, lo reconozco)
Quitar controles
Para quitar controles agregados dinámicamente, se utiliza el método Remove. Solamente se pueden
quitar los controles agregados con el método Add (a diferencia de los controles agregados con la
instrucción Load, que se quitan mediante Unload ).
El siguiente ejemplo quita el control NuevoTextBox agregado dinámicamente:
Me.Controls.Remove "NuevoTextBox"
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 132
Visual Basic - Guía del Estudiante - Ademdun 2 al Capitulo 4
EL EXAMINADOR DE OBJETOS
El Examinador de objetos es una herramienta que tienen Visual Basic para ver los objetos de las
colecciones, las propiedades, métodos y eventos de los controles, los métodos del proyecto, las
constantes . Lo entenderemos mejor abriéndolo. Para abrirlo, basta con pulsar F2
Este es el analizador de objetos. Puede ver que tienen varias partes. Comencemos por arriba.
El desplegable donde pone Todas sirve para elegir una parte de todo lo que nos puede mostrar. En este
caso está mostrando todo lo que tienen el proyecto. Si observa la figura de la página siguiente verá que
está desplegado, mostrando todas las referencias y controles que tienen en ese momento. Puede ver
que tienen el MSCommDlg, porque a ese proyecto le habíamos introducido el CommonDialog. Si
seleccionamos ese control, nos aparecen en la ventana Classes todas las colecciones que tiene el
CommonDialog, entre ellas el propio control, que si lo seleccionamos, en la ventana de la derecha,
(Miembros) aparecerán todas la propiedades, los métodos, y los eventos (Claro que un CommonDialog
no tienen eventos, pero sí aparecerán si mostramos cualquier otro control)
Si le añadimos ahora una referencia (El acceso a una base de datos mediante DAO, por ejemplo)
aparecerá esa referencia en la lista desplegable.
Los controles básicos aparecen en la referencia VB. Aparecen concretamente los controles que figuran
en la barra de herramientas al abrir un nuevo proyecto. Si añadimos más componentes (Haciendo clic
en la barra de menú Proyecto | Componentes) veremos que aparecen nuevos controles en el
desplegable.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 133
En la casilla Miembros aparecen los métodos, procedimientos y eventos de la clase seleccionada. Al
hacer click sobre cualquiera de estas propiedades, métodos y eventos, en la parte inferior aparece la
explicación del elemento elegido.
Parece que es un poco complicado. Nada más lejos de la realidad. Verá que es una herramienta que le
va a ser muy útil, y que la va a comprender una vez se decida a usarla, mucho antes que el tiempo que
necesitaría para leérselo en este libro. Adelante.
Visual Basic - Guía del Estudiante Cap. 5
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 134
PORTAPAPELES
INTERCAMBO DINAMICO DE DATOS
EL DRAG AND DROP (Drag & Drop) Arrastrar y Soltar
EL OLEDRAGDROP Drag & Drop con otras aplicaciones
MENÚS - MENUS EMERGENTES
EL PORTAPAPELES. EL OBJETO CLIPBOARD
El objeto Clipboard Proporciona acceso al Portapapeles del sistema.
El portapapeles es una herramienta de windows que permite transportar texto o imágenes de una
parte a otra dentro de la misma aplicación, o entre dos aplicaciones distintas. ¿Quién no ha
cortado y pegado en Windows? Pues al hacerlo está introduciendo texto en el portapaleles y
copiándolo en otra parte.
El objeto Clipboard se usa para manipular el texto y los gráficos del Portapapeles. Este objeto puede
usarse para permitir que el usuario corte, copie y pegue texto y gráficos en la aplicación.
El objeto Clipboard puede contener varias unidades de datos siempre y cuando cada una tenga un
formato diferente. Por ejemplo, se puede usar el método SetData para poner un mapa de bits en el
Clipboard con el formato CF_BITMAP y después usar el método SetText con el formato CF_TEXT para
poner texto en el Clipboard. Después se puede usar el método GetText para recuperar el texto o el
método GetData para recuperar el gráfico. Los datos del Clipboard se pierden cuando se colocan otros
datos con el mismo formato en el Clipboard desde el código o mediante un comando de menú.
SetText
Pone una cadena de texto en el objeto Clipboard usando el formato del objeto Clipboard especificado.
No acepta argumentos con nombre.
Sintaxis
Clipboard.SetText datos, formato
datos
Requerido. Cadena de datos que se va a colocar en el Portapapeles.
formato Opcional. Una constante o valor que especifica uno de los formatos del Portapapeles
reconocidos por Visual Basic, como se describe a continuación :
Los valores de formato son:
Constante
Valor
Descripción
vbCFLink
vbCFRTF
vbCFText
&HBF00
&HBF01
1
Información de conversación DDE
Formato de texto enriquecido
(Predeterminado) Texto
Estas constantes se enumeran en la biblioteca de objetos de Visual Basic (VB) del Examinador
de objetos.
SetData
Pone una imagen en el objeto Clipboard usando el formato gráfico especificado. No acepta
argumentos con nombre.
LSB
Sintaxis
Clipboard.SetData datos, formato
datos
Requerido. El gráfico que se va colocar en el objeto Clipboard.
formato
Opcional. Una constante o valor que especifica uno de los formatos del
Visual Basic – Guía del Estudiante
Capítulo 1
Página 135
objeto Clipboard reconocidos por Visual Basic, como se describe mas adelante.
Si formato se omite, SetData determina el formato gráfico automáticamente.
Los valores de formato son:
Constante
Valor
Descripción
vbCFBitmap
vbCFMetafile
vbCFDIB
vbCFPalette
2
3
8
9
Mapa de bits (archivos .BMP)
Metarchivo (archivos .WMF)
Mapa de bits independiente del dispositivo (DIB)
Paleta de colores
Estas constantes se enumeran en la biblioteca de objetos de Visual Basic (VB) del Examinador
de objetos.
El gráfico que se va colocar en el objeto Clipboard se define mediante la función LoadPicture o la
propiedad Picture de los objetos Form, Image o PictureBox.
GetData
Devuelve un gráfico del objeto Clipboard. No acepta argumentos con nombre.
Sintaxis
Clipboard.GetData (formato)
formato
Opcional. Una constante o valor que especifica el formato gráfico de Clipboard, como se
describe mas adelante. La constante o valor debe ir entre paréntesis. Si formato es 0 o se omite,
GetData usa automáticamente el formato apropiado.
Los valores de formato son:
Constante
Valor
Descripción
vbCFBitmap
vbCFMetafile
vbCFDIB
vbCFPalette
2
3
8
9
Mapa de bits (archivos .BMP)
Metarchivo (archivos .WMF)
Mapa de bits independiente del dispositivo (DIB)
Paleta de colores
Si en el objeto Clipboard no hay ningún gráfico que coincida con el formato esperado, no se
devuelve nada. Si en el objeto Clipboard sólo hay una paleta de colores, se crea un DIB de
tamaño mínimo (1 x 1).
GetText
Devuelve una cadena de texto del objeto Clipboard. No acepta argumentos con nombre.
Sintaxis
Clipboard.GetText (formato)
formato
Opcional. Un valor o constante que especifica el formato del objeto Clipboard, como se describe
mas adelante. La constante o valor debe ir entre paréntesis.
Los valores de formato son:
Constante
Valor
vbCFLink
vbCFText
&HBF00
1
Descripción
Información de conversación DDE
(Predeterminado) Texto
Si en el objeto Clipboard no hay ninguna cadena de texto que coincida con el formato esperado,
se devuelve una cadena vacía ("").
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 136
Paste
Copia datos desde el Portapapeles del sistema en un control contenedor OLE.
Sintaxis
objeto.Paste
Objeto es el nombre del Panel Contenedor OLE donde se quiere depositar el contenido del
Portapapeles.
Comentario
Para usar este método, defina la propiedad OLETypeAllowed y después verifique el valor de la
propiedad PasteOK. No se puede pegar con éxito a menos que PasteOK devuelva True.
Si se ha ejecutado el método Paste, la propiedad OLEType es vbOLELinked (0) o
vbOLEEmbedded (1). Si no se ha ejecutado el método Paste, la propiedad OLEType es
vbOLENone (3).
Este método puede usarse para implementar un comando Edición Pegar en un menú.
Si el valor de la propiedad PasteOK es True y Visual Basic no puede pegar el objeto, el control
contenedor OLE elimina cualquier objeto existente en el control.
PasteOK
Devuelve un valor booleano que determina si el contenido del Portapapeles del sistema se
puede pegar en el control contenedor OLE.
Sintaxis
VariableBooleana = objeto.PasteOK
Objeto es el nombre del contenedor OLE donde se quiere pegar el contenido del portapapeles.
Cuando el valor de esta propiedad es True, el contenido del Portapapeles del sistema se puede
pegar en el control contenedor OLE.
La propiedad OLETypeAllowed se usa para especificar el tipo del objeto (vinculado o incrustado)
que se quiere pegar en el control contenedor OLE. Una vez que un objeto se ha pegado en el
control contenedor OLE, se puede verificar el valor de la propiedad OLEType para determinar el
tipo de objeto que ha sido creado.
Esta propiedad puede usarse si se quiere que la aplicación implemente un comando Pegar en un
menú Edición. Si PasteOK es False, el comando del menú se deshabilita; si no, puede
habilitarse. Los comandos de menú se habilitan y se deshabilitan estableciendo su propiedad
Enabled a True o False, respectivamente.
Los objetos se pegan en el control contenedor OLE con el método Paste.
Para ofrecer mayor flexibilidad al usuario, presente un cuadro de diálogo Pegado especial
cuando el usuario elija el comando Edición Pegar
. (Establezca OLETypeAllowed = 2 y después use el método PasteSpecialDlg). Cuando se
presenta este cuadro de diálogo, el objeto del Portapapeles del sistema se pega basándose en
las selecciones del usuario en el cuadro de diálogo.
GetFormat
Devuelve un entero que indica si un elemento del objeto Clipboard coincide con un formato
especificado. No acepta argumentos con nombre.
Sintaxis
VariableLong = Clipboard.GetFormat (formato)
formato
Requerido. Un valor o constante que especifica el formato del objeto Clipboard, como se
describe mas adelante. La constante o valor debe ir entre paréntesis.
Los valores de formato son:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 137
Constante
Valor
Descripción
vbCFLink
vbCFText
vbCFBitmap
vbCFMetafile
vbCFDIB
vbCFPalette
HBF00
1
2
3
8
9
Información de conversación DDE
Texto
Mapa de bits (archivos .BMP)
Metarchivo (archivos .WMF)
Mapa de bits independiente del dispositivo (DIB)
Paleta de colores
El método GetFormat devuelve True si algún elemento del objeto Clipboard coincide con el
formato especificado. Si no, devuelve False.
Para los formatos vbCFDIB y vbCFBitmap, la paleta de colores que se encuentre en el Clipboard
se usa para presentar el gráfico.
Clear
Borra el contenido del Portapapeles del sistema.
Sintaxis
Clipboard.Clear
Con Clear se borra todo el contenido del portapapeles, texto y gráficos.
Copy
Copia el objeto de un control contenedor OLE al Portapapeles del sistema.
Sintaxis
objeto.Copy
Objeto es el nombre del contenedor OLE cuyo contenido queremos copiar
Cuando se copia un objeto en el Portapapeles del sistema, todos los datos y la información de
vinculación asociados con el objeto se copian en el Portapapeles del sistema. En el Portapapeles del
sistema se pueden copiar objetos vinculados y objetos incrustados.
Este método puede usarse para implementar un comando Edición | Copiar en un menú.
EJERCICIO
Se propone el siguiente ejercicio, donde pueden verse todas las posibilidades del Portapapeles.
Cree un formulario de la siguiente forma :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 138
El gráfico que tiene el Picture de la izquierda puede ser cualquiera.
El código de este formulario es el siguiente:
Option Explicit
Private Sub Check1_Click()
End Sub
Private Sub Command1_Click()
Clipboard.SetData Picture1.Image
End Sub
Private Sub Command2_Click()
Dim ClpFmt As Integer
Dim Msg As String
On Error Resume Next ' Configura el controlador de errores.
If Clipboard.GetFormat(vbCFText) Then ClpFmt = ClpFmt + 1
If Clipboard.GetFormat(vbCFBitmap) Then ClpFmt = ClpFmt + 2
If Clipboard.GetFormat(vbCFDIB) Then ClpFmt = ClpFmt + 4
If Clipboard.GetFormat(vbCFMetafile) Then ClpFmt = ClpFmt + 8
Select Case ClpFmt
Case 1
Msg = "El Portapapeles sólo contiene texto."
Case 2
Msg = " El Portapapeles sólo contiene un archivo de mapa de bits."
Case 3
Msg = " El Portapapeles contiene texto y un archivo de mapa de bits."
Case 5
Msg = " El Portapapeles contiene texto y un archivo DIB."
Case 8
Msg = " El Portapapeles contiene solamente un archivo MetaFile."
Case 9
Msg = " El Portapapeles contiene texto y un archivo MetaFile."
Case Else
Msg = "No hay nada en el Portapapeles."
End Select
Label1.Caption = Msg ' Muestra el mensaje.
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 139
Private Sub Command3_Click()
Clipboard.Clear
End Sub
Private Sub Command4_Click()
Clipboard.SetText Label2.Caption
End Sub
Private Sub Command5_Click()
Label3.Caption = Clipboard.GetText
End Sub
Private Sub Command6_Click()
Picture2.Picture = Clipboard.GetData()
End Sub
Private Sub Command7_Click()
Picture2.Picture = LoadPicture
End Sub
Private Sub Command8_Click()
Text1.Text = Trim(Text1.Text)
If UCase(Right(Text1.Text, 3)) = "BMP" Then
Check1.Value = 1
Else
Check1.Value = 0
End If
If Check1.Value = 1 Then
Clipboard.SetData LoadPicture(Text1.Text), 8
Else
Clipboard.SetData LoadPicture(Text1.Text)
End If
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 140
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 141
INTERCAMBO DINAMICO DE DATOS (Dinamic Data Exchange) DDE
El intercambio dinámico de datos es una utilidad de Windows que utiliza Visual Basic, y nos permite
crear aplicaciones que tomen datos una de otras.
Para pasar datos de una aplicación a otra se necesitan al menos, dos aplicaciones (lógico), una que se
deje leer, y la otra (u otras), que quieran leer la información en aquella.
Puede darse el caso que una aplicación esté recibiendo datos de otra aplicación, y a su vez envíe datos
a una tercera.
A la aplicación que envía la información se le llama aplicación servidor, y a la que la recibe, aplicación
cliente.
La aplicación servidor debe estar funcionando antes de que la aplicación cliente le pida la información. Si
no es así, se generará un error.
Los datos a traspasar de una aplicación a otra pueden ser:


Textos, de un Label o un TextBox.
Imágenes, de un PictureBox.
El origen de un intercambio DDE siempre es un formulario. Dentro de este formulario origen estará el
Label, TextBox o PictureBox que contiene la información a enviar.
Para indicar que un formulario es origen de información para un intercambio DDE debemos decírselo en
sus propiedades LinkMode y LinkTopic.
El destino de un texto ha de ser necesariamente un Label, un TextBox, y el destino de un gráfico debe
ser un PictureBox.
Cuando queremos que uno de estos controles sea el destino de un intercambio DDE debemos indicarlo
en sus propiedades LinkMode, LinkTopic, LinkItem, e indicarle el tiempo de espera para un
intercambio en la propiedad LinkTimeout.
Propiedad LinkMode
Tiene distinta forma si se trata de un control (Label, TextBox y PictureBox) ó un formulario.
Para un formulario tiene dos valores posibles :
0 = None
1= Source
No puede existir comunicación DDE con ese formulario
El formulario permite que exista una comunicación DLL entre uno de
sus controles y otra aplicación.
Si se establece el valor de esta propiedad a 0 en tiempo de diseño, no podrá cambiarse en tiempo de
ejecución. Si se establece a 1 en tiempo de diseño, se podrá cambiar a 0 y volver a ponerla a 1 en
tiempo de ejecución.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 142
Para un control, la propiedad LinkMode le permite que inicie una conversación DDE con una aplicación
servidor, (origen), y cómo iniciarla. Tiene 4 valores posibles :
0=None.
No existe comunicación DDE con ese control
1=Automático
Los datos se traspasarán desde la aplicación servidor a este control de
la aplicación cliente cada vez que cambie el dato en la aplicación
servidor (origen)
2=Manual
Los datos se traspasarán cuando lo pida la aplicación cliente (destino),
mediante la orden LinkRequest.
3=Notify
Cuando existe un cambio en los datos de la aplicación origen, ésta
notifica a la aplicación destino que el dato ha cambiado, pero no le envía el dato
nuevo. En el control de la aplicación destino donde debe llevarse la información,
se genera el evento LinkNotify, en cuyo procedimiento podremos escribir el
código necesario dependiendo de nuestra aplicación. Para traer la información,
debe ejecutarse la orden LinkRequest. (Véase mas adelante)
En tiempo de ejecución, para un control, esta propiedad es de lectura y escritura, es decir, se puede usar
para saber que valor tiene esta propiedad en un determinado control, o para forzar esa propiedad a un
determinado valor.
La sintaxis de esta propiedad es :
objeto.LinkMode [= número]
donde número es un entero que especifica el tipo de conexión. (0, 1, 2 ó 3 según se ha visto)
y objeto es el nombre del control.
Propiedad LinkTopic
Esta propiedad es de lectura y escritura, tanto para los controles como para los formularios.
Cuando un control destino quiere establecer una comunicación DDE “llama” a la aplicación origen, y
dentro de ella, al formulario que contiene el control cuya información debe ser traspasada. (Nótese que
la aplicación origen puede tener varios formularios). Al ese formulario podría llamarle por su nombre,
(por su Name), pero no lo hace así. Le llama por un nombre que le debemos poner al formulario en su
propiedad LinkTopic. A este nombre se le denomina Tema.
La propiedad LinkTopic, para un formulario de origen, devuelve o establece el tema al que el formulario
“responde” en una conversación DDE.
Sintaxis
NombredelFormulario.LinkTopic [= tema]
Para un control destino, La propiedad LinkTopic contiene el nombre de la aplicación y el tema, ambos
separados mediante el carácter | (carácter 124)
Sintaxis
NombredelControl.LinkTopic [= aplicacionorigen|tema]
El nombre de la aplicación origen será el nombre del de proyecto de Visual Basic sin la extensión .VBP
(si la aplicación se está ejecutando en el entorno de desarrollo de Visual Basic), o el nombre de la
aplicación de Visual Basic sin la extensión .EXE (si se ejecuta como un archivo ejecutable
independiente).
El tema será el mismo al que “responde” el formul ario donde se encuentra el control que contiene la
información a traspasar.
(DDE es una utilidad de Windows. Windows establece que el estándar de un vinculo DDE es
Aplicación | Tema | elemento. Véase para mas detalles el manual de Windows, enlaces DDE)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 143
Propiedad LinkItem
La propiedad LinkItem solamente la tiene el control destino de la información. No la tiene el formulario
origen. En esta propiedad deberá expresarse el nombre del control origen de la información.
Esta propiedad es de lectura y escritura, es decir, tanto sirve para saber el nombre del control origen de
los datos, como para establecerlo en tiempo de ejecución.
Sintaxis
objeto.LinkItem = cadena
donde cadena es el nombre del control origen que tiene los datos y objeto es el nombre del control al que
le estamos poniendo la propiedad LinkItem.
Propiedad LinkTimeout
Devuelve o establece la cantidad de tiempo que un control espera una respuesta a un mensaje DDE.
Sintaxis
objeto.LinkTimeout = número
donde número es una expresión numérica que especifica el tiempo de espera en décimas de segundo.
El tiempo de respuesta DDE desde aplicaciones origen varía. Use esta propiedad para ajustar el tiempo
que un control destino espera la respuesta de una aplicación origen. Si se usa LinkTimeout de forma
correcta se puede evitar la generación de un error por Visual Basic si una aplicación origen tarda mucho
en responder.
Nota La plazo mayor de tiempo que un control puede esperar es 65.535 décimas de segundo, es decir,
sobre 1 hora y 49 minutos. Al establecer LinkTimeout a 1 se indica al control que espere la respuesta
en una conversación DDE durante el mayor plazo de tiempo. El usuario puede forzar que el control deje
de esperar presionando la tecla ESC..
Evento LinkNotify
Ocurre cuando el origen ha cambiado el dato definido por el vínculo DDE si la propiedad LinkMode del
control destino está establecido a 3 (Notificar).
Private Sub objeto_LinkNotify([índice As Integer])
End Sub
En este procedimiento se puede escribir el código necesario para nuestra aplicación, a sabiendas de que
este evento se produce cuando cambia la información en origen. Posiblemente no quiera depositarlo de
inmediato en el control destino, puesto que si fuese así habría puesto la propiedad LinkMode a 1.
Cuando quiera colocar el dato en el control destino, puede utilizar el método LinkRequest para obtener el
nuevo dato de la fuente.
Método LinkRequest
Pide a la aplicación origen de una conversación DDE que actualice el contenido de un control Label,
PictureBox o TextBox.
Sintaxis
objeto.LinkRequest
Siendo objeto el nombre del control destino de la aplicación.
Objeto es el nombre de un control Label, PictureBox o TextBox involucrado en una conversación DDE
como destino. LinkRequest provoca que la aplicación origen envíe los datos actuales al objeto,
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 144
actualizando la propiedad Caption si objeto es un control Label, la propiedad Picture si objeto es un
control PictureBox o la propiedad Text si objeto es un control TextBox.
Si la propiedad LinkMode del objeto está definida como 1 (Automático), la aplicación origen actualiza
objeto automáticamente y LinkRequest no es necesario. Si la propiedad LinkMode del objeto está
definida como 2 (Manual) , la aplicación origen actualiza objeto sólo cuando se usa LinkRequest.
Si la propiedad LinkMode del objeto está definida como 3 (Notify), el origen notifica al destino que los
datos han cambiado invocando el método LinkNotify. El destino debe entonces usar el método
LinkRequest para actualizar los datos.
Método LinkSend
Transfiere el contenido de un control PictureBox a la aplicación destino de una conversación DDE.
Sintaxis
objeto.LinkSend
Objeto debe ser un control PictureBox de un objeto Form que sea origen de una conversación DDE.
Cuando otras aplicaciones establecen vínculos automáticos con un objeto Form de su aplicación, Visual
Basic las notifica cuando el contenido de un control TextBox o Label origen cambia. Sin embargo, Visual
Basic no notifica automáticamente a una aplicación destino DDE cuando el valor de la propiedad Picture
de un control PictureBox origen cambia. Como la cantidad de datos de un gráfico pueden ser muy
grande y como no tiene sentido actualizar la aplicación destino por cada cambio de píxel de la imagen,
Visual Basic requiere el uso del método LinkSend para notificar explícitamente a las aplicaciones
destino DDE cuándo cambia el contenido de un control PictureBox.
Método LinkPoke
Transfiere el contenido de un control Label, PictureBox o TextBox a la aplicación origen de una
conversación DDE.
Sintaxis
objeto.LinkPoke
Objeto es el nombre del control Label, PictureBox o TextBox involucrado en la conversación DDE como
destino. Si objeto es un control Label, LinkPoke transfiere el contenido de la propiedad Caption al origen.
Si objeto es un control PictureBox, LinkPoke transfiere el contenido de la propiedad Picture al origen. Si
objeto es un control TextBox, LinkPoke transfiere el contenido de la propiedad Text al origen.
Normalmente, en una conversación DDE la información fluye de origen a destino. Sin embargo,
LinkPoke permite que un objeto destino suministre datos al origen. No todas las aplicaciones origen
aceptan información de esta forma; si la aplicación origen no acepta los datos, se produce un error.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 145
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 146
EL DRAG & DROP
(Arrastrar y Soltar)
El Drag & Drop es una forma visual de representar el movimiento de algo. Para ello se toma algo de una
parte de la interface gráfica, mediante la operación de colocar el puntero del ratón y pulsar su botón
izquierdo sobre ese algo que se quiere tomar. Sin dejar de pulsar el botón izquierdo del ratón se desliza
(se arrastra) el puntero del ratón hasta el punto de la interface gráfica donde lo queremos dejar. Ese
punto puede ser un control o un formulario. Una vez en el punto de destino se suelta el botón del ratón y
se “deja caer” lo que habíamos tomado en el punto de origen. El efecto de “tomar” algo de un control le
denominaremos Drag. Si durante la operación de arrastre pasamos por encima de un control, se
producirá en ese control el evento DragOver Al efecto de dejar caer le denominaremos DragDrop.
El Drag & Drop tiene un efecto visual muy didáctico. Pero NO HACE otra cosa. Es decir, no toma nada
del control origen ni lo suelta al llegar a destino. Esa acción de tomar algo en el origen o soltarlo al llegar
al destino debemos realizarla mediante código en los eventos adecuados (MouseDown, DragOver ,
DragDrop), dando los valores adecuados a las propiedades DragMode y DragIcon, y utilizando el
método Drag.
Propiedad DragMode
Es una propiedad de lectura y escritura. Devuelve o establece un valor que determina si se usa el modo
de arrastre manual o automático en una operación de arrastrar y soltar.
Sintaxis
NombreControlOrigen.DragMode = número
Donde número puede tomar los valores 0 (Manual) ó 1 (Automático).
El valor predeterminado es el 0.
Cuando esta propiedad está a 0 (Manual) se debe emplear el Método Drag para iniciar una operación
Drag & Drop. Si está a 1, la operación de arrastrar y soltar se inicia automáticamente cada vez que
hacemos click sobre el botón izquierdo del ratón, teniendo el puntero del mismo sobre el control. Los
controles contenedores OLE sólo se arrastran automáticamente cuando no tienen el enfoque.
Parece en principio mas práctico tener esta propiedad a 1. Sin embargo la realidad es distinta. Se
controla mucho mejor el Drag & Drop poniendo esta propiedad a 0 (Manual), pese a que en este caso
deberemos utilizar el método Drag para iniciar el proceso.
El poner esta propiedad en automático conlleva también el hecho de que el control no toma el foco
haciendo click sobre él, ya que no sabe si lo que quiere hacer es llevarle el foco o iniciar una operación
de Drag & Drop.
Propiedad DragIcon
Devuelve o establece el icono que se presenta como puntero del ratón durante una operación de
arrastrar y soltar.
Sintaxis
NombreControlOrigen.DragIcon = icono
Donde Icono es cualquier referencia a un icono válido.
Esta propiedad va a marcar el icono que aparezca durante la operación Drag & Drop desplazándose a lo
largo de la ventana. Si no se especifica esta propiedad, el desplazamiento se expresa mediante un
rectángulo del tamaño del control origen, cosa que resulta bastante desagradable en cualquier
aplicación. Debe ponerse por lo tanto un icono en esta propiedad.
El valor de esta propiedad puede establecerse en tiempo de diseño, eligiendo el icono en el cuadro de
Propiedades del control origen, o en tiempo de ejecución. En este caso, la referencia a un icono válido
puede darse igualando el valor de esta propiedad a un icono ya existente en la aplicación
(NCO.DragIcon = Form1.Icon pondría como icono el del formulario Form1, NCO.DragIcon =
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 147
Text1.DragIcon pondría el mismo icono de Text1 para esta propiedad), o cargándolo mediante la
función LoadPicture :
(NCO.DragIcon = LoadPicture (C :\Iconos\Icono1.ICO)
El archivo que se cargue debe tener la extensión .ICO y formato de icono.
Para Nota. Cuando quiera colocar un icono animado en la propiedad DragIcon (una hoja de papel que
oscila al moverse, una hoja de papel que se destruye - ejemplos tomados de W95-), debe usar varios
iconos en secuencia. Por lo tanto debe cambiar la propiedad DragIcon a lo largo del tiempo que dura el
arrastre. Puede utilizar para ello un temporizador (control Timer) o basarse en las coordenadas del
formulario por donde se mueve (para eso introducen en el evento DragOver del Formulario). Dado que el
cambio debe ser rápido, no es conveniente acceder al disco (mediante la función LoadPicture) cada vez
que tiene que cambiar la imagen del icono. Como para simular un movimiento tan sencillo son
suficientes pocas imágenes, (8 por ejemplo) puede crear otras tantas variables tipo Picture, cargar las
imágenes al comienzo de la aplicación (con la función LoadPicture) y cuando necesite el movimiento
animado del icono, cargar las 8 imágenes secuencialmente desde esas variables, para simular el
movimiento
NCO.DragIcon = Variable1
NCO.DragIcon = Variable2
......
NCO.DragIcon = Variable8
Esto le ocupará mas memoria. Es el precio a pagar por la rapidez y la buena presentación de una
aplicación.
Método Drag
Inicia, termina o cancela una operación de arrastre de cualquier objeto excepto los controles Line, Menu,
Shape o Timer.
Sintaxis
NombreControlOrigen.Drag TipoAcción
NombreControlOrigen es el nombre del control donde se inició la operación Drag & Drop.
TipoAcción es un valor o una constante que especifica la acción a realizar, según se describe a
continuación :
Constante
Valor
Descripción
vbCancel
vbBeginDrag
vbEndDrag
0
1
2
Cancela la operación de arrastre.
Inicia el arrastre del objeto.
Termina el arrastre y suelta el objeto.
Si se omite TipoAcción, la acción predeterminada es iniciar el arrastre del objeto.
El uso del método Drag para controlar una operación de arrastrar y soltar sólo se requiere cuando la
propiedad DragMode del control origen tiene el valor Manual (0). Sin embargo, Drag puede usarse con
objetos cuya propiedad DragMode tenga el valor 1 (o vbAutomatic).
En versiones anteriores de Visual Basic, Drag era un método asíncrono y las instrucciones siguientes se
ejecutaban incluso aunque la acción de arrastre no hubiera terminado. En Visual Basic versión 4.0, Drag
es un método síncrono y las instrucciones siguientes no se ejecutan hasta que la acción de arrastre no
haya terminado.
Usando el método Drag puede controlar exactamente cuando quiere que se produzca el inicio del Drag &
Drop y el final. El autor de esta Guía del Estudiante vuelve a recomendar que ponga la propiedad
DragMode = 0 (Manual). Entre otras razones por la siguiente :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 148
Cuando tenemos la propiedad DragMode de un TextBox a 1 (automático) ese TextBox no podrá coger el
foco, (al menos de forma fácil) y si lo consigue no puede seleccionar el texto que tiene actualmente, ya
que VB no puede saber si lo que está ocurriendo es que queremos seleccionar el texto o si deseamos
iniciar la operación D & D.
Como decíamos al principio, el Drag & Drop solamente es una manifestación visual de algo que se está
produciendo, pero ese algo deberemos programarlo. Por ejemplo, es muy típico llevar un dato de una
casilla a otra (de un TextBox a otro p.e.) mediante una operación D & D.
El dato debemos llevarlo a una variable que nos permita, al final de la operación, introducir ese dato en el
TextBox final. (No olvide declarar la variable en el lugar correspondiente para que sea válida en ambos
controles). La acción de llevar el dato a la variable debemos hacerla en el procedimiento mas adecuado.
Puede ser por ejemplo, el procedimiento MouseDown del control origen, ya que cualquier operación de
D & D comienza haciendo click en el control origen. Si tiene la propiedad DragMode de ese control en
Manual, en el momento de hacer Click, ese control toma el foco y, caso de un TextBox, puede arrastrar
con el ratón para cambiar el texto, cosa que no podría hacer si pone DragMode=1.
Evento DragOver
Cuando una operación de arrastrar y soltar está en progreso y el cursor del ratón pasa por encima de un
control o un formulario, se produce el evento DragOver de ese control o formulario.
Dependiendo si se trata de un Formulario convencional, un Formulario MDI o un control, el
procedimiento DragOver captura distintos parámetros :
Private Sub Form_DragOver(origen As Control, x As Single, y As Single, estado As Integer)
Private Sub MDIForm_DragOver(origen As Control, x As Single, y As Single, estado As Integer)
Private Sub Control_DragOver([índice As Integer,]origen As Control, x As Single, y As Single, estado As
Integer)
Donde :
origen = Control que se está arrastrando. O dicho de forma mas ortodoxa, control en el que se inició la
operación de Drag & Drop. Dentro de este procedimiento puede hacer referencia a sus propiedades y
métodos con este argumento. Por ejemplo, Source.Visible = False. Caso de que el Control Origen fuese
parte de un array de controles, el Index de ese control se tiene en índice
Número que especifica la posición horizontal (x) y vertical (y) actual del puntero del mouse
x, y
dentro del control o formulario destino. Estas coordenadas se expresan siempre en términos del sistema
de coordenadas del destino tal y como se establece en las propiedades ScaleHeight, ScaleWidth,
ScaleLeft y ScaleTop.
estado Entero que nos indica el estado de transición del control que se está arrastrando en relación al
formulario o control destino:
0 = Entra. Este valor se produce en el instante en el que entra el cursor del ratón a
este control o Formulario. Se genera también en el control origen en el instante que se
pulsa el botón del ratón, iniciándose de esta forma el D & D.
1 = Deja Este valor se produce cuando el cursor sale del control o Formulario.
2 = Sobre Este valor se produce cuando el cursor se está moviendo sobre el control o
el Formulario destino.
Mediante el parámetro origen (completado con índice si el origen se trata de un array) podemos
conocer el control desde el que se inició la operación de Drag & Drop. Debemos tener siempre presente
que el procedimiento DragOver se realiza cada vez que pasamos por encima de un control o formulario
durante una operación de Drag & Drop, independientemente que ese control o formulario sea o no sea
origen ni destino de esa operación. Puede emplearse el procedimiento DragOver para comprobar si ese
valor que transportamos puede depositarse sobre el control o formulario por el que estamos pasando, si
el valor que llevamos está dentro de los márgenes que admite la aplicación, etc. Es muy llamativo por
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 149
ejemplo, cambiar el color del control que va a recibir el valor traspasado si este valor se sale de los
márgenes aceptables. O cambiar la propiedad DragIcon del control origen cuando ese dato no se puede
depositar en ese control. Es típico poner la señal de trafico de Prohibido cuando el dato transportado no
se puede soltar sobre el control sobre el que estamos pasando el cursor del ratón. (Como el control
origen se pasa como parámetro al procedimiento DragOver con el nombre Origen basta con poner
Origen.Dragicon = ..... ) Recuerde en este caso que al abandonar ese control debe restaurar el icono
original. Para ello es útil cargar varias variables con los distintos iconos que se van a usar y luego igualar
la propiedad DragIcon del control origen a una u otra variable, dependiendo de los valores u otros
factores de la aplicación.
En el siguiente ejemplo, se declaran 6 variables tipo Picture que van a almacenar seis iconos distintos :
En General - Declaraciones
Dim pepe as string
Dim icono1 As Picture, Icono2 As Picture, Icono3 As Picture
Dim Icono4 As Picture, Icono5 As Picture, Icono6 As Picture
El Form1.Load se cargan los valores de estas variables con seis iconos existentes en el disco. El icono
asignado al control origen (Text1) es Icono4.
Set icono1 = LoadPicture("C:\vb\icons\dragdrop\drag1pg.ico")
Set Icono2 = LoadPicture("C:\vb\icons\dragdrop\drag2pg.ico")
Set Icono3 = LoadPicture("C:\vb\icons\dragdrop\drag3pg.ico")
Set Icono4 = LoadPicture("C:\vb\icons\dragdrop\drop1pg.ico")
Set Icono5 = LoadPicture("C:\vb\icons\dragdrop\dragfldr.ico")
Set Icono6 = LoadPicture("C:\vb\icons\dragdrop\dropfldr.ico")
Text1.DragIcon = Icono4
En el control destino se cambia el icono si el valor de la variable transportada (pepe) es mayor de 999 :
En el procedimiento DragOver
If Val(pepe) > 999 Then Source.DragIcon = icono1
‘Al salir de Text1 se recupera el icono original
If State = 1 Then Source.DragIcon = Icono4
Evento DragDrop
Ocurre cuando se completa una operación de arrastrar y soltar como resultado de arrastrar un control
sobre un formulario o control y liberar el botón del mouse o utilizar el método Drag con su argumento
acción establecido a 2 (Drop).
Dependiendo de si soltamos sobre un Formulario convencional, Formulario MDI o Control, este evento
captura los siguientes parámetros :
Private Sub Form_DragDrop(origen As Control, x As Single, y As Single)
Private Sub MDIForm_DragDrop(origen As Control, x As Single, y As Single)
Private Sub Control_DragDrop([índice As Integer,]origen As Control, x As Single, y As Single)
Estos parámetros son idénticos a los del Procedimiento DragOver ya comentados
Utilice un procedimiento de evento DragDrop para controlar qué ocurre tras completarse una operación
de arrastrar. Por ejemplo, puede mover el contenido del control origen a un nuevo lugar o copiar un
archivo de un lugar a otro, depositar un valor sobre un control etc.
Recuerde que la operación Drag & Drop no hace otra cosa que lo que se puede ver en la interface
gráfica. Debe poner en este Procedimiento (DragDrop) el código necesario para que se realice la
operación deseada.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 150
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 151
EL OLE Drag & Drop
El Drag & Drop visto hasta ahora permite llevar datos desde un control a otro siempre dentro de la
misma aplicación, incluyendo una interface gráfica muy didáctica para presentar ese movimiento de
información. El DDE permite llevar información desde una aplicacióna otra, pero de forma rígida, es
decir, desde un control a otro control, sin intervención del usuario, o al menos, sin una intervención
realizada de forma gráfica con el ratón.
Cuando veíamos las propiedades de los controles relacionadas con el Drag & Drop, veíamos otras que
hablaban de Drag y Drop, que eran OLEDragMode y OLEDropMode, y en el Formulario veíamos
solamente esta última: OLEDropMode. Entre los procedimientos observábamos algo parecido:
OLECompleteDrag, OLEDragDrop, OLEDragOver, OLEGiveFeedback, OLESetData y
OLEStartDrag. También existe el Método OLEDrag.
Mediante estas propiedades, procedimientos y método, podemos hacer que desde una aplicación (Word
por ejemplo) pase información a una aplicación hecha por nosotros, utilizando la misma interfase gráfica
para “ver” el movimiento de los datos. Lo mismo ocurre en sentido contrario. Desde una aplicación
nuestra podemos llevar texto o imágenes a Word. A ese mecanismo se le denomina OLE Drag & Drop.
Parece como si el OLE Drag & Drop reuniera las dos ventajas de DDE y de Drag & Drop. Esa fue la idea
con la que Microsoft creo esta herramienta.
Mediante el OLE Drag & Drop ya podemos enlazar nuestras aplicaciones a las aplicaciones compradas.
Pero piense que lo que va a conseguir con el OLE Drag & Drop ya lo tiene prácticamente igual con el
portapapeles. Por lo tanto, no se haga demasiadas ilusiones. Y además recuerde que el mecanismo de
arrastrar y soltar no es tan fácil como copiar y pegar, al menos para personas poco hábiles.
El Objeto DataObjet
El objeto DataObjet es un contenedor que utiliza OLE para transportar datos. Recuerde, cuando
hacíamos Drag & Drop normal, en el Drag teníamos que meter lo que queríamos transportar (Texto o
imagen) en una variable y en el Drop poníamos el contenido de esa variable en el control final. Esto
puede hacerse cuando se trata de una misma aplicación, en la que el valor de la variable se mantiene
mientras estuviésemos dentro del ámbito donde se ha declarado. ¿Cómo haríamos esto para pasar un
texto a Word? Debe haber una “variable” que mantenga su contenido entre dos aplicaciones. Esa
“variable” debe ser un objeto superior a las dos aplicaciones que van a intercambiar datos. Es
concretamente el DataObjet
El objeto DataObject es un contenedor de datos donde se pueden transportar datos desde un
componente de origen a un componente de destino.
El DataObject tiene sus propiedades y métodos.
Métodos del DataObject
Método SetData
Inserta datos en un objeto DataObject con el formato de datos especificado.
Sintaxis
objeto.SetData [datos], [formato]
objeto es un objeto tipo DataObjet. Este objeto no es necesario declararlo, ya que aparece en todos los
procedimientos donde es posible introducir o sacar datos del DataObject.
Por ejemplo, en el método OLEStartDrag se pasa como parámetro un objeto DataObject llamado Data.
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
Data.SetData Text1.Text, vbCFText
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 152
Data es un objeto tipo DataObject donde se ha metido el texto que contienen el Text1. Ese objeto
llamado Data lo ha pasado el procedimiento (Data As DataObject) por lo que podemos meterle los datos
sin necesidad de crearlo previamente. Este objeto es único para Windows, por lo que a partir de la
ejecución de ese procedimiento OLEStartDrag el texto introducido en Data está disponible para cualquier
aplicación Windows que sepa recogerlo.
datos es el dato a introducir en el DataObject. En el ejemplo anterior, era el texto contenido en Text1
formato es un valor o constante que especifica el tipo de datos introducidos. Este argumento es
opcional. Vea valores posibles en el cuadro más abajo.
Método GetData
Devuelve datos de un objeto DataObject en forma de Variant.
Sintaxis
objeto.GetData (formato)
objeto es el objeto tipo DataObject
formato es un valor o constante, que determina el formato de los datos que se van a obtener. Los
valores para formato se pueden ver en el cuadro más abajo.
Un ejemplo de GetData. En el procedimiento OLEDragDrop de un RichTextBox con la propiedad
OLEDropMode existe este código para poner el texto que llevaba el DataObject en el RichTextBox.
Observe que también se pasa en este procedimiento, un parámetro llamado Data del tipo DataObject.
Private Sub RTB1_OLEDragDrop(Data As RichTextLib.DataObject, Effect As Long, Button As Integer,
Shift As Integer, x As Single, y As Single)
RTB1.SelText = Data.GetData(vbCFText)
End Sub
Loa valores o constantes para formato en ambos métodos son:
Valor
1
2
3
14
8
9
15
-16639
Constante
vbCFText
vbCFBitmap
vbCFMetafile
vbCFEMetafile
vbCFDIB
vbCFPalette
vbCFFiles
vbCFRTF
Descripción
Texto (archivos .txt)
Mapa de bits (Archivos .bmp)
Metaarchivo (archivos .wmf)
Metarchivo mejorado (archivos .emf)
Mapa de bits independiente del dispositivo (DIB)
Paleta de colores
Lista de archivos
Formato de texto enriquecido (archivos .rtf)
Método Clear
Elimina el contenido del objeto DataObject.
Sintaxis
objeto.Clear
Puede ejecutar este método antes de introducir nuevos datos en el DataObject para asegurarse que ha
borrado los datos existentes
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
Data.Clear
Data.SetData Text1.Text
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 153
End Sub
Este método sólo está disponible para los orígenes de operaciones de arrastre de componentes. Si se
invoca Clear desde un destino de la operación de colocación de componentes, se producirá un error.
Método GetFormat
Devuelve un valor booleano que indica si un elemento del objeto DataObject coincide con un formato
especificado.
Sintaxis
objeto.GetFormat formato
Ejemplo
Puede asegurarse que el formato contenido en el DataObject es el deseado antes de
proceder a colocarlo en un control en la operación de Drop:
Private Sub RTB1_OLEDragDrop(Data As RichTextLib.DataObject, Effect As Long, Button As Integer,
Shift As Integer, x As Single, y As Single)
If Data.GetFormat(vbCFText) = True Then
RTB1.SelText = Data.GetData(vbCFText)
End If
End Sub
Propiedades del DataObject
Deberíamos decir mejor, propiedad, ya que solamente tiene una:
Propiedad Files
Devuelve una colección DataObjectFiles, que a su vez contiene una lista con todos los nombres de
archivo utilizados por un objeto DataObject (por ejemplo los nombres de los archivos que un usuario
arrastra hacia o desde el Explorador de archivos de Windows).
Sintaxis
NombredelObjetoDataObject.Files(índice)
La colección Files sólo se puebla con nombres de archivo cuando el objeto DataObject contiene datos
de tipo vbCFFiles. La colección Files puede rellenarse para permitir a las aplicaciones de Visual Basic
actuar como origen de operaciones de arrastre de una lista de archivos.
Colección DataObjectFiles
Es la colección de cadenas con los nombres de ficheros de la propiedad Files del objeto DataObject.
Sintaxis
NombredelObjetoDataObject.DataObjectFiles
La colección DataObjectFiles es una colección de cadenas que representan un conjunto de archivos
seleccionados mediante el método GetData o en una aplicación, como el Explorador de Windows.
Aunque la colección DataObjectFiles tiene sus propios métodos y propiedades, debe usar la propiedad
Files del objeto DataObject para ver y manipular el contenido de la colección DataObjectFiles.
Aunque se ha pretendido realizar un ejemplo de esta propiedad, el autor cede ese honor al alumno
interesado en el tema. No he podido obtener los elementos de la colección DataObjectFiles.
Volvamos sobre las propiedades y métodos de los controles involucrados en un OLE Drag & Drop
Propiedad OleDragMode
Esta propiedad establece la forma en la que comienza a realizarse la operación de Drag. Si está en
Automático basta con seleccionar el texto o la imagen a pasar a otra aplicación y una vez seleccionado,
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 154
al volver a marcarlo con el ratón, se inicia el Drag. En ese instante se ejecuta el procedimiento
OLEStartDrag donde deberemos colocar el código para que VB haga lo que nosotros queramos. Ya se
verá al estudiar este procedimiento.
A diferencia del Drag & Drop estudiado anteriormente, donde recomendábamos poner la propiedad
similar a manual, en este caso es mucho más práctico ponerlo en automático y además no es molesto,
ya que el Drag no se inicia si no se ha seleccionado previamente parte del texto o la imagen a enviar a la
otra aplicación.
La propiedad DragMode de ese control debe estar ahora a Manual, ya que si está en automático se
genera antes el Drag & Drop ordinario y no se producirá el OLE Drag & Drop.
Si se pone esta propiedad a Manual es necesario iniciar el drag mediante el método OLEDrag, que
ejecuta el procedimiento OLEStartDrag, y colocar en este el código correspondiente. No es práctico,
pero cada aplicación y cada programador es una caso distinto.
Propiedad OLEDropMode
Esta propiedad va a determinar la forma en la que el componente destino toma los datos transportados
medainte OLE Drag & Drop. Acepta tres valores:
0
1
2
vbOLEDropNone
El componente no acepta operaciones de Drop. Cuando pasa el
cursor del ratón sobre él durante una operación de OLE Drag &
Drop, muestra el icono de No Colocar
Manual. El componente de destino desencadena los eventos
vbOLEDropManual
OLE de colocar, (Evento OLEDragDrop) lo que permite al
programador controlar la operación en el código.
vbOLEDropAutomatic Automático. El componente de destino acepta automáticamente
las operaciones OLE de colocar si el objeto DataObject
contiene datos en un formato que reconoce. En este caso, en el
destino no se producen los eventos del mouse ni eventos OLE
de arrastrar y colocar.
Es normal poner esta propiedad a manual, para poder controlar lo que ocurre con la información tanto en
destino como en origen. Estando en Automático, la información en el origen se mueve al destino, es
decir, desaparece del origen al tiempo que se pone en el destino. Esto puede que no sea lo deseado por
el programador. Si pone esta propiedad en Manual, puede controlar lo que hace la información tanto en
destino como en origen.
Eventos relacionados con el OLE Drag & Drop.
Una cosa que podemos advertir en todos los eventos relacionados con el OLE Drag & Drop es la
ausencia del parámetro Source que teníamos en los eventos DragDrop y DragOver del Drag&Drop
convencional. Parece normal, ya que no tenemos porque saber el nombre del control origen si éste es
de una aplicación externa (Word por ejemplo). Ese parámetro Source lo empleábamos para saber si un
control podía recibir o no la información, dependiendo del origen de la misma. En el OLE Drag & Drop
solamente podemos basarnos para eso en el tipo de información que transporta el DataObject, tipo que
podemos determinar mediante el método GetFormat.
Evento OLEStartDrag
Se produce cuando se ejecuta el método OLEDrag de un componente o cuando un componente inicia
una operación OLE de arrastrar y colocar, y su propiedad OLEDragMode está establecida a Automatic.
Sintaxis
Private Sub objeto_OLEStartDrag(datos As DataObject, efectosPermitidos As Long)
Vemos que pasa como parámetro el objeto datos que es del tipo DataObject. Por lo tanto podemos
realizar sobre este objeto el método SetData visto anteriormente, para introducir en él los datos
deseados. Veamos un ejemplo:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 155
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
Data.Clear
Data.SetData Text1.Text
AllowedEffects = 1
End Sub
El parámetro EfectosPermitidos va a determinar lo que ocurre con el dato en el control origen. Acepta 3
valores:
0
1
vbDropEffectNone
vbDropEffectCopy
2
vbDropEffectMove
No se inicia el OLE Drag & Drop
Los datos se copian en el destino y no se modifican en el
control origen.
Los datos se colocan en el destino y desaparecen del control
origen. Ocurre el efecto de mover los datos.
Evento OLEDragOver
Se produce cuando el puntero del ratón pasa por encima de un control durante una operación de OLE
Drag & Drop.
Sintaxis
Private Sub nombredelcontrol_OLEDragOver( datos As DataObject, efecto As Long, botón As Integer,
mayúsculas As Integer, x As Single, y As Single, estado As Integer)
Este evento solamente ocurre cuando la propiedad OLEDropMode está en manual
nombredelcontrol
datos
efecto
boton
mayusculas
x, y
Nombre del control sobre el que pasa el puntero del ratón, en el que se
produce el evento OLEDragOver.
Objeto tipo DataObject que transporta los datos
Este parámetro es similar al AllowedEffects del evento OLEStartDrag y
tiene los mismos valores.
Indica el botón que se está pulsando: 1 = izdo. 2 = Dcho. 4 = Central.
Si está pulsado más de uno, será la suma de los valores de cada uno.
Indica el estado de pulsación de las teclas MAYUSCULAS, CTRL y ALT
1 = MAY, 2 = CTRL, 4 = ALT. Si hay más de una tecla pulsada, será
la suma de los valores de cada una.
Posición del puntero del ratón dentro del control destino, medidas en las
unidades de medida del formulario.
estado
Valor que indica uno de los tres estados siguientes:
0
1
2
vbEnter
vbLeave
vbOver
El ratón está entrando al control
El ratón está saliendo del control
El ratón está dentro del control
Evento OLEDragDrop
Se produce cuando se termina la operación de OLEDrag&Drop sobre el control. Para que se pueda
terminar la operación de OLEDrag&Drop el componente destino tienen que permitirlo.
Nota Este evento sólo se produce cuando OLEDropMode está establecido a 1 (Manual).
Sintaxis
Private Sub objeto_OLEDragDrop(datos As DataObject, efecto As Long, botón As Integer,
mayúsculas As Integer, x As Single, y As Single)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 156
En este evento podemos escribir el código necesario para que el dato se coloque de la forma deseada
(por ejemplo, puede analizar el tipo de dato y proceder de acuerdo al contenido del DataObject).
Los parámetros pasados por este evento son iguales al del evento anterior.
Evento OLECompleteDrag
Se produce en el origen cuando se ha completado la operación de arrastre (cuando se levanta el botón
del ratón), e informa al componente de origen de que se ha completado o cancelado dicha operación.
Sintaxis
Private Sub objeto_OLECompleteDrag([efecto As Long])
Efecto es idéntico a los eventos anteriores.
En el ejemplo siguiente, el control origen (Text1) se pone rojo cuando se termina el OLEDrag&Drop:
Private Sub Text1_OLECompleteDrag(Effect As Long)
Text1.BackColor = 255
End Sub
Evento OLEGiveFeedback
Este evento se produce en el control Origen. Se produce después de cada evento OLEDragOver.
OLEGiveFeedback permite al componente de origen proporcionar al usuario una indicación visual, como
cambiar el cursor del mouse para indicar lo que ocurrirá si coloca el objeto o señalar visualmente la
selección (en el componente de origen) para indicar lo que va a ocurrir.
Sintaxis
Private Sub objeto_OLEGiveFeedback( efecto As Long, cursoresPredeterminados As Boolean)
efecto
igual a los eventos anteriores.
CursoresPredeterminados
Valor booleano que determina si Visual Basic utiliza el cursor
predeterminado del mouse que indica el componente o si utiliza un cursor definido por el usuario.
True (predeterminado) = utiliza el cursor predeterminado.
False = no utiliza el cursor predeterminado. Debe haber establecido un cursor de mouse con la
propiedad MousePointer del objeto Screen .
En este capítulo hemos visto tres formas de transvasar información, bien de una aplicación a otra, bien
dentro de la misma aplicación.
Es posible que le haya llamado la atención estas herramientas. Y posiblemente piense en un enorme
número de posibilidades de aplicación. La realidad le va a demostrar que se aplican muy pocas veces.
Exceptuando el OLEDrag&Drop, que le permite exportar texto a / desde Word, y eso le vienen muy bien
al usuario porque le ahorra tiempo de teclear, los demás no se usan con la profusión que se debería,
vistas a priori las ventajas que tienen.
Como siempre en programación, lo bueno es lo que acepta y le gusta al usuario. Y el realizar un arrastre
con el ratón es una operación que no todos terminan con éxito. Quizás sea esa la razón de no usarlo tan
profusamente.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 157
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 158
EL EDITOR DE MENUS
El Menú o Barra de Menú es la segunda línea de cualquier ventana Windows, donde pueden verse
distintos nombres. La Barra de Menú es un componente de un Formulario.
La Barra de Menú puede tener tantas palabras como se desee, y sobre cada palabra, puede desplegarse
un Menú desplegable con mas palabras. Sobre cada una de estas puede a su vez desplegarse otro
conjunto de palabras, etc. con lo que se puede conseguir una cantidad de palabras tan grande como
necesitemos.
Para cada palabra se produce el evento click. Cada palabra de la Barra de Menú lleva anexo un único
procedimiento, que se ejecutará al hacer click sobre la palabra. Pero en las palabras que sirven para
desplegar un menú no tiene sentido que se ponga ningún código en su procedimiento, ya que están ahí
justamente para desplegar otras palabras. Será en las palabras finales donde se colocará el código
correspondiente.
En las figuras anteriores pueden verse tres formas distintas de ver el mismo Menú. En la primera figura
el Menú está sin desplegar. En la segunda figura puede verse un árbol de Menú largo, desplegado en su
totalidad. En la tercera puede verse el Menú desplegable de la palabra Archivo de la Barra de Menú.
Puede apreciarse en este menú desplegable una línea que separa las palabras Guardar Como y
SALIR. Esta línea separadora es muy práctica para separar dos temas distintos dentro de un Menú
desplegable. Tan distintos como las operaciones de Abrir y Guardar respecto a la última orden del menú
desplegable que es SALIR de la aplicación.
Para crear un menú debe usarse el Editor de Menú, que se encuentra en la Barra de Menú de VB en
Herramientas | Editor de menús. Le aparecerá el siguiente cuadro. (En principio vacío)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 159
Cada palabra del menú tiene su Caption (La palabra que aparece en el menú), su Name (Nombre), y
puede tener Index (si existen varias palabras con el mismo Name). Para introducir estas propiedades
basta con teclearlas directamente en cada una de las casillas al efecto del cuadro del editor de menús.
Para colocar el cursor de escritura en una u otra casilla, puede hacerse bien con el cursor del ratón, bien
con el tabulador. Para pasar a la siguiente línea de edición (crear una nueva palabra), basta con pulsar
ENTER.
Existen otras propiedades aparte del Caption y Name que se introducen directamente en las casillas al
efecto.
HelpContextID Igual que esta propiedad en el resto de los controles, permite introducir un número de
contexto para la ayuda de Windows.
Enabled.
Habilitado. Si se quita la marca de esa casilla, esa palabra aparecerá por defecto
deshabilitada. Esta propiedad puede leerse y cambiarse en tiempo de ejecución, por lo que esta
propiedad puede usarse para deshabilitar ciertas funciones de la aplicación, dependiendo de la evolución
de la propia aplicación. La presentación en el menú cuando está deshabilitada es con color pálido.
Visible.
ejecución.
Como su nombre indica, que sea visible o no lo sea. Puede cambiarse en tiempo de
WindowList Indica si esa palabra es la que va a mostrar todos los formularios abiertos en una
aplicación de documentos múltiples (MDI). Al hacer click sobre esta palabra, se desplegará un
submenú con todos los Caption de los Formularios hijo abiertos en ese momento. Solamente puede
existir una palabra en un menú con esta propiedad activada. Esta propiedad n o pu ede variarse en
tiempo de ejecución.
Para cambiar una de estas propiedades en tiempo de ejecución, basta con citar por su nombre a esa
palabra (por su Name, no por su Caption), e igualar a True o False su valor :
nmuDocumentos.Visible = False
El nombre usado para nombrar a una de las palabras del menú puede ser cualquiera. Sin embargo es
prudente usar un nombre que nos pueda identificar, por una parte, que ese nombre corresponde a una
de las palabras del menú, y por otra, a que palabra se refiere. La solución puede ser cualquiera. El autor
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 160
de estos apuntes propone poner las letras mnu (o menu - recomiendo no usar acentos e los Names de
VB), seguido del Caption de esa palabra.
Otras propiedades
Atajo. Esta propiedad admite varias combinaciones de teclas para acceder al
Shortcut
procedimiento click de esa palabra sin necesidad de usar el ratón. Las combinaciones de teclas posibles
se muestran haciendo click en la flecha hacia abajo que tiene esa casilla. Se desplegará una lista con
todas ellas. Para elegir una de estas combinaciones, basta con hacer click sobre la línea que la contiene.
Esta combinación de teclas aparecerá en el menú, al lado de la palabra (Véase figura siguiente, SALIR
Ctrl + X)
Establece un valor que determina si los controles Menu de nivel superior se
NegotiatePosition.
muestran en la barra de menús mientras un objeto vinculado o incrustado de un formulario está activo y
mostrando sus menús. No está disponible en tiempo de ejecución. Puede tener los valores 0
(Predeterminado) Ninguno. El menú no se muestra en la barra de menús cuando el objeto está activo.
1 Izquierda. El menú se muestra a la izquierda de la barra de menús cuando el objeto está activo.
2 Medio. El menú se muestra en medio de la barra de menús cuando el objeto está activo.
3 Derecha. El menú se muestra a la derecha de la barra de menús cuando el objeto está activo.
El menú editado con los datos de la figura anterior tendrá esta forma en tiempo de ejecución :
Observe que tiene cuatro palabras en la línea superior, y que “colgando” de la primera aparece un menú
desplegable. Para conseguir un menú desplegable fíjese en la figura del Editor, en la parte de abajo
donde están todos los Caption de las palabras del menú. Observará que algunas de ellas (&Edicion,
Documentos, Ayuda - Hay otra que no se vé, &Archivo) están completamente a la izquierda de la
ventana, y las demás están separadas de la parte izquierda por unos guiones. Las palabras que están
completamente a la izquierda son las que figurarán en la barra de menú de forma permanente. Las que
están separadas (tabuladas) corresponden a las que aparecerán en los menús desplegables. Como es
lógico, un menú desplegable debe colgar de una palabra de las de la barra de menú. La palabra de la
que cuelga el submenú es la palabra sin tabular inmediatamente anterior.
Para tabular las palabras, hay que hacer click en el botón en forma de flecha a la derecha que está sobre
la ventana de edición:
Situandonos sobre una de las líneas ya editadas, y haciendo click sobre el botón con flecha hacia la
izquierda, quitamos la tabulación.
Los botones con flecha hacia arriba o abajo nos permiten variar el orden de las líneas ya editadas.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 161
Podemos hacer varios niveles de submenús a base de introducir varias tabulaciones. Al comienzo de
este capítulo puede ver un ejemplo de ello.
Quedan un par de cosas. Una de ellas es el carácter & que está delante de los Caption de Archivo y
Edición. Este carácter nos permite acceder al procedimiento click de esa palabra pulsando la tecla Alt +
la tecla correspondiente a la letra que está detrás del carácter &. Justamente la letra que está subrayada
en la palabra del menú.
El carácter & no tiene porqué ir precisamente al comienzo de la palabra. Puede ir en el medio de la
palabra. De esta forma se subrayará una letra intermedia.
Otra cosa. Puede verse en el menú desplegado de la figura anterior una línea entre Guardar Como y
SALIR. Esta línea, que solamente tiene efectos estéticos, se logra introduciendo como Caption un guión
( - ). El editor de menús solamente le permite el guión en una palabra de menú desplegable (Tabulada).
No se olvide de poner el Name incluso para este guión.
NOTA MUY IMPORTANTE
Siempre se recomienda poner la orden de SALIR en la primera palabra de la barra de Menú. Bien que
esa primera palabra sea Salir o que esté en el menú desplegable de la primera palabra de la Barra de
Menú, en este último caso, separada mediante una línea separadora. (Vea The Windows Interface
Guidelines for Software Design, pág.124)
POPUP MENÚS
Un PopUpMenú o Menú Emergente es un menú que despliega en cualquier punto de un Formulario (MDI
o normal) con varias opciones. Es normal en los procesadores de texto que se obtenga un menú
emergente pulsando el botón derecho del ratón, donde aparecen las tres palabras mágicas de Copiar,
Cortar y Pegar.
Para crear un menú emergente o PopUpMenu es necesario tener en el menú de ese formulario una
palabra de la que se despliegue un submenú con las mismas palabras que queremos que aparezcan en
el PopUpMenu.
Por ejemplo, en el menú que hemos editado como ejemplo anteriormente, existía una palabra Edición,
de la que se desplegaba el Submenú Copiar, Cortar y Pegar. Si analizamos la edición realizada, las
palabras tenían el siguiente Caption y Name :
Caption
Name
Tabulada
Edición
Copiar
Cortar
Pegar
mnuEdicion
mnuCopiar
mnuCortar
mnuPegar
NO
SI
SI
SI
Recuerde que las palabras del menú que estaban tabuladas son las que aparecían en el menú
desplegable. Esas mismas serán las que aparezcan en el PopUpMenu.
Para ello utilizaremos el Método PopupMenu. Este método pesenta un menú emergente en un objeto
MDIForm o Form en la posición actual del mouse o en las coordenadas especificadas.
La sintaxis de este método es la siguiente :
NombreFormulario.PopupMenu nombremenú, indics, x, y, negrita
Donde NombreFormulario es el nombre del formulario donde presentamos el PopUpMenu. Puede
omitirse.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 162
Nombremenú. Este parámetro es requerido. Es el Name de la palabra del menú de donde cuelga el
menú desplegable. La palabra del menú a que se refiere Nombremenú debe tener al menos un
submenú.
Indics . Parámetro opcional. Un valor o constante que especifica la posición y el comportamiento del
menú emergente, como se describe a continuación :
Constante (posición)
Valor
Descripción
vbPopupMenuLeftAlign
0
vbPopupMenuCenterAlign 4
vbPopupMenuRightAlign 8
(Predeterminado) El lado izquierdo del menú se
sitúa en x.
El menú emergente se centra en x.
El lado derecho del menú se sitúa en x.
Constante (comportamiento)
Valor
Descripción
vbPopupMenuLeftButton
0
vbPopupMenuRightButton
2
(Predeterminado) Los elementos del
menú emergente sólo reaccionan a los
clic del mouse cuando se use el botón
primario del mouse.
Los elementos del menú emergente
reaccionan a los clic del mouse cuando se
usen los botones primario o secundario.
Para combinar la los valores de indics de posición y comportamiento basta con sumar los valores.
Nota El parámetro indics no tiene efecto en las aplicaciones que se ejecuten bajo Microsoft Windows
versión 3.0 o anteriores.
X, y Parámetro(s) opcionales que especifican las coordenadas x e y donde va a aparecer el menú
emergente. Si no se especifican, aparecerá donde esté el puntero del mouse. Las unidades de medida
de las coordenadas x e y se definen mediante la propiedad ScaleMode.
negrita . Parámetro opcional que especifica el nombre de un control menú del menú emergente para
presentar su título en negrita. Si se omite, ningún control del menú aparece en negrita.
Nota . Este argumento funciona solamente en las aplicaciones que se ejecuten bajo Windows 95. La
aplicación ignora este argumento cuando se ejecute bajo versiones de 16 bits de Windows o Windows
NT 3.51 y anteriores.
La forma mas habitual de presentar un menú emergente es mediante el botón derecho del ratón.
Concretamente en el editor Word que estoy utilizando para escribir estos apuntes ocurre cuando se
levanta el botón derecho del ratón. Es decir, en el evento MouseUp, con la condición de que Button=2.
Imaginemos que queremos presentar en un menú emergente las palabras Cortar, Copiar y Pegar del
ejemplo anterior, que colgaban en el menú de la palabra Edición. (Vea mas atrás). Queremos también
que la palabra Copiar salga resaltada en negrita. Iríamos al procedimiento MouseUp del Formulario y
escribiríamos :
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 2 Then
PopupMenu mnuEdicion, , , , mnuCopiar
End If
End Sub
Observe que se ha omitido el nombre del Formulario (Opcional), el parámetro indics, y las coordenadas
x e y (el menú emergente aparecerá donde esté situado el cursor del ratón). Observe también que las
comas separadoras de los parámetros hay que colocarlas.
Cuando se presenta un menú emergente, el código que sigue a la llamada al método PopupMenu no se
ejecuta hasta que el usuario elige un comando del menú (en cuyo caso se ejecuta antes el código del
procedimiento de evento Click) o cancela el menú. Además, sólo puede presentarse un menú emergente
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 163
al mismo tiempo; por lo tanto, las llamadas a este método se ignoran si el menú emergente está
presentado actualmente o si un menú desplegable está abierto.
Si queremos presentar un menú emergente es necesario tener ese menú en el menú del formulario. El
problema puede ser que no queramos que esté en la barra de menú. No es problema. Ponga la
propiedad Visible del elemento del menú desde el que se va a desplegar el submenú a False. No se verá
ya en la barra de menú ni esa palabra ni el submenú que de ella se despliega. Eso sí, las palabras del
submenú deben tener la propiedad Visible = True. Si les pone esa propiedad a False, no se verán en el
menú emergente. Puede aprovechar esta circunstancia para hacer menús emergentes con mas o
menos elementos, según las necesidades de su aplicación. También puede poner la propiedad Enabled
a False si así lo precisa. No puede activar la propiedad WindowList en un elemento que forma parte de
un menú emergente.
Ejercicio propuesto: un editor de texto, con un menú que diga Copiar | Cortar | Pegar donde
pueda utilizar el portapapeles. Ahora es posible que le cueste un poco de trabajo. Pero este
ejercicio lo va a repetir con casi todas las aplicaciones que realice en su vida profesional.
Visual Basic - Guía del Estudiante Cap. 6
FICHEROS EN VISUAL BASIC
Existen tres tipos de ficheros donde podremos almacenar y leer datos:
- Secuenciales
- Aleatorios (Random)
- Binarios
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 164
Cada uno de ellos tiene sus aplicaciones y particularidades.
FICHEROS SECUENCIALES
Este tipo de ficheros nos permite guardar información de cualquier longitud. En este tipo de ficheros, la
información se guarda colocando un carácter tras otro. La forma de leerlos es, igualmente, carácter tras
carácter. (Byte tras byte). Son los mas sencillos de manejar, y los utilizados para guardar texto en ASCII.
Permiten guardar datos en un fichero con un determinado nombre, "machacando" la información de otro
posible fichero que ya estuviese en el disco con el mismo nombre, o añadir la información nueva a
continuación de la ya existente.
Para abrir un fichero secuencial para guardar información, debemos ejecutar la siguiente instrucción:
Open Nombrefichero For Output As # Numerocanal
De esta forma, si ya existía un fichero llamado Nombrefichero, sobreescribiremos dicho fichero
perdiendo la información que contuviese. Es la forma típica de hacerlo cuando modificamos un texto.
Para añadir la nueva información tras la ya existente, deberemos abrirlo con la siguiente instrucción:
Open Nombrefichero For Append As # Numerocanal
Numerocanal debe ser un número comprendido entre 1 y 255. Representa el número del canal por
donde introduciremos los datos. Normalmente se llama también número de archivo . No puede haber
mas de un archivo abierto con un número de canal determinado.
Para cerrar un fichero secuencial, basta con ejecutar la instrucción:
Close # Numerocanal
Si no se especifica Numerocanal (la instrucción Close a secas) se cerrarán todos los ficheros abiertos
actualmente.
Para introducir la información, pueden emplearse dos métodos: Print y Write Nos centraremos de
momento solamente en Print.
Print
Introduce la información de forma secuencial, byte tras byte tal como se comentó. Sirve
para guardar textos. Por ejemplo si deseamos guardar en ese fichero el contenido de
una caja de texto llamada Text1, basta con ejecutar la siguiente instrucción:
Print #NumerodeCanal, Text1.Text
El texto queda en el fichero en caracteres ASCII, que se pueden leer con el Bloc de
Notas.
Cuando los datos se han introducido con la instrucción Print, la forma de acceder a ese texto es muy
sencilla:
Se abre el archivo con la instrucción Open
Open Nombrefichero For Input As # Numerodecanal
Se utiliza la instrucción Input o Line Input para sacar los datos del fichero.
La instrucción Input tiene en este caso la siguiente sintaxis:
VariableString = Input (Numero de caracteres, # Numero de canal)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 165
Por ejemplo, VariableString = Input (1, #1) extrae un carácter del fichero abierto como #1. El número
máximo de caracteres a extraer de un golpe mediante la instrucción Input está limitado a 65.534.
Verá un poco mas adelante la propiedad LOF de los ficheros secuenciales. LOF devuelve un valor igual
a la longitud total del fichero. Si ejecutamos la instrucción :
Para no emplear una palabra tan larga como Numerodecanal, utilizaremos de ahora en adelante el
número 1 como número de canal. Recuerde que ese número puede ser un número comprendido entre
el 1 y el 255
VariableString = Input (LOF(1), #1)
LOF(1)=longitud del fichero #1
leeremos el fichero de una única vez. Este procedimiento puede ahorrarle cierto tiempo a la hora de la
lectura. (Por lo dicho anteriormente, este procedimiento de leer todo el fichero de un golpe solamente se
podrá hacer si la longitud del fichero (LOF(1)) es inferior a 65.534 bytes. Tenga esto presente cuando
vaya a leer un fichero que no sabe que longitud tiene. Para curarse en salud, le recomiendo que lea los
ficheros secuenciales carácter a carácter. Input(1,#X) pues tarda poco mas que leyéndolo de un golpe.
Claro que para leer un fichero carácter a carácter debe poner un bucle en el que se van leyendo los
caracteres hasta que llaga al final del fichero..
La forma de hacer este bucle es la siguiente:
Dim A As String
A es la variable donde meteremos el carácter que extraemos del fichero.
Dim MiVariable as String
MiVariable es una variable tipo string donde vamos a meter todo el
contenido del fichero
Do Until EOF(1)
El programa ejecutará este bucle hasta que se cumpla que EOF(1) sea
True. EOF(NumerodeCanal) es una propiedad de los ficheros cuando
están abiertos, que es True cuando la posición del puntero de lectura
apunta al carácter Fin De Fichero (End Of File) que es el carácter siguiente
al último carácter de texto de ese fichero.
A = Input (1, #1)
Estrae un carácter del fichero abierto por el canal número 1. Al leer este
carácter, el puntero de lectura avanza automáticamente tantos caracteres
como haya leído, colocándose sobre el primer carácter no leído.
MiVariable = MiVariable & A
Con esta línea vamos anexando el carácter leído a la variable
MiVariable. En vez de utilizar una variable, podríamos poner ese
texto sobre un TextoBox o un RichTextBox (RTB) (Lo verá
proximamente). Si lo ponemos en un RTB esta línea sería:
RTB.SelText = A
Loop
Vuelve al comienzo del bucle.
Close #1
Cierra el fichero
Sólo se utilizará la instrucción Input con archivos abiertos en modo Input o Binary. (Los Binary Se verán
a continuación) A diferencia de la instrucción Input #, (la veremos a continuación, pues es la instrucción
que deberá utilizar para leer archivos escritos con la instrucción Write ), Input devuelve todos los
caracteres que lee, incluyendo puntos y coma, retornos de carro, avances de línea, comillas y espacios
iniciales.
Existe una instrucción, Input$ , que asume que el dato a leer es un String. (Cadena de caracteres).
Puede ahorrar un poco de memoria usando esta instrucción en lugar de Input.
Nota Se proporciona otra función (InputB) para su uso con datos de byte incluidos en archivos de texto.
En lugar de especificar el número de caracteres a devolver, número especifica el número de bytes.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 166
INSTRUCCION LINE INPUT
La instrucción Line Input se utiliza para extraer una línea completa. Tiene la siguiente sintaxis:
Line Input # Número de canal, VariableString
Mediante esta instrucción se extrae una línea completa (los caracteres delimitados entre dos retornos de
carro), y se le asigna esa cadena a VariableString
Una línea es un trozo de texto delimitado por los caracteres 13 (Retorno de carro) y 10 (Avance de línea)
La instrucción Line Input # lee un carácter cada vez en un archivo hasta que encuentra un retorno de
carro (Chr(13)) o una secuencia retorno de carro - avance de línea (Chr(13) + Chr(10)). Las secuencias
de retorno de carro - avance de línea no se tienen en cuenta y no se añaden a la cadena de caracteres
extraída mediante esta instrucción. Cuando lea un archivo mediante Line Input # y lo quiere presentar
en un TextBox o en el Printer, deberá introducirlos para evitar que le salga todo el texto en una única
línea.
Con lo que se ha explicado, ya puede realizar un pequeño edito de textos. Este sencillo editor tiene un
TextBox llamado TBTexto, donde podemos escribir el texto que queramos (con la propiedad MultiLine =
True y ScrollBars = Vertical), tres botones llamados BAbrir (1), (2 a y b) y (3), para abrir el fichero y
poner su contenido en TBTexto, y dos BGuardar para guardar, uno abriendo el fichero For Append y el
otro abriéndolo For Output. En este último, al guardar el texto borramos el contenido que del fichero, si
ya existiera. En el primero, lo anexamos al final del mismo . Para conocer el nombre del fichero,
ponemos un CommonDialog llamado CD1, con un filtro CD1.Filter = “Ficheros de Texto |*.txt”
Para abrir el fichero, y depositar su contenido en TBTexto pondremos este código en BAbrir :
Private Sub BAbrir1_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
VarTexto = Input(LOF(1), #1)
'leemos todo el fichero de un golpe
Close #1
TBTexto = VarTexto
End Sub
Cuando el fichero es mayor de 64 kilobytes, el leerlo de un golpe puede dar problemas. Mejor dicho, no
funciona. Deberemos leerlo en ese caso, carácter a carácter o línea a línea.
Para leer carácter a carácter :
Private Sub BAbrir_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
‘Hacemos un bucle de lectura hasta que encontremos EOF(1)
‘ Vea mas adelante la Propiedad EOF en Propiedades de los ficheros Secuenciales
VarTexto = Input(1, #1)
'leemos el fichero carácter a carácter
TBTexto = TBTexto & VarTexto
'vamos añadiendo los caracteres leídos a TBTexto
Loop
Close #1
End Sub
(NOTA.- Lo expuesto funciona perfectamente, pero el hecho de meter en un TextBox carácter a carácter
eterniza la aplicación. - Meter un texto en un TextBox o en un Label es una operación que tarda cierto
tiempo. Si esa operación hay que hacerla una vez por carácter, puede tardar mucho tiempo. Para evitar
esto, cuando vaya a leer un fichero carácter a carácter, métalo primero en una variable y luego realice un
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 167
volcado único de esa variable al TextBox o Label)
Y podemos hacerlo también leyendo línea a línea con Line Input
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
Line Input #1, VarTexto
'leemos el fichero Línea a Línea
TBTexto = TBTexto & VarTexto & vbCrLf 'vamos añadiendo las líneas leídas a TBTexto
'(Hay que introducir un retorno + avance de línea con cada línea (vbCrLf), ya que VarTexto no
‘contiene los retornos ni avances de línea.
Loop
Close #1
Los Botones de Guardar tienen el código :
Private Sub BGuardar_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowSave
Open CD1.filename For Output As #1
Print #1, TBTexto.Text
Close #1
End Sub
O para el caso de abrir con For Append
Private Sub BGuardar2_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowSave
Open CD1.filename For Append As #1
Print #1, TBTexto.Text
Close #1
End Sub
Ya hemos visto como se guardan y se leen datos de texto en un fichero secuencial.
INSTRUCCIÓN WRITE
La otra forma de introducir datos en un fichero secuencial es Write. Mediante esta instrucción, no se
puede introducir texto, sino datos, aunque esos datos sean de texto. Mediante la instrucción Write
puede crear una pequeña base de datos. Eso sí, una base de datos de escasa calidad. Pero no es
momento de cuestionar la calidad de esta base de datos, sino de explicarla.
Write
Puede introducir varias informaciones, que posteriormente se podrán leer de forma
separada con la instrucción Input #. Esta forma de introducir datos en un fichero
secuencial permite realizar un fichero con distintos datos que se pueden leer en el propio
fichero, puesto que se guardan en ASCII, y leerlos mediante el programa de una forma
muy sencilla. Hacemos, en realidad, una pequeña base de datos. (Verá a lo largo de su
vida profesional que lo de pequeña no es cierto, pues es la forma mas sencilla de
guardar datos cuando la cantidad de estos datos no es muy grande)
Lo que estamos haciendo en realidad al escribir datos mediante la instrucción Write es escribir estos
datos en un fichero secuencial, utilizando una coma como separador entre los distintos datos. Un fichero
secuencial con datos introducidos mediante la instrucción Write tendrá esta forma :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 168
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
“Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27”
Observe que el contenido de este fichero se diferencia algo de una simple sucesión de caracteres. Tiene
varias partes separadas por una coma. Cada una de ellas es un dato.
Imaginemos una aplicación, con la que introducimos datos de libros. La aplicación es un único formulario
donde podemos introducir la información mediante varios TextBox. Existe un Botón de comando con el
siguiente código:
Private Sub Command1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
PRECIO = LIBRETBPREC.Text
EXISTENCIAS = LIBRETBEX.Text
‘Donde LIBRETBTITULO, LIBRETBAUTOR, Etc. son los nombres de los TextBox
‘Ha leído los datos de los TextBox. Ya están el las variables TITULO, AUTOR, Etc.
‘Ahora los metemos en el fichero con la instrucción Write. El nombre del fichero será el
‘que hayamos puesto en el TextBox LIBRETBFICHERO, y lo guardará en el directorio
‘C :\cursoVB
Open TBNombreFichero.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, PRECIO, EXISTENCIAS
Close #1
End Sub
Si introduce los datos del ejemplo anterior, se creará un fichero que tiene esta apariencia:
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
Si realizamos otra introducción de datos, con la segunda línea del ejemplo anterior, los datos existentes
en ese fichero no se borrarán, dado que lo hemos abierto con Append. Quedará de la siguiente forma:
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
“Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27”
¿Que pasaría si leemos este fichero con la instrucción Input o Line Input # vista anteriormente ? Pues
simplemente que lo leeríamos tal como está, con sus comas y comillas dobles. No sería la forma mas
adecuada, ya que lo que queremos es obtener sucesivos datos de autores, títulos, editoriales, precios y
existencias.
Para sacar estos datos debemos leerlos con la instrucción Input #. Esta instrucción saca los datos que
hemos metido, es decir, elimina las comillas y la coma que servían de separadores.
En nuestro ejemplo, podríamos hacerlo de esta forma, aprovechando los mismos TextBox:
Private Sub Command2_Click()
' Limpiamos los TextBox
LIBRETBTITULO.Text = "" : LIBRETBAUTOR.Text = "" : LIBRETBEDITORIAL.Text = ""
LIBRETBPREC.Text = "" : LIBRETBEX.Text = ""
'Abrimos el fichero
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 169
' Introducimos una parada para poder leer datos
DETENERSE = True
Input #1, TIT, AUT, NED, PRE, EXS
LIBRETBTITULO.Text = TIT
LIBRETBAUTOR.Text = AUT
LIBRETBEDITORIAL.Text = NED
LIBRETBPREC.Text = PRE
LIBRETBEX.Text = EXS
' Refrescamos los TextBox
Refresh
' Esto produce una pequeña parada
Do While DETENERSE = True
A=A+1
If A = 100000 Then DETENERSE = False: A = 0
Loop
' terminó la parada y vuelve a leer datos
Loop
Close #1
End Sub
Observe que los nombre de las variables en el proceso de lectura tienen distintos nombres a los
utilizados durante la escritura. Como en el fichero no se guarda ninguna referencia al respecto, lo único
que importa es que el número de variables para la lectura sea igual al número de variables que se utilizó
para la escritura, y que el orden de las variables sea correcto. Si por ejemplo, el número de variables
usadas en la introducción de datos fuese distinto al número de variables usado en la lectura, Visual Basic
nos daría un error.
Observe también que se ha introducido un temporizador. Sirve para ver los sucesivos títulos que
tenemos en nuestra base de datos tan sui generis. Se ha pretendido presentar unos datos de esta
pequeña base de datos sin complicarnos mucho la vida. Mas adelante veremos como presentarlos de
una forma correcta. Este tipo de ficheros no es el mas adecuado para construir bases de datos, es
complicado manejar ficheros de mas de unas pocas líneas, por lo que para tener muchos datos, este
tipo de ficheros no es recomendable. No es aconsejable ni para muchos datos ni para pocos datos. Pero
es obligación del autor explicarlo … y de advertirlo.
En esta pequeña aplicación mostrábamos las informaciones sucesivamente según las íbamos leyendo
del fichero. Interrumpíamos momentáneamente la lectura para presentar cada información durante un
instante, ya que como tenemos cinco datos distintos en cada registro y cinco TextBox para presentarlos,
deberemos presentar una información tras otra. Esto no parece en principio una solución práctica para
una base de datos, donde lo que interesa es disponer de todos los datos para usarlos cuando sea
necesario. Esto nos lleva a crear una matriz para albergar todos los datos de la base, ya que los ficheros
secuenciales se leen y se les tiene que extraer toda la información de un golpe, ya que no permiten ir a
leer hacia atrás. Por lo tanto, si deseamos disponer de todos los datos, deberemos guardarlos en la
memoria, en una matriz. Imagínese que estamos tratando datos de varios miles de libros en el ejemplo
anterior. Si la información de cada campo es medianamente extensa, no tendríamos memoria RAM
suficiente en el ordenador para albergarlos. Esto nos lleva a pensar en otro tipo de archivo que veremos
a continuación, los Random (aleatorios), que permiten leer solamente los registros que nos interesan.
Pero volvamos a nuestra aplicación de librería, donde hemos hecho una variación, los campos PRECIO
y EXISTENCIAS los vamos a tratar ahora como números (Integer). También se ha introducido otro
campo tipo texto, para introducir la edición. El fichero creado tras introducir varios libros quedó de la
siguiente forma :
"EL RODABALLO","GUNTER GRASS","PLANETA",”1995”,2000,12
" VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 170
"EL NOMBRE DE LA ROSA","UMBERTO ECO","AGUILAR",”28”,1000,21
"ENCICLOPEDIA DEL VB","CEBALLOS","RAMA",”CUARTA”,1200,23
"LA GRANJA ANIMAL","ORWELL","DESTINO",”45”,12000,78
"LA PASION TURCA","ANTONIO GALA","PLANETA",”SEGUNDA”,2500,25
"LA METAMORFOSIS","KAFKA","PLAZA&JANES", “4ª”,3400,101
"VB4 PARA WINDOWS95","GARY CORNELL","MCGRAWHILL",”1ª”,6500,25
Observe que los dos últimos campos (correspondientes a PRECIO y EXISTENCIAS) no están entre
comillas, pues no se trata de texto, sino de números.
(Observe también la gran ventaja de tener una base de datos con datos completamente legibles)
Se han introducido alguna variaciones en el programa. Entre ellas, se crea una matriz de variables de 5 x
n (n=número de registros). También se le añaden unos botones para poder recorre toda la base de
datos.
La interfaz gráfica quedó de la siguiente forma :
El programa necesita que le introduzcamos el nombre del fichero que alberga la base de datos. Por
sencillez no se ha usado ningún CommonDialog y se introduce directamente el nombre de este fichero
en un TextBox llamado TBNombreFichero
El fichero anterior podemos leerlo tal y como indicábamos antes :
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
Input #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Donde las variables TITULO, AUTOR, EDITORIAL y EDICION serán del tipo String y PRECIO y
EXISTENCIAS serán de tipo numérico. Podemos saberlo, ya que en una línea cualquiera del fichero
anterior :
" VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21
los cuatro primeros parámetros van entre comillas dobles, ya que son datos tipo texto, y los dos últimos
van sin comillas, como corresponde a datos numéricos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 171
Pero existe otra forma mejor (al menos un poco mas complicada) para leer estos datos, y evitar el
problema que teníamos antes de tener que hacer un temporizador para poder ver, aunque solo sea un
momento, los datos. Podemos meter los datos a una matriz que tenga tantas columnas como datos
(campos) (en el ejemplo 6, cuatro String y dos numéricos), y tantas filas como apuntes (registros)
tengamos.
Para ello, antes de nada debemos definir un tipo de variable, mediante la instrucción Type. Parece que
no nos basta con los tipos de variable que trae VB (Long, String, Integer ...) y es cierto. La variable que
necesitamos no es de ningún tipo de esos. Está compuesta por varias secciones, y cada una de ellas
puede ser de un tipo distinto. Este tipo de definiciones debe hacerse en un módulo (Véase instrucción
Type en la ayuda de VB), por lo que se ha creado un módulo llamado LIBREMD2.BAS, con el siguiente
código :
Type REGISTROLIBRO
AUTOR As String
TITULO As String
EDITORIAL As String
EDICION As String
PRECIO As Integer
EXISTENCIAS As Integer
End Type
Esto es lo que se llama DEFINIR una variable. Es como hacerse un traje a medida. Y dese cuenta de
que es un tipo de variable (REGISTROLIBRO) formado por varias partes (AUTOR, TITULO, Etc.)
Observe que DEFINIR una variable NO es lo mismo que DECLARAR
En el apartado de Declaraciones del General del formulario declaramos las variables, entre ellas una
variable, REGISTROLIBROS, de la cual decimos que va a ser una matriz mediante los paréntesis que la
acompañan, y además declaramos que va a se similar a REGISTROLIBRO ya definida en el módulo.
Dim NR As Integer
Dim REGISTROLIBROS() As REGISTROLIBRO
Dim NRP As Integer
Observe que al usar paréntesis al declarar la variable REGISTROLIBROS le estamos diciendo a VB que
esa variable será un Array, y además que es una variable del tipo REGISTROLIBRO, tipo de variable
que ya conoce, puesto que se la hemos definido en un módulo.
En el ejemplo preparado podemos escribir y leer datos. Veamos de nuevo como se escriben
El código del procedimiento click del botón BIntroducir1 es :
Private Sub BIntroducir1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
EDICION = LIBRETBEDICION.Text
PRECIO = Val(LIBRETBPREC.Text)
EXISTENCIAS = Val(LIBRETBEX.Text)
‘TextBox para introducir el título
autor
‘
editorial
‘
edición
‘
precio
‘
existencias
‘
‘(Observe que para introducir el precio y las existencias se transformó el contenido del TextBox a ‘un
valor numérico mediante la instrucción Val.)
Open "C:\cursoVB\" + LIBRETBFICHERO.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Close #1
End Sub
Tras reiteradas entradas, el fichero de la BD quedó como se vio anteriormente.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 172
Al leer los datos, lo primero es que no conocemos el número de registros existentes. Como cada registro
va en una línea del fichero, si contamos el número de retornos de carro (Chr(13)) obtendremos el
número de registros. Esta operación es la primera que se realiza en el procedimiento click del botón
LEER :
Private Sub Command2_Click()
‘Pone todos los TextBox en blanco
LIBRETBTITULO.Text = ""
LIBRETBAUTOR.Text = ""
LIBRETBEDITORIAL.Text = ""
LIBRETBEDICION.Text = ""
LIBRETBPREC.Text = ""
LIBRETBEX.Text = ""
NR = 0
‘ NR=número de registros
‘ Abre el fichero, lo lee entero y cuenta el número de retornos de carro. Existirán tantos apuntes
(registros) como retornos de carro existan, ya que cada registro ocupa una línea.
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
A = Input(1, #1)
If A = Chr(13) Then NR = NR + 1
Loop
Close #1
‘ Presenta en LNumFich el número de registros
LNumFich.Caption = Str(NR) + " Registros)"
'Redimensionamos la matriz de REGISTROLIBROS a NR elementos..
ReDim REGISTROLIBROS(1 To NR)
‘Volvemos a abrir el fichero
Open TBNombreFichero.Text For Input As #1
‘Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando a los elementos ‘que
componen la matriz.
For I = 1 To NR
Input #1, REGISTROLIBROS(I).TITULO
Input #1, REGISTROLIBROS(I).AUTOR
Input #1, REGISTROLIBROS(I).EDITORIAL
Input #1, REGISTROLIBROS(I).EDICION
Input #1, REGISTROLIBROS(I).PRECIO
Input #1, REGISTROLIBROS(I).EXISTENCIAS
Next I
Close #1
NOTA.- Estas líneas podríamos heberlas puesto en una línea única :
Input#1 ,REGISTROLIBROS(I).TITULO,REGISTROLIBROS(I).AUTOR,_
REGISTROLIBROS(I).EDITORIAL,REGISTROLIBROS(I).EDICION,_
REGISTROLIBROS(I).PRECIO,
REGISTROLIBROS(I).EXISTENCIAS
‘NRP = Número del Registro Presentado. Lo hacemos igual a 1 para presentar, de momento, el ‘número
1
NRP = 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 173
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Copiamos este código de presentación de datos y lo llevamos a las flechas de incrementar o disminuir el
número del registro a presentar.
Private Sub BMas1_Click()
NRP = NRP + 1
If NRP > NR Then
‘protegemos que salga error de NRP fuera d e intervalo
MsgBox "No existen mas registros en esta dirección"
NRP = NR
Else
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End If
End Sub
Esta es la de incrementar. La de disminuir es igual, pero restando 1 a NRP
Las flechas dobles llevan al registro 1 y al último. Tienen este código
Private Sub BMas2_Click()
NRP = NR
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Observe que es muy sencillo trabajar con ficheros secuenciales para bases de datos. El inconveniente
es la cantidad de memoria necesaria para la matriz de datos. También tienen un gran inconveniente:
solamente se pueden leer de hacia adelante. Un fichero secuencial hay que leerlo de una sola vez. Esto
que no es ningún inconveniente para un fichero de texto, o incluso para un fichero de datos que leemos
una única vez, es un problema cuando leemos un dato situado en un punto de ese fichero, y luego
tenemos que leer un dato colocado en una posición anterior. En este caso, deberemos terminar de
leerlo, y volver a comenzar por el principio. Este es un gran inconveniente para hacer bases de datos con
ficheros secuenciales.
No solamente hemos visto una forma de crear una base de datos, sino que hemos visto como movernos
a lo largo de los registros. Verá esto con mucho mas detalle cuando demos bases de datos. Este tipo de
bases de datos son la Tipo Texto que verá mas adelante.
Propiedades de los ficheros Secuenciales:
EOF
Indica el fin del fichero (End Of File). EOF será False hasta que encuentre el final del fichero
secuencial. Habrá observado instrucciones tales como:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 174
Do until EOF(1)
(Hazlo hasta que encuentres el EOF del canal 1)
Do While Not EOF(1) (Hazlo mientras EOF del canal 1 sea False)
Estas expresiones se usan en un bucle, para ir extrayendo con la instrucción Input o Line Input
los caracteres de un fichero hasta que se encuentre la marca de final de fichero (EOF)
LOC
Devuelve la posición de lectura/escritura actual en un archivo abierto.
La sintaxis de esta propiedad es: LOC (Numero de canal)
la información devuelta para un archivo secuencial es la posición de byte actual en el archivo,
dividida por 128.
LOF
Devuelve la longitud de un fichero (Lenght Of File) abierto mediante Open.
Sintaxis
LOF(numeroarchivo)
Ejemplo Long = LOF (1)
Observaciones Para obtener la longitud de un archivo que no está abierto utilice la función
FileLen. (Véala mas abajo)
SEEK
Devuelve la posición actual de lectura/escritura de un archivo abierto con la instrucción Open.
Sintaxis
Seek(númeroArchivo)
Seek devuelve un valor entre 1 y 2,147,483,647 (equivalente a 2^31-1) inclusive. Para archivos abiertos
en modo Output, Append o Input, Seek devuelve la posición de byte en la que se va a ejecutar la
siguiente operación. El primer byte de un archivo está en la posición 1, el segundo en la posición 2 y así
sucesivamente.
FICHEROS ALEATORIOS (RANDOM)
Un fichero aleatorio es un conjunto de registros, todos ellos de la misma longitud, que nos permite
guardar varias colecciones de datos.
Tal como habíamos visto en los ficheros secuenciales, el almacenar una serie de colecciones de datos
en un fichero secuencial era muy fácil, pero bastante difícil de almacenarlas en la memoria cuando el
número de estas colecciones superaba una cierta cantidad.
Los ficheros aleatorios permiten almacenar información en registros que pueden ser fácilmente leídos,
pudiendo leer los registros uno a uno, sin necesidad de leerlos todos. En los archivos secuenciales, la
información de varios datos podíamos introducirla mediante la instrucción Write, y conseguíamos un
registro de la forma: (Recuérdese el ejemplo de los datos de un libro)
"Título","Autor","Editorial","Edición","Precio","Existencias"
Si deseábamos guardar la información de muchos libros, no había mucho problema para guardarla, pero
sí para almacenarla en memoria para poder usarla luego. Teníamos que leer todo el fichero, y extraer de
él la colección de informaciones y guardarlas en una matriz. Cambiar una información dentro del fichero
secuencial también implica una complicación adicional, ya que debemos rehacer el fichero completo,
pues un fichero secuencial no permite “remendar” el trozo que queremos cambiar.
Los ficheros aleatorios nos permiten guardar una información similar a la anterior, referida a cualquier
número de libros, y para leerla no es necesario leer todo el fichero, sino simplemente acceder a los
registros que nos interesen. También permite realizar el cambio de un registro de una forma sencilla, sin
alterar los demás.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 175
Todo esto tiene un precio: En los archivos secuenciales, podíamos introducir informaciones de cualquier
longitud. En los archivos aleatorios cada dato tiene una longitud asignada, longitud que no se puede
sobrepasar, y si la información que debemos almacenar tiene menos que la longitud preestablecida,
perderemos esa capacidad sobrante.
Para abrir un fichero aleatorio debemos emplear la expresión:
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
Nombrefichero es el nombre que queremos dar al fichero
Numerocanal es el número del canal (número de fichero) que puede ser de 1 a 255
LogitudRegistro es la longitud total del registro.
Un fichero aleatorio (Random), una vez abierto, puede utilizarse para leer o escribir datos.
Para escribir datos en un fichero aleatorio, primero debemos definir el registro, es decir, en el caso de los
libros visto anteriormente, un registro va almacenar los datos del titulo, autor, editorial, etc. Para "saber"
como se colocan estos datos dentro del registro será necesario definirlo.
En realidad lo que vamos a hacer es definir una variable de las denominadas “Definidas por el usuario”
Con esto lo que hacemos es crear un nuevo tipo de variable, en el ejemplo, la variable tipo Registro.
Se debbe hacer en la sección de declaraciones de un módulo o de un formulario, y siempre antes de
declarar una variable como variable de ese tipo. (La definición de la variable debe hacerse en la sección
de declaraciones del módulo o formulario con ámbito suficiente para que sea válida en todas las partes
de la aplicación donde se necesite esa variable)
Podemos hacerlo con la instrucción Type:
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Asignamos 30 caracteres para el título
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
Observe la diferencia de esta definición con la que hacíamos en los ficheros secuenciales. En aquellos
no poníamos la longitud de cada sección. Aquí es necesario, ya que la longitud de un registro (y también
de cada campo) es fija.
Ya una vez definido como es Registro, podemos decir que una variable es del tipo definido para
Registro, es decir :
Dim MiVariable as Registro
Entonces MiVariable ya puede almacenar los datos de Titulo, Autor, Editorial, Edición, Precio y
Existencias, colocando un dato tras otro, sin ninguna separación, en el mismo orden que lo habíamos
definido para Registro. No es necesario utilizar separaciones ya que el programa sabe que longitud
tiene cada dato y el orden de colocación. Lo sabe porque se lo hemos dicho al definir Registro. Si los
datos a introducir son :
Titulo :
Autor :
Editorial :
Edición :
Precio :
LSB
Guía del Estudiante
Luis Suárez Bernaldo
Ediciones XX
2ª
3500
Visual Basic – Guía del Estudiante
Capítulo 1
Página 176
Existencias :
25
el registro correspondiente a este libro tendrá una forma mas o menos así :
Guía del Estudiante///////////Luís Suárez Bernaldo//////////Ediciones XX///2ª////350025/
donde se ha sustituido el carácter nulo por una barra ( / ) con el fin de hacerlo visible en el texto. Si se
molesta en contar los caracteres que tiene el registro observará que son 88, que es la suma de 30 + 30 +
15 + 6 + 4 + 3 que son los caracteres asignados a cada uno de las partes que forman el registro (Título,
Autor, etc.) Para hablar con propiedad, a esas partes que componen el registro lea vamos a llamar
CAMPOS. Un Registro está formado por varios Campos, y cada Campo contiene una información.
Imagínese que introducimos otro libro. El primer campo de ese nuevo registro se colocará en el fichero
inmediatamente después del último campo existente, sin ningún tipo de separación. No hace falta esa
separación, pues VB conoce donde finaliza un registro y comienza otro, ya que la longitud total del
registro se le ha introducido en la instrucción para abrir el fichero, que repetimos aquí por comodidad :
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
(Si se omite el dato LongitudRegistro VB colocará la longitud por defecto, 128 caracteres)
LongitudRegistro deberá ser igual o mayor que la suma de caracteres de cada uno de los campos
declarados en la instrucción Type, que también reproducimos :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Asignamos 30 caracteres para el título
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
¿Deberá ser igual o mayor, o estrictamente igual ? La respuesta es igual o mayor . Pero si declaramos
en la instrucción Open que el registro es mayor que la suma de los caracteres de todos los campos que
lo componen, estaremos perdiendo espacio de disco duro, tanto como la diferencia entre lo declarado en
la instrucción Open menos la suma de los caracteres de cada uno de los campos. Y esa cifra,
multiplicada por el número de registros existentes. Por lo tanto debe declararse en la instrucción Open
exactamente la suma de los caracteres de todos los campos. En el ejemplo anterior era bastante fácil, ya
que todos los campos eran del tipo String (cadena de caracteres) y cada carácter ocupa un byte. La cosa
se complica si uno o varios de los campos son de tipo numérico, porque nos obligará a recordar cuantos
bytes ocupa un integer, un Long, etc. Si hubiésemos declarado en la instrucción Type Precio as Long,
Existencias as Integer deberíamos tener en cuenta que un Long (número entero entre -2.147.483.648 y
2.147.483.647, inclusive) ocupa 4 bytes y un integer (número entero entre -32.768 y 32.767) ocupa 2
bytes. Se reproduce a continuación la longitud en Bytes de cada uno de los tipos de datos. No se
moleste en aprendérsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como
Resumen de tipos de datos. Pero fíjese en algo tan curioso como que un dato tipo Boolean que
solamente puede tomar 2 valores (Sí / No) ocupa 2 bytes frente a un dato tipo Byte, que puede tomar
256 valores y ocupa solamente un Byte.
Tipo de Dato
Byte
Boolean
Integer
Long(entero largo)
Single(coma flotante Simple precisión)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Ocupa
1 byte
2 bytes
2 bytes
4 bytes
4 bytes
Página 177
Double(coma flotante Doble Precisión)
Currency
Date
Object
String (longitud variable)
String (longitud fija)
Variant (con números)
Variant (con caracteres)
8 bytes
8 bytes
8 bytes
4 bytes
10 bytes + longitud de cadena
longitud declarada de la cadena
16 bytes
22 bytes + longitud de cadena
Ya le estoy viendo tomando buena nota de cuanto ocupa cada variable. Y echando números para saber
la longitud exacta de la variable y no perder ningún byte del disco duro desaprovechándolo sin
información. ¿No habrá algo que nos lo facilite ? Sí, lógicamente. La instrucción LEN
LEN nos da la longitud de un texto (Var=Len (“Hola que tal”), o de una variable Var=Len(Variable)
Podemos usarla para conocer la longitud total de la variable MiVariable
LongitudRegistro = Len (MiVariable)
Pero si quiere reducir mas la cosa, abra el fichero de esta forma :
Open Nombrefichero For Random As # Numerocanal Len = Len (MiVariable)
Ni que decir tiene que si se abre ese fichero en varias partes del programa con distintas instrucciones
Open el valor de LongitudRegistro debe ser igual en todas ellas.
La declaración del registro mediante la instrucción Type debe hacerse en la sección de declaraciones de
un Módulo. Esta instrucción Type en realidad lo que está haciendo es definir un nuevo tipo de variable,
(una variable definida por el usuario) que servirá de “muestra” para que en otra parte del programa le
digamos, mediante una instrucción Dim, que tal variable es del tipo definido anteriormente mediante la
instrucción Type. Por lo tanto, debemos declarar una variable en la parte que corresponda del programa,
dependiendo del ámbito que se le quiera dar a esa variable, diciendo que será del tipo de la declarada
mediante la instrucción Type.
Usando la declaración de Registro del ejemplo anterior, vamos a retomar el ejemplo de la biblioteca.
Declararemos (posiblemente en la sección de declaraciones del formulario) una variable que llamaremos
p.e. REGLIBROS de la siguiente forma :
Dim REGLIBROS as Registro
A partir de este momento, el programa sabe que REGLIBROS es una variable que tiene 6 campos
(Titulo, Autor, Editorial, Edición, Precio y Existencias) y que cada campo tiene los caracteres
especificados en la instrucción Type.
Ahora nos cabe una pregunta ¿Cuantos registros tiene un fichero Random? La respuesta es sencilla.
Basta conocer la longitud del fichero mediante la instrucción LOF si el fichero ya está abierto, o con la
instrucción FILELEN si no lo está, y dividir el dato obtenido con cualquiera de las dos instrucciones
anteriores por el valor LongitudRegistro.
Escribir datos en un fichero Random. Instrucción Put
Una vez abierto el fichero Random podemos leer y escribir datos en él. Para escribir datos utilizaremos la
instrucción Put. La sintaxis de Put es la siguiente:
Put # Numerocanal , NumeroRegistro, Variable
Puede omitirse NumeroRegistro. En este caso, el número de registro que se escribirá será el siguiente al
último registro escrito.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 178
NumeroRegistro es el número del registro que queremos escribir, y Variable es el contenido de ese
registro. Siguiendo con nuestro ejemplo de biblioteca, Variable tiene en este caso el nombre
REGLIBROS, que no es un String ni un Integer, sino una variable definida por el usuario ya que la
declaramos con Dim REGLIBROS as Registro. Por lo tanto, la variable REGLIBROS contendrá los
mismos campos que habíamos declarado para Registro en la instrucción Type. Recuerde :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Asignamos 30 caracteres para el título
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
Luego REGLIBROS tendrá 6 campos (Titulo, Autor, Editorial, Edición, Precio y Existencias), cada uno de
una longitud determinada, la definida en la instrucción Type.
Antes de introducir REGLIBROS en el fichero habrá que decir que valor tiene. Pero cada campo que lo
compone tendrá un valor. Podríamos hacer una aplicación en la que, a través de varios TextBox, le
introdujésemos los valores de los campos, y el número de registro en el cual queremos escribir. El
nombre de cada uno de los TextBox para cada uno de los datos es el siguiente :
Campo Título : TBTITULO Campo Autor : TBAUTOR Campo Editorial : TBEDITORIAL
Campo Edición :TBEDICION Campo Precio : TBPRECIO Campo Existencias : TBEXISTENCIAS
La aplicación deberá introducir en cada campo el valor (string) existente en cada uno de esos TextBox.
El valor de la variable REGLIBROS lo compondremos de la siguiente forma :
REGLIBROS.Titulo = TBTITULO.Text
REGLIBROS.Autor = TBAUTOR.Text
REGLIBROS.Editorial = TBEDITORIAL.Text
REGLIBROS.Edicion = TBEDICION.Text
REGLIBROS.Precio = TBPRECIO.Text
REGLIBROS.Existencias = TBEXISTENCIAS.Text
(Si se hubiese omitido alguna de estas igualdades, el campo correspondiente contendría el valor nulo)
De esta forma, REGLIBROS ya tiene un valor que se puede escribir en el fichero mediante la instrucción
Put.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 179
El formulario de esa aplicación tendrá esta forma :
Observe que ya se le han introducido otros controles (TextBox para introducir el nombre del fichero, otro
para el número de registro, botones para leer, escribir, abrir el fichero (EXAMINAR), un par de botones
para subir o bajar el número de registro y un botón para salir de la aplicación. El TextBox para introducir
el nombre del fichero se llama TBNOMBREFICHERO y en el que debemos introducir el número de
registro a leer o escribir TBLEERESCR.
El Botón EXAMINAR cierra cualquier fichero que pudiese estar abierto, abre el fichero indicado en
TBNOMBREFICHERO, calcula el número de registros y escribe este número en el Label con nombre
LNUMFICH. El código de su procedimiento Click es el siguiente :
Private Sub BEXAMINAR_Click()
Close
Open TBNOMBREFICHERO For Random As #1 Len = 88
LONGITUDFICH = LOF(1)
NUMREGS = LONGITUDFICH / 88
LNUMFICH.Caption = NUMREGS
End Sub
‘Cierra cualquier fichero abierto
‘Abre el fichero deseado
‘Obtiene su longitud
‘Calcula el Nº. de registros
‘Pone ese Nº. en el Label
Veamos como se escribe un registro. Analicemos el código del procedimiento click del botón ESCRIBIR
Private Sub BESCRIBIR_Click()
REGISTROLIBRO.Titulo = TBTITULO.Text
REGISTROLIBRO.Autor = TBAUTOR.Text
REGISTROLIBRO.Editorial = TBEDITORIAL.Text
REGISTROLIBRO.Edición = TBEDICION.Text
REGISTROLIBRO.Precio = TBPRECIO.Text
REGISTROLIBRO.Existencias = TBEXISTENCIAS.Text
Put #1, Val(TBLEERESCR), REGISTROLIBRO
End Sub
‘Se asignan los valores de cada
‘uno de los campos de la variable
‘REGISTROLIBROS
‘Se escribe el registro
Observe que el Nº. de registro es el valor que figure en el TextBox TBLEERESCR
Leer datos en un fichero Rando m. Instrucc ión Get
Para leer los datos de un fichero Random utilizaremos la instrucción Get. Su sintaxis es la siguiente :
Get # Numerocanal , NumeroRegistro, Variable
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 180
Puede omitirse NumeroRegistro. En este caso, el número de registro que se leerá será el siguiente al
último registro leído.
La Instrucción Get leerá un registro completo. Ese registro contendrá varios campos, y seguramente nos
interesará conocer el valor de cada campo dentro de ese registro. Variable es una variable que
contendrá todos los campos. En nuestra aplicación de biblioteca, Variable tiene por nombre
REGISTROLIBRO (El mismo que tenía para la instrucción Put de escribir. Es pura comodidad del
programador. Puede tener cualquier otro nombre)
Para obtener el contenido de cada campo, realizaremos un proceso similar al empleado para la escritura,
pero al revés. En nuestra aplicación, pretendemos poner el contenido de cada campo en los mismos
TextBox que se utilizaron para escribirlos. Veamos el contenido del procedimiento click del botón LEER
Private Sub BLEER_Click()
Get #1, Val(TBLEERESCR), REGISTROLIBRO
TBTITULO.Text = REGISTROLIBRO.Titulo
TBAUTOR.Text = REGISTROLIBRO.Autor
TBEDITORIAL.Text = REGISTROLIBRO.Editorial
TBEDICION.Text = REGISTROLIBRO.Edición
TBPRECIO.Text = REGISTROLIBRO.Precio
TBEXISTENCIAS.Text = REGISTROLIBRO.Existencias
End Sub
‘Lee el registro completo
‘Obtiene el valor del campo Ti tulo
‘Autor, Editorial, Edición, Precio
‘y Existencias y los pone en los
‘TextBox correspondientes a cada
‘dato
Funciones e instrucciones aplicables a los ficheros Random.
Funciones Seek y Loc.
En los ficheros Random tienen especial importancia las funciones Seek y Loc.
Mediante la Función Loc podemos conocer la el último registro manipulado, bien por lectura, escritura. Si
abrimos el fichero y no se ha hecho ninguna lectura o escritura de registros, el número devuelto por la
función Loc es 0.
La sintaxis de la función Loc es :
Variable = Loc (Numerocanal)
Variable tomará un valor igual al número del registro escrito o leído por última vez.
Mediante la Función Seek podemos conocer el próximo registro que será manipulado en una operación
de lectura o escritura. Si abrimos el fichero y no se ha hecho aún ninguna operación de lectura o
escritura, Seek devuelve el valor 1.
La sintaxis de la función Seek es :
Variable = Seek (Numerocanal)
ATENCION
¡¡¡ Seek pu ede ser un a fun ción (lee un Dato ) o una in stru cc ión (fuerza un d ato) ! ! !
Instrucción Seek
La instrucción Seek establece el próximo registro a leer o escribir en un fichero Random.
Sintaxis
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 181
Seek (Numerocanal), posición
posición es el número de registro que se va a leer o escribir en la siguiente operación. No acepta el 0
como número de registro, el mas bajo debe ser el 1. Si se intenta forzar a la posición 0 dará un error.
Funciones de los ficheros Random:
EOF
Devuelve un valor que indica si se ha llegado al final de un archivo.
Sintaxis
EOF(Numerocanal)
En archivos Random, EOF devuelve False hasta que se haya ejecutado una instrucción Get y no haya
podido leer el registro completo, en cuyo caso devolverá True.
La función EOF no suele emplearse en ficheros Random, ya que en estos nos movemos a base de
registros, y es muy fácil controlar cuantos registros existen en el fichero y en que registro nos
encontramos o nos vamos a mover, mediante las funciones LOF, LOC y SEEK
LOF
( Lenght Of File )
Devuelve la longitud de un fichero .
Sintaxis
Variable = LOF(Numerocanal)
Mediante la función LOF podemos conocer el número de registros existentes en un fichero Random,
dividiendo el valor devuelto por LOF por la longitud del registro declarada en la instrucción Open (LEN =
longitud)
Nº. Registros = LOF / longitud
Recuerde
LSB
Para obtener la longitud de un archivo que no está abierto utilíce la función
FileLen.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 182
FICHEROS BINARIOS
Un fichero binario es una sucesión de bytes, uno tras otro, que puede almacenar cualquier tipo de
información. Cuando se explicaban los ficheros secuenciales, decíamos que eran los mas adecuados
para introducir información de un texto, con los Random podíamos realizar una base de datos de forma
sencilla, a base de controlar los registros y sus campos. Con un fichero binario podemos almacenar
cualquier información. (texto y cualquier tipo de datos) .
Para abrir un fichero secuencial se abre utilizando la instrucción :
Open Nombrefichero For Binary As # Numerocanal
Como siempre en VB, Numerocanal puede ser un número comprendido entre 1 y 255, que define ea
fichero. No pueden existir al mismo tiempo 2 ficheros abiertos con el mismo Numero de canal.
Nombrefichero es el nombre completo del fichero, con su Path.
Una vez abierto un fichero se binario, podemos leer o escribir datos en él.
Para escribir uno o varios caracteres en un fichero binario, usaremos la instrucción Put.
Put # Numerocanal, Posición, Variable
Donde Posición es el Byte donde comenzará la escritura, y Variable es el nombre de la variable que
contiene el dato a escribir. Este dato puede ser un byte o varios bytes.
Para escribir varios bytes podemos hacerlo de dos formas :
- Si se puede conocer de antemano el número de bytes a escribir, puede declararse Variable como un
string de ese número de caracteres mediante la instrucción Dim, por ejemplo :
Dim Variable As String * numero de bytes
y en este caso siempre escribirá el número de bytes declarado. ¡ Cuidado ! Si los datos a introducir
sobrepasan el número de bytes declarados para Variable, los datos sobrantes no se escribirán en el
fichero. Si los datos a escribir en el fichero fuesen menos que los declarados para Variable, la diferencia
se rellenará con el byte nulo ( 0 ).
- Si no se conoce de antemano el número de bytes a escribir, podemos declarar la variable sin
especificar el número de bytes que tiene, y de esta forma se escribirán todos los bytes que componen la
variable :
Dim Variable As String
Pero en este caso debemos volver a decir ¡ Cuidado !, si no conocemos el número de bytes que vamos
a escribir, puede que “machaquemos” parte de la información que ya tenemos en el fichero, pues la
instrucción Put va a colocar los bytes que componen Variable en la posición especificada por Posición y
siguientes, hasta que quepa toda la cadena de bytes que le queremos introducir. Si la posición en la que
introducimos esos bytes es una posición intermedia, y no controlamos bien el número de bytes a
introducir y las informaciones que ya existen en el fichero en las posiciones colindantes con las que
vamos a introducir los datos, es muy probable que perdamos esa información al introducir la nueva.
Si se omite el dato Posición, se tomará como byte de inicio de la escritura el siguiente al último usado
por la instrucción Put. Si quiere omitir este dato, debe conservar las comas que lo separan :
Put # Numerocanal, , Variable
¿Qué pasará si el dato Posición indica una posición mayor que la que tiene realmente el fichero ?
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 183
Simplemente que rellenará las posiciones intermedias que se formarán con un byte (puede verlo con el
Block de Notas ÿÿÿ)
Un fichero binario es, como se decía al principio, una sucesión de bytes, que no tiene ningún tipo de
separación entre bytes. Cada dato (byte o conjunto de bytes) que introduzcamos en un fichero binario se
escribirá en el fichero tal y como se introducen. Machacando información ya existente si no se controla
bien donde se mete. Por lo tanto, aunque parece que los ficheros binarios pueden ser mucho mas
versátiles que los secuenciales y los Random, exigen mucho mas control que los anteriores. Limite el
uso de este tipo de ficheros a las aplicaciones en que sea realmente imprescindible.
Para leer datos de un fichero binario, utilizaremos la instrucción Get.
Get # Numerocanal, Posición, Variable
Donde Posición es el número del primer byte leído, que como en el caso de Put, si se omite, tomará
como valor el byte siguiente al usado en la última instrucción Get. Variable es el nombre de una variable
que contendrá los datos leídos.
Pueden leerse uno o varios Bytes, pero ahora surge un pequeño problema. ¿Como le decimos cuantos
bytes debe leer ? Sencillamente los especificados al declarar la variable . Imaginemos que la
declaración de la variable fue :
Dim Variable As String * 10
Con Variable declarada de esta forma, leerá 10 bytes a partir del byte Posición. (Incluido)
De esta forma, siempre leeremos un número determinado de caracteres (10 en el caso del ejemplo).
Esta es una limitación para el uso de Get. Esta función viene muy bien en aquellas aplicaciones en las
que tenemos que extraer un número fijo de bytes (En la práctica, en la mayor parte de las aplicaciones
se extrae de uno en uno)
Pero pueden existir aplicaciones en las que sea necesario leer una vez un número de caracteres, y otra
vez otro. Ese problema lo tenemos resuelto con la instrucción Input.
Podemos leer caracteres de un fichero secuencial mediante la instrucción Input :
Variable = Input (Numero de bytes, # Numerocanal)
Mediante la instrucción Input podemos leer el número de caracteres que queramos, pero no podemos
controlar el byte de comienzo. Por lo tanto deberemos ayudarnos de la instrucción Seek para posicionar
el puntero de lectura encima del primer byte que queramos leer :
Seek (Numerocanal), Número del primer Byte a leer
Por ejemplo, si queremos leer 35 bytes de un archivo binario, abierto con el número de canal 1,
comenzando por el byte 48 (el 48 será el primer byte leído), ejecutaremos las dos siguientes
instrucciones :
Seek (1), 48
Variable = Input (35, #1)
Variable contendrá ahora los 35 bytes deseados.
Al igual que se hizo para los ficheros secuenciales y Random, vamos a ver con un ejemplo práctico
como se manejan los ficheros binarios.
El formulario del ejemplo tiene esta forma :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 184
Con el botón ABRIR se abre el fichero deseado. Si no existe en el disco, lo crea, ya que la instrucción
Open Nombrefichero For Binary As # Numerocanal
intenta abrir un fichero existente llamado Nombrefichero, y si este no existe, lo crea. Si existe el fichero,
presenta todo su contenido en el TextBox inferior, para poder tener una referencia de que lugar ocupan
los distintos caracteres (un fichero binario puede guardar cualquier byte, por lo que si abre un fichero
generado con cualquier programa puede ser que muchos de los bytes no contengan información de un
carácter, por lo que le recomendamos haga esta práctica con un fichero creado por la misma práctica)
El botón CERRAR cierra el fichero. SALIR sale de la aplicación. El TextBox superior (variable) sirve para
introducir la variable a escribir en el fichero, o para presentar la variable leída en caso de lectura . El
TextBox posición sirve para indicar la posición del primer byte. Posición por defecto presenta la posición
que se extrae mediante la función Seek cada vez que se hace una lectura o escritura en el fichero.
Longitud de la variable permite introducir esa longitud, para leer mediante la instrucción Input.
El botón ESCRIBIR escribe el dato Variable en el fichero, LEER (GET) lee un único byte, y LEER
(INPUT) lee una cadena de caracteres, de longitud la especificada en el TextBox Longitud de la variable.
Se enumera a continuación el código de cada uno, dejando para las explicaciones del profesor en clase,
o el estudio del alumno, la interpretación de cada una de susu partes.
FORMULARIO. DECLARACIONES
Option Explicit
‘Obliga a declarar todas las variables
Dim LONGVAR As Integer
‘Se declara la variable LONGVAR
Dim COMIENZA As Long
‘Se declara la variable COMIENZA
Dim TESTO As String
‘Se declara la variable TESTO
Dim pospordef As Long
‘Se declara la variable pospordef
BOTON ABRIR
Private Sub BABRIR_Click()
CD1.ShowOpen
‘CD1 es un CommonDialog para buscar el fichero
Open CD1.filename For Binary As #1 ‘Abre el fichero indicado en CD1
TESTO = Input(LOF(1), #1)
‘Lee de un golpe el fichero y lo mete en la variable TESTO
TBFICHERO.Text = TESTO
‘Presenta el fichero en el TextBox TBFICHERO
End Sub
BOTON CERRAR
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 185
Private Sub BCERRAR_Click()
Close
End Sub
BOTON ESCRIBIR
Private Sub BESCRIBIR_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
Dim escribe As String
escribe = TBVAR1.Text
Put #1, Val(TBVAR3), escribe
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
BOTON LEER (GET)
Private Sub BLEER_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
TBVAR2.Text = "1"
If Seek(1) >= LOF(1) Then
Seek #1, 1
End If
Dim TEXTO As String * 1
If TBVAR3.Text <> "" Then
COMIENZA = Val(TBVAR3.Text)
ElseIf Lvar5.Caption <> "" Then
COMIENZA = Val(Lvar5.Caption)
Else
COMIENZA = Seek(1)
End If
Get #1, COMIENZA, TEXTO
TBVAR1.Text = TEXTO
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
‘La instrucción Close cierra todos los ficheros abiertos
‘Pone el TB long. De la variable en rojo
‘Declara la variable escribe como string, sin limitación
‘Pasa el contenido de TBVAR a la variable escribe
‘Instrucción Put. Val(TBVAR3) es la posición del 1er byte
‘Analiza donde quedó el puntero del fichero
‘y pone este valor en la etiqueta Lvar5
‘Pone en rojo el TB TBVAR2 (long. de la variable)
‘e indica que la longitud leída es 1
‘Si está al final del archivo
‘pone el puntero en la posición 1
‘
‘Declara la variable TEXTO de un byte
‘Si se le ha indicado donde tiene que comenzar
‘le dice que comience en la posición indicada en TBVAR3
‘si no, si existe posición por defecto
‘le indica que comience en la posición por defecto
‘ si no
‘pone el puntero en la posición 1 (byte 1)
‘lee un byte
‘y lo presenta en TBVAR1
‘busca la nueva posición por defecto
‘y pone ese valor en Lvar5
BOTON LEER (INPUT)
Private Sub BLLERINPUT_Click()
TBVAR2.BackColor = RGB(255, 255, 255)
‘Pone TBVAR2 en blanco
LONGVAR = Val(TBVAR2.Text) ‘pasa el valor para long. de variable a LONGVAR
‘si ese valor existe (TBVAR3 es distinto de nada)
If TBVAR3.Text <> "" Then
‘la variable COMIENZA toma ese valor
COMIENZA = Val(TBVAR3.Text)
Seek (1), COMIENZA
‘coloca el puntero en ese valor
End If
‘
Dim TEXTO As String
‘Declara la variable TEXTO sin limitación
TEXTO = Input(LONGVAR, #1)
‘Lee LONGVAR bytes del canal 1 y los pasa a TEXTO
TBVAR1.Text = TEXTO
‘y lo presenta en el TB TBVAR1
pospordef = Seek(1)
‘analiza la nueva posición por defecto
Lvar5 = Str(pospordef)
‘y la presenta en Lvar5
End Sub
‘
BOTON SALIR
Private Sub BSALIR_Click()
End
End Sub
‘Sale de la aplicación.
Private Sub TBVAR2_Change()
TBVAR2.BackColor = RGB(255, 255, 255)
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
‘Vuelve a color blanco si introducimos un dato en
‘este Text Box
Página 186
FIN DE LA APLICACIÓN PARA MANEJO DE FICHEROS BINARIOS
Funciones y propiedades aplicables a todos los ficheros
DIR
Devuelve el nombre de un archivo, directorio o carpeta que concuerda con el patrón o atributo de archivo
especificado o la etiqueta de volumen de una unidad de disco.
Sintaxis
Dir[(nombreruta[, atributos])]
nombreruta
Expresión de cadena que especifica un nombre de archivo. Puede incluir el
directorio o carpeta y la unidad de disco. Si no se encuentra nombreruta, devuelve
Null.
atributos
Constante o expresión numérica, cuya suma especifica atributos de archivo. Si se
omite, devuelve todos los archivos normales que satisfacen el nombreruta.
El argumento atributos tiene estas constantes y valores:
Constante
Valor
Descripción
vbNormal
vbHidden
vbSystem
vbVolume
vbDirectory
0
2
4
8
16
Normal.
Oculto.
Sistema
Etiqueta de volumen; si se especifica se ignoran todos los atributos
Directorio o carpeta.
En Microsoft Windows, Dir permite el empleo de los caracteres comodín '*' (múltiples caracteres) y '?'
(un solo carácter) para especificar varios archivos.
La primera vez que se llama a la función Dir se debe especificar el nombreruta, de lo contrario se
produce un error. Si además se especifican atributos de archivo, se debe incluir el nombreruta.
Dir devuelve el primer nombre de archivo que coincide con el nombreruta. Para obtener más nombres de
archivo que coincidan con el nombreruta, se debe volver a llamar a Dir sin argumentos.
Cuando no hay más nombres de archivo coincidentes, Dir devuelve una cadena de caracteres de
longitud cero. Cuando se devuelve una cadena de longitud cero, en las siguientes llamadas se debe
especificar nombreruta o se producirá un error. Se puede cambiar el nombreruta sin haber obtenido
todos los nombres de archivo que coinciden con el nombreruta actual. Sin embargo, no se puede llamar
a la función Dir.
FILECOPY
Copia un archivo.
Sintaxis
FileCopy fuente, destino
fuente Expresión de cadena que especifica el nombre de un archivo a copiarse puede incluir el
directorio o carpeta y la unidad de disco..
destino Expresión de cadena que especifica el nombre del archivo de destino se puede incluir el
directorio o carpeta y la unidad de disco.
Si intenta utilizar la instrucción FileCopy en un archivo abierto actualmente, se produce un error.
FILEDATATIME
Devuelve una fecha que indica la fecha y hora en que un archivo fue creado o modificado por última vez.
Sintaxis
LSB
Variable = FileDateTime(nombreRuta)
Visual Basic – Guía del Estudiante
Capítulo 1
Página 187
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo. Se puede incluir el directorio o carpeta y la unidad de disco.
FILELEN
Devuelve la longitud de un archivo en bytes.
Variable = FileLen(nombreRuta)
Sintaxis
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo se puede incluir el directorio o carpeta y la unidad de disco.
Si el archivo especificado está abierto cuando se llama la función FileLen, el valor devuelto representa el
último tamaño de ese archivo cuando se guardó la ultima vez en el disco.
Para obtener la longitud de un archivo abierto, utilice la función LOF.
GETATTR
Devuelve un número, que representa los atributos de un archivo, directorio o carpeta o una etiqueta de
volumen.
Sintaxis
Variable = GetAttr(nombreRuta)
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo se puede incluir el directorio o carpeta y la unidad de disco.
Valores devueltos
El valor devuelto por GetAttr es la suma de los siguientes valores de atributos:
Valor
Constante
Descripción
0
1
2
4
16
32
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Sólo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado después de efectuar la última copia de
seguridad.
SETATTR
Establece los atributos de un archivo.
Sintaxis
nombreRuta
atributos
SetAttr nombreRuta;atributos
Expresión de cadena que especifica un nombre de archivo se puede incluir el
directorio o carpeta y la unidad de disco.
Constante o expresión numérica cuya suma especifica los atributos de
archivo.
Las constantes y valores de atributos son los mismos que para la instrucción GetAttr
Si se trata de establecer los atributos de un archivo abierto, se producirá un error en tiempo de
ejecución.
FREEFILE
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 188
Devuelve el siguiente número de archivo disponible para ser usado con la instrucción Open.
Sintaxis
FreeFile[(númerodeintervalo)]
El argumento númerodeintervalo especifica el intervalo desde el que el siguiente número de archivo libre
se va a devolver. Se especifica 0 (predeterminado) para devolver un número de archivo en el intervalo 1
a 255, inclusive. Se especifica 1 para devolver un número de archivo en el intervalo 256 a 511.
Observaciones Se usa FreeFile cuando se necesita proveer un número de archivo y se quiere asegurar
que el número de archivo no está ya en uso.
Visual Basic - Guía del Estudiante Cap. 6
FICHEROS EN VISUAL BASIC
Existen tres tipos de ficheros donde podremos almacenar y leer datos:
- Secuenciales
- Aleatorios (Random)
- Binarios
Cada uno de ellos tiene sus aplicaciones y particularidades.
FICHEROS SECUENCIALES
Este tipo de ficheros nos permite guardar información de cualquier longitud. En este tipo de ficheros, la
información se guarda colocando un carácter tras otro. La forma de leerlos es, igualmente, carácter tras
carácter. (Byte tras byte). Son los mas sencillos de manejar, y los utilizados para guardar texto en ASCII.
Permiten guardar datos en un fichero con un determinado nombre, "machacando" la información de otro
posible fichero que ya estuviese en el disco con el mismo nombre, o añadir la información nueva a
continuación de la ya existente.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 189
Para abrir un fichero secuencial para guardar información, debemos ejecutar la siguiente instrucción:
Open Nombrefichero For Output As # Numerocanal
De esta forma, si ya existía un fichero llamado Nombrefichero, sobreescribiremos dicho fichero
perdiendo la información que contuviese. Es la forma típica de hacerlo cuando modificamos un texto.
Para añadir la nueva información tras la ya existente, deberemos abrirlo con la siguiente instrucción:
Open Nombrefichero For Append As # Numerocanal
Numerocanal debe ser un número comprendido entre 1 y 255. Representa el número del canal por
donde introduciremos los datos. Normalmente se llama también número de archivo . No puede haber
mas de un archivo abierto con un número de canal determinado.
Para cerrar un fichero secuencial, basta con ejecutar la instrucción:
Close # Numerocanal
Si no se especifica Numerocanal (la instrucción Close a secas) se cerrarán todos los ficheros abiertos
actualmente.
Para introducir la información, pueden emplearse dos métodos: Print y Write Nos centraremos de
momento solamente en Print.
Print
Introduce la información de forma secuencial, byte tras byte tal como se comentó. Sirve
para guardar textos. Por ejemplo si deseamos guardar en ese fichero el contenido de
una caja de texto llamada Text1, basta con ejecutar la siguiente instrucción:
Print #NumerodeCanal, Text1.Text
El texto queda en el fichero en caracteres ASCII, que se pueden leer con el Bloc de
Notas.
Cuando los datos se han introducido con la instrucción Print, la forma de acceder a ese texto es muy
sencilla:
Se abre el archivo con la instrucción Open
Open Nombrefichero For Input As # Numerodecanal
Se utiliza la instrucción Input o Line Input para sacar los datos del fichero.
La instrucción Input tiene en este caso la siguiente sintaxis:
VariableString = Input (Numero de caracteres, # Numero de canal)
Por ejemplo, VariableString = Input (1, #1) extrae un carácter del fichero abierto como #1. El número
máximo de caracteres a extraer de un golpe mediante la instrucción Input está limitado a 65.534.
Verá un poco mas adelante la propiedad LOF de los ficheros secuenciales. LOF devuelve un valor igual
a la longitud total del fichero. Si ejecutamos la instrucción :
Para no emplear una palabra tan larga como Numerodecanal, utilizaremos de ahora en adelante el
número 1 como número de canal. Recuerde que ese número puede ser un número comprendido entre
el 1 y el 255
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 190
VariableString = Input (LOF(1), #1)
LOF(1)=longitud del fichero #1
leeremos el fichero de una única vez. Este procedimiento puede ahorrarle cierto tiempo a la hora de la
lectura. (Por lo dicho anteriormente, este procedimiento de leer todo el fichero de un golpe solamente se
podrá hacer si la longitud del fichero (LOF(1)) es inferior a 65.534 bytes. Tenga esto presente cuando
vaya a leer un fichero que no sabe que longitud tiene. Para curarse en salud, le recomiendo que lea los
ficheros secuenciales carácter a carácter. Input(1,#X) pues tarda poco mas que leyéndolo de un golpe.
Claro que para leer un fichero carácter a carácter debe poner un bucle en el que se van leyendo los
caracteres hasta que llaga al final del fichero..
La forma de hacer este bucle es la siguiente:
A es la variable donde meteremos el carácter que extraemos del fichero.
Dim A As String
Dim MiVariable as String
MiVariable es una variable tipo string donde vamos a meter todo el
contenido del fichero
Do Until EOF(1)
El programa ejecutará este bucle hasta que se cumpla que EOF(1) sea
True. EOF(NumerodeCanal) es una propiedad de los ficheros cuando
están abiertos, que es True cuando la posición del puntero de lectura
apunta al carácter Fin De Fichero (End Of File) que es el carácter siguiente
al último carácter de texto de ese fichero.
A = Input (1, #1)
Estrae un carácter del fichero abierto por el canal número 1. Al leer este
carácter, el puntero de lectura avanza automáticamente tantos caracteres
como haya leído, colocándose sobre el primer carácter no leído.
MiVariable = MiVariable & A
Con esta línea vamos anexando el carácter leído a la variable
MiVariable. En vez de utilizar una variable, podríamos poner ese
texto sobre un TextoBox o un RichTextBox (RTB) (Lo verá
proximamente). Si lo ponemos en un RTB esta línea sería:
RTB.SelText = A
Loop
Vuelve al comienzo del bucle.
Close #1
Cierra el fichero
Sólo se utilizará la instrucción Input con archivos abiertos en modo Input o Binary. (Los Binary Se verán
a continuación) A diferencia de la instrucción Input #, (la veremos a continuación, pues es la instrucción
que deberá utilizar para leer archivos escritos con la instrucción Write ), Input devuelve todos los
caracteres que lee, incluyendo puntos y coma, retornos de carro, avances de línea, comillas y espacios
iniciales.
Existe una instrucción, Input$ , que asume que el dato a leer es un String. (Cadena de caracteres).
Puede ahorrar un poco de memoria usando esta instrucción en lugar de Input.
Nota Se proporciona otra función (InputB) para su uso con datos de byte incluidos en archivos de texto.
En lugar de especificar el número de caracteres a devolver, número especifica el número de bytes.
INSTRUCCION LINE INPUT
La instrucción Line Input se utiliza para extraer una línea completa. Tiene la siguiente sintaxis:
Line Input # Número de canal, VariableString
Mediante esta instrucción se extrae una línea completa (los caracteres delimitados entre dos retornos de
carro), y se le asigna esa cadena a VariableString
Una línea es un trozo de texto delimitado por los caracteres 13 (Retorno de carro) y 10 (Avance de línea)
La instrucción Line Input # lee un carácter cada vez en un archivo hasta que encuentra un retorno de
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 191
carro (Chr(13)) o una secuencia retorno de carro - avance de línea (Chr(13) + Chr(10)). Las secuencias
de retorno de carro - avance de línea no se tienen en cuenta y no se añaden a la cadena de caracteres
extraída mediante esta instrucción. Cuando lea un archivo mediante Line Input # y lo quiere presentar
en un TextBox o en el Printer, deberá introducirlos para evitar que le salga todo el texto en una única
línea.
Con lo que se ha explicado, ya puede realizar un pequeño edito de textos. Este sencillo editor tiene un
TextBox llamado TBTexto, donde podemos escribir el texto que queramos (con la propiedad MultiLine =
True y ScrollBars = Vertical), tres botones llamados BAbrir (1), (2 a y b) y (3), para abrir el fichero y
poner su contenido en TBTexto, y dos BGuardar para guardar, uno abriendo el fichero For Append y el
otro abriéndolo For Output. En este último, al guardar el texto borramos el contenido que del fichero, si
ya existiera. En el primero, lo anexamos al final del mismo . Para conocer el nombre del fichero,
ponemos un CommonDialog llamado CD1, con un filtro CD1.Filter = “Ficheros de Texto |*.txt”
Para abrir el fichero, y depositar su contenido en TBTexto pondremos este código en BAbrir :
Private Sub BAbrir1_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
VarTexto = Input(LOF(1), #1)
'leemos todo el fichero de un golpe
Close #1
TBTexto = VarTexto
End Sub
Cuando el fichero es mayor de 64 kilobytes, el leerlo de un golpe puede dar problemas. Mejor dicho, no
funciona. Deberemos leerlo en ese caso, carácter a carácter o línea a línea.
Para leer carácter a carácter :
Private Sub BAbrir_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
‘Hacemos un bucle de lectura hasta que encontremos EOF(1)
‘ Vea mas adelante la Propiedad EOF en Propiedades de los ficheros Secuenciales
VarTexto = Input(1, #1)
'leemos el fichero carácter a carácter
TBTexto = TBTexto & VarTexto
'vamos añadiendo los caracteres leídos a TBTexto
Loop
Close #1
End Sub
(NOTA.- Lo expuesto funciona perfectamente, pero el hecho de meter en un TextBox carácter a carácter
eterniza la aplicación. - Meter un texto en un TextBox o en un Label es una operación que tarda cierto
tiempo. Si esa operación hay que hacerla una vez por carácter, puede tardar mucho tiempo. Para evitar
esto, cuando vaya a leer un fichero carácter a carácter, métalo primero en una variable y luego realice un
volcado único de esa variable al TextBox o Label)
Y podemos hacerlo también leyendo línea a línea con Line Input
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
Line Input #1, VarTexto
'leemos el fichero Línea a Línea
TBTexto = TBTexto & VarTexto & vbCrLf 'vamos añadiendo las líneas leídas a TBTexto
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 192
'(Hay que introducir un retorno + avance de línea con cada línea (vbCrLf), ya que VarTexto no
‘contiene los retornos ni avances de línea.
Loop
Close #1
Los Botones de Guardar tienen el código :
Private Sub BGuardar_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowSave
Open CD1.filename For Output As #1
Print #1, TBTexto.Text
Close #1
End Sub
O para el caso de abrir con For Append
Private Sub BGuardar2_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowSave
Open CD1.filename For Append As #1
Print #1, TBTexto.Text
Close #1
End Sub
Ya hemos visto como se guardan y se leen datos de texto en un fichero secuencial.
INSTRUCCIÓN WRITE
La otra forma de introducir datos en un fichero secuencial es Write. Mediante esta instrucción, no se
puede introducir texto, sino datos, aunque esos datos sean de texto. Mediante la instrucción Write
puede crear una pequeña base de datos. Eso sí, una base de datos de escasa calidad. Pero no es
momento de cuestionar la calidad de esta base de datos, sino de explicarla.
Write
Puede introducir varias informaciones, que posteriormente se podrán leer de forma
separada con la instrucción Input #. Esta forma de introducir datos en un fichero
secuencial permite realizar un fichero con distintos datos que se pueden leer en el propio
fichero, puesto que se guardan en ASCII, y leerlos mediante el programa de una forma
muy sencilla. Hacemos, en realidad, una pequeña base de datos. (Verá a lo largo de su
vida profesional que lo de pequeña no es cierto, pues es la forma mas sencilla de
guardar datos cuando la cantidad de estos datos no es muy grande)
Lo que estamos haciendo en realidad al escribir datos mediante la instrucción Write es escribir estos
datos en un fichero secuencial, utilizando una coma como separador entre los distintos datos. Un fichero
secuencial con datos introducidos mediante la instrucción Write tendrá esta forma :
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
“Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27”
Observe que el contenido de este fichero se diferencia algo de una simple sucesión de caracteres. Tiene
varias partes separadas por una coma. Cada una de ellas es un dato.
Imaginemos una aplicación, con la que introducimos datos de libros. La aplicación es un único formulario
donde podemos introducir la información mediante varios TextBox. Existe un Botón de comando con el
siguiente código:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 193
Private Sub Command1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
PRECIO = LIBRETBPREC.Text
EXISTENCIAS = LIBRETBEX.Text
‘Donde LIBRETBTITULO, LIBRETBAUTOR, Etc. son los nombres de los TextBox
‘Ha leído los datos de los TextBox. Ya están el las variables TITULO, AUTOR, Etc.
‘Ahora los metemos en el fichero con la instrucción Write. El nombre del fichero será el
‘que hayamos puesto en el TextBox LIBRETBFICHERO, y lo guardará en el directorio
‘C :\cursoVB
Open TBNombreFichero.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, PRECIO, EXISTENCIAS
Close #1
End Sub
Si introduce los datos del ejemplo anterior, se creará un fichero que tiene esta apariencia:
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
Si realizamos otra introducción de datos, con la segunda línea del ejemplo anterior, los datos existentes
en ese fichero no se borrarán, dado que lo hemos abierto con Append. Quedará de la siguiente forma:
“Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51”
“Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27”
¿Que pasaría si leemos este fichero con la instrucción Input o Line Input # vista anteriormente ? Pues
simplemente que lo leeríamos tal como está, con sus comas y comillas dobles. No sería la forma mas
adecuada, ya que lo que queremos es obtener sucesivos datos de autores, títulos, editoriales, precios y
existencias.
Para sacar estos datos debemos leerlos con la instrucción Input #. Esta instrucción saca los datos que
hemos metido, es decir, elimina las comillas y la coma que servían de separadores.
En nuestro ejemplo, podríamos hacerlo de esta forma, aprovechando los mismos TextBox:
Private Sub Command2_Click()
' Limpiamos los TextBox
LIBRETBTITULO.Text = "" : LIBRETBAUTOR.Text = "" : LIBRETBEDITORIAL.Text = ""
LIBRETBPREC.Text = "" : LIBRETBEX.Text = ""
'Abrimos el fichero
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
' Introducimos una parada para poder leer datos
DETENERSE = True
Input #1, TIT, AUT, NED, PRE, EXS
LIBRETBTITULO.Text = TIT
LIBRETBAUTOR.Text = AUT
LIBRETBEDITORIAL.Text = NED
LIBRETBPREC.Text = PRE
LIBRETBEX.Text = EXS
' Refrescamos los TextBox
Refresh
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 194
' Esto produce una pequeña parada
Do While DETENERSE = True
A=A+1
If A = 100000 Then DETENERSE = False: A = 0
Loop
' terminó la parada y vuelve a leer datos
Loop
Close #1
End Sub
Observe que los nombre de las variables en el proceso de lectura tienen distintos nombres a los
utilizados durante la escritura. Como en el fichero no se guarda ninguna referencia al respecto, lo único
que importa es que el número de variables para la lectura sea igual al número de variables que se utilizó
para la escritura, y que el orden de las variables sea correcto. Si por ejemplo, el número de variables
usadas en la introducción de datos fuese distinto al número de variables usado en la lectura, Visual Basic
nos daría un error.
Observe también que se ha introducido un temporizador. Sirve para ver los sucesivos títulos que
tenemos en nuestra base de datos tan sui generis. Se ha pretendido presentar unos datos de esta
pequeña base de datos sin complicarnos mucho la vida. Mas adelante veremos como presentarlos de
una forma correcta. Este tipo de ficheros no es el mas adecuado para construir bases de datos, es
complicado manejar ficheros de mas de unas pocas líneas, por lo que para tener muchos datos, este
tipo de ficheros no es recomendable. No es aconsejable ni para muchos datos ni para pocos datos. Pero
es obligación del autor explicarlo … y de advertirlo.
En esta pequeña aplicación mostrábamos las informaciones sucesivamente según las íbamos leyendo
del fichero. Interrumpíamos momentáneamente la lectura para presentar cada información durante un
instante, ya que como tenemos cinco datos distintos en cada registro y cinco TextBox para presentarlos,
deberemos presentar una información tras otra. Esto no parece en principio una solución práctica para
una base de datos, donde lo que interesa es disponer de todos los datos para usarlos cuando sea
necesario. Esto nos lleva a crear una matriz para albergar todos los datos de la base, ya que los ficheros
secuenciales se leen y se les tiene que extraer toda la información de un golpe, ya que no permiten ir a
leer hacia atrás. Por lo tanto, si deseamos disponer de todos los datos, deberemos guardarlos en la
memoria, en una matriz. Imagínese que estamos tratando datos de varios miles de libros en el ejemplo
anterior. Si la información de cada campo es medianamente extensa, no tendríamos memoria RAM
suficiente en el ordenador para albergarlos. Esto nos lleva a pensar en otro tipo de archivo que veremos
a continuación, los Random (aleatorios), que permiten leer solamente los registros que nos interesan.
Pero volvamos a nuestra aplicación de librería, donde hemos hecho una variación, los campos PRECIO
y EXISTENCIAS los vamos a tratar ahora como números (Integer). También se ha introducido otro
campo tipo texto, para introducir la edición. El fichero creado tras introducir varios libros quedó de la
siguiente forma :
"EL RODABALLO","GUNTER GRASS","PLANETA",”1995”,2000,12
" VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21
"EL NOMBRE DE LA ROSA","UMBERTO ECO","AGUILAR",”28”,1000,21
"ENCICLOPEDIA DEL VB","CEBALLOS","RAMA",”CUARTA”,1200,23
"LA GRANJA ANIMAL","ORWELL","DESTINO",”45”,12000,78
"LA PASION TURCA","ANTONIO GALA","PLANETA",”SEGUNDA”,2500,25
"LA METAMORFOSIS","KAFKA","PLAZA&JANES", “4ª”,3400,101
"VB4 PARA WINDOWS95","GARY CORNELL","MCGRAWHILL",”1ª”,6500,25
Observe que los dos últimos campos (correspondientes a PRECIO y EXISTENCIAS) no están entre
comillas, pues no se trata de texto, sino de números.
(Observe también la gran ventaja de tener una base de datos con datos completamente legibles)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 195
Se han introducido alguna variaciones en el programa. Entre ellas, se crea una matriz de variables de 5 x
n (n=número de registros). También se le añaden unos botones para poder recorre toda la base de
datos.
La interfaz gráfica quedó de la siguiente forma :
El programa necesita que le introduzcamos el nombre del fichero que alberga la base de datos. Por
sencillez no se ha usado ningún CommonDialog y se introduce directamente el nombre de este fichero
en un TextBox llamado TBNombreFichero
El fichero anterior podemos leerlo tal y como indicábamos antes :
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
Input #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Donde las variables TITULO, AUTOR, EDITORIAL y EDICION serán del tipo String y PRECIO y
EXISTENCIAS serán de tipo numérico. Podemos saberlo, ya que en una línea cualquiera del fichero
anterior :
" VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21
los cuatro primeros parámetros van entre comillas dobles, ya que son datos tipo texto, y los dos últimos
van sin comillas, como corresponde a datos numéricos.
Pero existe otra forma mejor (al menos un poco mas complicada) para leer estos datos, y evitar el
problema que teníamos antes de tener que hacer un temporizador para poder ver, aunque solo sea un
momento, los datos. Podemos meter los datos a una matriz que tenga tantas columnas como datos
(campos) (en el ejemplo 6, cuatro String y dos numéricos), y tantas filas como apuntes (registros)
tengamos.
Para ello, antes de nada debemos definir un tipo de variable, mediante la instrucción Type. Parece que
no nos basta con los tipos de variable que trae VB (Long, String, Integer ...) y es cierto. La variable que
necesitamos no es de ningún tipo de esos. Está compuesta por varias secciones, y cada una de ellas
puede ser de un tipo distinto. Este tipo de definiciones debe hacerse en un módulo (Véase instrucción
Type en la ayuda de VB), por lo que se ha creado un módulo llamado LIBREMD2.BAS, con el siguiente
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 196
código :
Type REGISTROLIBRO
AUTOR As String
TITULO As String
EDITORIAL As String
EDICION As String
PRECIO As Integer
EXISTENCIAS As Integer
End Type
Esto es lo que se llama DEFINIR una variable. Es como hacerse un traje a medida. Y dese cuenta de
que es un tipo de variable (REGISTROLIBRO) formado por varias partes (AUTOR, TITULO, Etc.)
Observe que DEFINIR una variable NO es lo mismo que DECLARAR
En el apartado de Declaraciones del General del formulario declaramos las variables, entre ellas una
variable, REGISTROLIBROS, de la cual decimos que va a ser una matriz mediante los paréntesis que la
acompañan, y además declaramos que va a se similar a REGISTROLIBRO ya definida en el módulo.
Dim NR As Integer
Dim REGISTROLIBROS() As REGISTROLIBRO
Dim NRP As Integer
Observe que al usar paréntesis al declarar la variable REGISTROLIBROS le estamos diciendo a VB que
esa variable será un Array, y además que es una variable del tipo REGISTROLIBRO, tipo de variable
que ya conoce, puesto que se la hemos definido en un módulo.
En el ejemplo preparado podemos escribir y leer datos. Veamos de nuevo como se escriben
El código del procedimiento click del botón BIntroducir1 es :
Private Sub BIntroducir1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
EDICION = LIBRETBEDICION.Text
PRECIO = Val(LIBRETBPREC.Text)
EXISTENCIAS = Val(LIBRETBEX.Text)
‘TextBox para introducir el título
autor
‘
editorial
‘
edición
‘
precio
‘
existencias
‘
‘(Observe que para introducir el precio y las existencias se transformó el contenido del TextBox a ‘un
valor numérico mediante la instrucción Val.)
Open "C:\cursoVB\" + LIBRETBFICHERO.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Close #1
End Sub
Tras reiteradas entradas, el fichero de la BD quedó como se vio anteriormente.
Al leer los datos, lo primero es que no conocemos el número de registros existentes. Como cada registro
va en una línea del fichero, si contamos el número de retornos de carro (Chr(13)) obtendremos el
número de registros. Esta operación es la primera que se realiza en el procedimiento click del botón
LEER :
Private Sub Command2_Click()
LIBRETBTITULO.Text = ""
‘Pone todos los TextBox en blanco
LIBRETBAUTOR.Text = ""
LIBRETBEDITORIAL.Text = ""
LIBRETBEDICION.Text = ""
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 197
LIBRETBPREC.Text = ""
LIBRETBEX.Text = ""
NR = 0
‘ NR=número de registros
‘ Abre el fichero, lo lee entero y cuenta el número de retornos de carro. Existirán tantos apuntes
(registros) como retornos de carro existan, ya que cada registro ocupa una línea.
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
A = Input(1, #1)
If A = Chr(13) Then NR = NR + 1
Loop
Close #1
‘ Presenta en LNumFich el número de registros
LNumFich.Caption = Str(NR) + " Registros)"
'Redimensionamos la matriz de REGISTROLIBROS a NR elementos..
ReDim REGISTROLIBROS(1 To NR)
‘Volvemos a abrir el fichero
Open TBNombreFichero.Text For Input As #1
‘Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando a los elementos ‘que
componen la matriz.
For I = 1 To NR
Input #1, REGISTROLIBROS(I).TITULO
Input #1, REGISTROLIBROS(I).AUTOR
Input #1, REGISTROLIBROS(I).EDITORIAL
Input #1, REGISTROLIBROS(I).EDICION
Input #1, REGISTROLIBROS(I).PRECIO
Input #1, REGISTROLIBROS(I).EXISTENCIAS
Next I
Close #1
NOTA.- Estas líneas podríamos heberlas puesto en una línea única :
Input#1 ,REGISTROLIBROS(I).TITULO,REGISTROLIBROS(I).AUTOR,_
REGISTROLIBROS(I).EDITORIAL,REGISTROLIBROS(I).EDICION,_
REGISTROLIBROS(I).PRECIO,
REGISTROLIBROS(I).EXISTENCIAS
‘NRP = Número del Registro Presentado. Lo hacemos igual a 1 para presentar, de momento, el ‘número
1
NRP = 1
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Copiamos este código de presentación de datos y lo llevamos a las flechas de incrementar o disminuir el
número del registro a presentar.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 198
Private Sub BMas1_Click()
NRP = NRP + 1
If NRP > NR Then
‘protegemos que salga error de NRP fuera d e intervalo
MsgBox "No existen mas registros en esta dirección"
NRP = NR
Else
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End If
End Sub
Esta es la de incrementar. La de disminuir es igual, pero restando 1 a NRP
Las flechas dobles llevan al registro 1 y al último. Tienen este código
Private Sub BMas2_Click()
NRP = NR
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Observe que es muy sencillo trabajar con ficheros secuenciales para bases de datos. El inconveniente
es la cantidad de memoria necesaria para la matriz de datos. También tienen un gran inconveniente:
solamente se pueden leer de hacia adelante. Un fichero secuencial hay que leerlo de una sola vez. Esto
que no es ningún inconveniente para un fichero de texto, o incluso para un fichero de datos que leemos
una única vez, es un problema cuando leemos un dato situado en un punto de ese fichero, y luego
tenemos que leer un dato colocado en una posición anterior. En este caso, deberemos terminar de
leerlo, y volver a comenzar por el principio. Este es un gran inconveniente para hacer bases de datos con
ficheros secuenciales.
No solamente hemos visto una forma de crear una base de datos, sino que hemos visto como movernos
a lo largo de los registros. Verá esto con mucho mas detalle cuando demos bases de datos. Este tipo de
bases de datos son la Tipo Texto que verá mas adelante.
Propiedades de los ficheros Secuenciales:
EOF
Indica el fin del fichero (End Of File). EOF será False hasta que encuentre el final del fichero
secuencial. Habrá observado instrucciones tales como:
Do until EOF(1)
(Hazlo hasta que encuentres el EOF del canal 1)
Do While Not EOF(1) (Hazlo mientras EOF del canal 1 sea False)
Estas expresiones se usan en un bucle, para ir extrayendo con la instrucción Input o Line Input
los caracteres de un fichero hasta que se encuentre la marca de final de fichero (EOF)
LOC
Devuelve la posición de lectura/escritura actual en un archivo abierto.
La sintaxis de esta propiedad es: LOC (Numero de canal)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 199
la información devuelta para un archivo secuencial es la posición de byte actual en el archivo,
dividida por 128.
LOF
Devuelve la longitud de un fichero (Lenght Of File) abierto mediante Open.
Sintaxis
LOF(numeroarchivo)
Ejemplo Long = LOF (1)
Observaciones Para obtener la longitud de un archivo que no está abierto utilice la función
FileLen. (Véala mas abajo)
SEEK
Devuelve la posición actual de lectura/escritura de un archivo abierto con la instrucción Open.
Sintaxis
Seek(númeroArchivo)
Seek devuelve un valor entre 1 y 2,147,483,647 (equivalente a 2^31-1) inclusive. Para archivos abiertos
en modo Output, Append o Input, Seek devuelve la posición de byte en la que se va a ejecutar la
siguiente operación. El primer byte de un archivo está en la posición 1, el segundo en la posición 2 y así
sucesivamente.
FICHEROS ALEATORIOS (RANDOM)
Un fichero aleatorio es un conjunto de registros, todos ellos de la misma longitud, que nos permite
guardar varias colecciones de datos.
Tal como habíamos visto en los ficheros secuenciales, el almacenar una serie de colecciones de datos
en un fichero secuencial era muy fácil, pero bastante difícil de almacenarlas en la memoria cuando el
número de estas colecciones superaba una cierta cantidad.
Los ficheros aleatorios permiten almacenar información en registros que pueden ser fácilmente leídos,
pudiendo leer los registros uno a uno, sin necesidad de leerlos todos. En los archivos secuenciales, la
información de varios datos podíamos introducirla mediante la instrucción Write, y conseguíamos un
registro de la forma: (Recuérdese el ejemplo de los datos de un libro)
"Título","Autor","Editorial","Edición","Precio","Existencias"
Si deseábamos guardar la información de muchos libros, no había mucho problema para guardarla, pero
sí para almacenarla en memoria para poder usarla luego. Teníamos que leer todo el fichero, y extraer de
él la colección de informaciones y guardarlas en una matriz. Cambiar una información dentro del fichero
secuencial también implica una complicación adicional, ya que debemos rehacer el fichero completo,
pues un fichero secuencial no permite “remendar” el trozo que queremos cambiar.
Los ficheros aleatorios nos permiten guardar una información similar a la anterior, referida a cualquier
número de libros, y para leerla no es necesario leer todo el fichero, sino simplemente acceder a los
registros que nos interesen. También permite realizar el cambio de un registro de una forma sencilla, sin
alterar los demás.
Todo esto tiene un precio: En los archivos secuenciales, podíamos introducir informaciones de cualquier
longitud. En los archivos aleatorios cada dato tiene una longitud asignada, longitud que no se puede
sobrepasar, y si la información que debemos almacenar tiene menos que la longitud preestablecida,
perderemos esa capacidad sobrante.
Para abrir un fichero aleatorio debemos emplear la expresión:
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
Nombrefichero es el nombre que queremos dar al fichero
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 200
Numerocanal es el número del canal (número de fichero) que puede ser de 1 a 255
LogitudRegistro es la longitud total del registro.
Un fichero aleatorio (Random), una vez abierto, puede utilizarse para leer o escribir datos.
Para escribir datos en un fichero aleatorio, primero debemos definir el registro, es decir, en el caso de los
libros visto anteriormente, un registro va almacenar los datos del titulo, autor, editorial, etc. Para "saber"
como se colocan estos datos dentro del registro será necesario definirlo.
En realidad lo que vamos a hacer es definir una variable de las denominadas “Definidas por el usuario”
Con esto lo que hacemos es crear un nuevo tipo de variable, en el ejemplo, la variable tipo Registro.
Se debbe hacer en la sección de declaraciones de un módulo o de un formulario, y siempre antes de
declarar una variable como variable de ese tipo. (La definición de la variable debe hacerse en la sección
de declaraciones del módulo o formulario con ámbito suficiente para que sea válida en todas las partes
de la aplicación donde se necesite esa variable)
Podemos hacerlo con la instrucción Type:
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Asignamos 30 caracteres para el título
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
Observe la diferencia de esta definición con la que hacíamos en los ficheros secuenciales. En aquellos
no poníamos la longitud de cada sección. Aquí es necesario, ya que la longitud de un registro (y también
de cada campo) es fija.
Ya una vez definido como es Registro, podemos decir que una variable es del tipo definido para
Registro, es decir :
Dim MiVariable as Registro
Entonces MiVariable ya puede almacenar los datos de Titulo, Autor, Editorial, Edición, Precio y
Existencias, colocando un dato tras otro, sin ninguna separación, en el mismo orden que lo habíamos
definido para Registro. No es necesario utilizar separaciones ya que el programa sabe que longitud
tiene cada dato y el orden de colocación. Lo sabe porque se lo hemos dicho al definir Registro. Si los
datos a introducir son :
Titulo :
Autor :
Editorial :
Edición :
Precio :
Existencias :
Guía del Estudiante
Luis Suárez Bernaldo
Ediciones XX
2ª
3500
25
el registro correspondiente a este libro tendrá una forma mas o menos así :
Guía del Estudiante///////////Luís Suárez Bernaldo//////////Ediciones XX///2ª////350025/
donde se ha sustituido el carácter nulo por una barra ( / ) con el fin de hacerlo visible en el texto. Si se
molesta en contar los caracteres que tiene el registro observará que son 88, que es la suma de 30 + 30 +
15 + 6 + 4 + 3 que son los caracteres asignados a cada uno de las partes que forman el registro (Título,
Autor, etc.) Para hablar con propiedad, a esas partes que componen el registro lea vamos a llamar
CAMPOS. Un Registro está formado por varios Campos, y cada Campo contiene una información.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 201
Imagínese que introducimos otro libro. El primer campo de ese nuevo registro se colocará en el fichero
inmediatamente después del último campo existente, sin ningún tipo de separación. No hace falta esa
separación, pues VB conoce donde finaliza un registro y comienza otro, ya que la longitud total del
registro se le ha introducido en la instrucción para abrir el fichero, que repetimos aquí por comodidad :
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
(Si se omite el dato LongitudRegistro VB colocará la longitud por defecto, 128 caracteres)
LongitudRegistro deberá ser igual o mayor que la suma de caracteres de cada uno de los campos
declarados en la instrucción Type, que también reproducimos :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Asignamos 30 caracteres para el título
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
¿Deberá ser igual o mayor, o estrictamente igual ? La respuesta es igual o mayor . Pero si declaramos
en la instrucción Open que el registro es mayor que la suma de los caracteres de todos los campos que
lo componen, estaremos perdiendo espacio de disco duro, tanto como la diferencia entre lo declarado en
la instrucción Open menos la suma de los caracteres de cada uno de los campos. Y esa cifra,
multiplicada por el número de registros existentes. Por lo tanto debe declararse en la instrucción Open
exactamente la suma de los caracteres de todos los campos. En el ejemplo anterior era bastante fácil, ya
que todos los campos eran del tipo String (cadena de caracteres) y cada carácter ocupa un byte. La cosa
se complica si uno o varios de los campos son de tipo numérico, porque nos obligará a recordar cuantos
bytes ocupa un integer, un Long, etc. Si hubiésemos declarado en la instrucción Type Precio as Long,
Existencias as Integer deberíamos tener en cuenta que un Long (número entero entre -2.147.483.648 y
2.147.483.647, inclusive) ocupa 4 bytes y un integer (número entero entre -32.768 y 32.767) ocupa 2
bytes. Se reproduce a continuación la longitud en Bytes de cada uno de los tipos de datos. No se
moleste en aprendérsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como
Resumen de tipos de datos. Pero fíjese en algo tan curioso como que un dato tipo Boolean que
solamente puede tomar 2 valores (Sí / No) ocupa 2 bytes frente a un dato tipo Byte, que puede tomar
256 valores y ocupa solamente un Byte.
Tipo de Dato
Byte
Boolean
Integer
Long(entero largo)
Single(coma flotante Simple precisión)
Double(coma flotante Doble Precisión)
Currency
Date
Object
String (longitud variable)
String (longitud fija)
Variant (con números)
Variant (con caracteres)
Ocupa
1 byte
2 bytes
2 bytes
4 bytes
4 bytes
8 bytes
8 bytes
8 bytes
4 bytes
10 bytes + longitud de cadena
longitud declarada de la cadena
16 bytes
22 bytes + longitud de cadena
Ya le estoy viendo tomando buena nota de cuanto ocupa cada variable. Y echando números para saber
la longitud exacta de la variable y no perder ningún byte del disco duro desaprovechándolo sin
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 202
información. ¿No habrá algo que nos lo facilite ? Sí, lógicamente. La instrucción LEN
LEN nos da la longitud de un texto (Var=Len (“Hola que tal”), o de una variable Var=Len(Variable)
Podemos usarla para conocer la longitud total de la variable MiVariable
LongitudRegistro = Len (MiVariable)
Pero si quiere reducir mas la cosa, abra el fichero de esta forma :
Open Nombrefichero For Random As # Numerocanal Len = Len (MiVariable)
Ni que decir tiene que si se abre ese fichero en varias partes del programa con distintas instrucciones
Open el valor de LongitudRegistro debe ser igual en todas ellas.
La declaración del registro mediante la instrucción Type debe hacerse en la sección de declaraciones de
un Módulo. Esta instrucción Type en realidad lo que está haciendo es definir un nuevo tipo de variable,
(una variable definida por el usuario) que servirá de “muestra” para que en otra parte del programa le
digamos, mediante una instrucción Dim, que tal variable es del tipo definido anteriormente mediante la
instrucción Type. Por lo tanto, debemos declarar una variable en la parte que corresponda del programa,
dependiendo del ámbito que se le quiera dar a esa variable, diciendo que será del tipo de la declarada
mediante la instrucción Type.
Usando la declaración de Registro del ejemplo anterior, vamos a retomar el ejemplo de la biblioteca.
Declararemos (posiblemente en la sección de declaraciones del formulario) una variable que llamaremos
p.e. REGLIBROS de la siguiente forma :
Dim REGLIBROS as Registro
A partir de este momento, el programa sabe que REGLIBROS es una variable que tiene 6 campos
(Titulo, Autor, Editorial, Edición, Precio y Existencias) y que cada campo tiene los caracteres
especificados en la instrucción Type.
Ahora nos cabe una pregunta ¿Cuantos registros tiene un fichero Random? La respuesta es sencilla.
Basta conocer la longitud del fichero mediante la instrucción LOF si el fichero ya está abierto, o con la
instrucción FILELEN si no lo está, y dividir el dato obtenido con cualquiera de las dos instrucciones
anteriores por el valor LongitudRegistro.
Escribir datos en un fichero Random. Instrucción Put
Una vez abierto el fichero Random podemos leer y escribir datos en él. Para escribir datos utilizaremos la
instrucción Put. La sintaxis de Put es la siguiente:
Put # Numerocanal , NumeroRegistro, Variable
Puede omitirse NumeroRegistro. En este caso, el número de registro que se escribirá será el siguiente al
último registro escrito.
NumeroRegistro es el número del registro que queremos escribir, y Variable es el contenido de ese
registro. Siguiendo con nuestro ejemplo de biblioteca, Variable tiene en este caso el nombre
REGLIBROS, que no es un String ni un Integer, sino una variable definida por el usuario ya que la
declaramos con Dim REGLIBROS as Registro. Por lo tanto, la variable REGLIBROS contendrá los
mismos campos que habíamos declarado para Registro en la instrucción Type. Recuerde :
Type Registro
Titulo As String * 30
LSB
Visual Basic – Guía del Estudiante
Asignamos 30 caracteres para el título
Capítulo 1
Página 203
Autor As String * 30
Editorial As String * 15
Edición As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Otros 30 para el autor
Asignamos 15 caracteres para editorial
Asignamos 6 caracteres para Edición
Asignamos 4 caracteres para el precio
Tres caracteres para existencias.
Luego REGLIBROS tendrá 6 campos (Titulo, Autor, Editorial, Edición, Precio y Existencias), cada uno de
una longitud determinada, la definida en la instrucción Type.
Antes de introducir REGLIBROS en el fichero habrá que decir que valor tiene. Pero cada campo que lo
compone tendrá un valor. Podríamos hacer una aplicación en la que, a través de varios TextBox, le
introdujésemos los valores de los campos, y el número de registro en el cual queremos escribir. El
nombre de cada uno de los TextBox para cada uno de los datos es el siguiente :
Campo Título : TBTITULO Campo Autor : TBAUTOR Campo Editorial : TBEDITORIAL
Campo Edición :TBEDICION Campo Precio : TBPRECIO Campo Existencias : TBEXISTENCIAS
La aplicación deberá introducir en cada campo el valor (string) existente en cada uno de esos TextBox.
El valor de la variable REGLIBROS lo compondremos de la siguiente forma :
REGLIBROS.Titulo = TBTITULO.Text
REGLIBROS.Autor = TBAUTOR.Text
REGLIBROS.Editorial = TBEDITORIAL.Text
REGLIBROS.Edicion = TBEDICION.Text
REGLIBROS.Precio = TBPRECIO.Text
REGLIBROS.Existencias = TBEXISTENCIAS.Text
(Si se hubiese omitido alguna de estas igualdades, el campo correspondiente contendría el valor nulo)
De esta forma, REGLIBROS ya tiene un valor que se puede escribir en el fichero mediante la instrucción
Put.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 204
El formulario de esa aplicación tendrá esta forma :
Observe que ya se le han introducido otros controles (TextBox para introducir el nombre del fichero, otro
para el número de registro, botones para leer, escribir, abrir el fichero (EXAMINAR), un par de botones
para subir o bajar el número de registro y un botón para salir de la aplicación. El TextBox para introducir
el nombre del fichero se llama TBNOMBREFICHERO y en el que debemos introducir el número de
registro a leer o escribir TBLEERESCR.
El Botón EXAMINAR cierra cualquier fichero que pudiese estar abierto, abre el fichero indicado en
TBNOMBREFICHERO, calcula el número de registros y escribe este número en el Label con nombre
LNUMFICH. El código de su procedimiento Click es el siguiente :
Private Sub BEXAMINAR_Click()
Close
Open TBNOMBREFICHERO For Random As #1 Len = 88
LONGITUDFICH = LOF(1)
NUMREGS = LONGITUDFICH / 88
LNUMFICH.Caption = NUMREGS
End Sub
‘Cierra cualquier fichero abierto
‘Abre el fichero deseado
‘Obtiene su longitud
‘Calcula el Nº. de registros
‘Pone ese Nº. en el Label
Veamos como se escribe un registro. Analicemos el código del procedimiento click del botón ESCRIBIR
Private Sub BESCRIBIR_Click()
REGISTROLIBRO.Titulo = TBTITULO.Text
REGISTROLIBRO.Autor = TBAUTOR.Text
REGISTROLIBRO.Editorial = TBEDITORIAL.Text
REGISTROLIBRO.Edición = TBEDICION.Text
REGISTROLIBRO.Precio = TBPRECIO.Text
REGISTROLIBRO.Existencias = TBEXISTENCIAS.Text
Put #1, Val(TBLEERESCR), REGISTROLIBRO
End Sub
‘Se asignan los valores de cada
‘uno de los campos de la variable
‘REGISTROLIBROS
‘Se escribe el registro
Observe que el Nº. de registro es el valor que figure en el TextBox TBLEERESCR
Leer datos en un fichero Rando m. Instrucc ión Get
Para leer los datos de un fichero Random utilizaremos la instrucción Get. Su sintaxis es la siguiente :
Get # Numerocanal , NumeroRegistro, Variable
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 205
Puede omitirse NumeroRegistro. En este caso, el número de registro que se leerá será el siguiente al
último registro leído.
La Instrucción Get leerá un registro completo. Ese registro contendrá varios campos, y seguramente nos
interesará conocer el valor de cada campo dentro de ese registro. Variable es una variable que
contendrá todos los campos. En nuestra aplicación de biblioteca, Variable tiene por nombre
REGISTROLIBRO (El mismo que tenía para la instrucción Put de escribir. Es pura comodidad del
programador. Puede tener cualquier otro nombre)
Para obtener el contenido de cada campo, realizaremos un proceso similar al empleado para la escritura,
pero al revés. En nuestra aplicación, pretendemos poner el contenido de cada campo en los mismos
TextBox que se utilizaron para escribirlos. Veamos el contenido del procedimiento click del botón LEER
Private Sub BLEER_Click()
Get #1, Val(TBLEERESCR), REGISTROLIBRO
TBTITULO.Text = REGISTROLIBRO.Titulo
TBAUTOR.Text = REGISTROLIBRO.Autor
TBEDITORIAL.Text = REGISTROLIBRO.Editorial
TBEDICION.Text = REGISTROLIBRO.Edición
TBPRECIO.Text = REGISTROLIBRO.Precio
TBEXISTENCIAS.Text = REGISTROLIBRO.Existencias
End Sub
‘Lee el registro completo
‘Obtiene el valor del campo Ti tulo
‘Autor, Editorial, Edición, Precio
‘y Existencias y los pone en los
‘TextBox correspondientes a cada
‘dato
Funciones e instrucciones aplicables a los ficheros Random.
Funciones Seek y Loc.
En los ficheros Random tienen especial importancia las funciones Seek y Loc.
Mediante la Función Loc podemos conocer la el último registro manipulado, bien por lectura, escritura. Si
abrimos el fichero y no se ha hecho ninguna lectura o escritura de registros, el número devuelto por la
función Loc es 0.
La sintaxis de la función Loc es :
Variable = Loc (Numerocanal)
Variable tomará un valor igual al número del registro escrito o leído por última vez.
Mediante la Función Seek podemos conocer el próximo registro que será manipulado en una operación
de lectura o escritura. Si abrimos el fichero y no se ha hecho aún ninguna operación de lectura o
escritura, Seek devuelve el valor 1.
La sintaxis de la función Seek es :
Variable = Seek (Numerocanal)
ATENCION
¡¡¡ Seek pu ede ser un a fun ción (lee un Dato ) o una in stru cc ión (fuerza un d ato) ! ! !
Instrucción Seek
La instrucción Seek establece el próximo registro a leer o escribir en un fichero Random.
Sintaxis
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 206
Seek (Numerocanal), posición
posición es el número de registro que se va a leer o escribir en la siguiente operación. No acepta el 0
como número de registro, el mas bajo debe ser el 1. Si se intenta forzar a la posición 0 dará un error.
Funciones de los ficheros Random:
EOF
Devuelve un valor que indica si se ha llegado al final de un archivo.
Sintaxis
EOF(Numerocanal)
En archivos Random, EOF devuelve False hasta que se haya ejecutado una instrucción Get y no haya
podido leer el registro completo, en cuyo caso devolverá True.
La función EOF no suele emplearse en ficheros Random, ya que en estos nos movemos a base de
registros, y es muy fácil controlar cuantos registros existen en el fichero y en que registro nos
encontramos o nos vamos a mover, mediante las funciones LOF, LOC y SEEK
LOF
( Lenght Of File )
Devuelve la longitud de un fichero .
Sintaxis
Variable = LOF(Numerocanal)
Mediante la función LOF podemos conocer el número de registros existentes en un fichero Random,
dividiendo el valor devuelto por LOF por la longitud del registro declarada en la instrucción Open (LEN =
longitud)
Nº. Registros = LOF / longitud
Recuerde
LSB
Para obtener la longitud de un archivo que no está abierto utilíce la función
FileLen.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 207
FICHEROS BINARIOS
Un fichero binario es una sucesión de bytes, uno tras otro, que puede almacenar cualquier tipo de
información. Cuando se explicaban los ficheros secuenciales, decíamos que eran los mas adecuados
para introducir información de un texto, con los Random podíamos realizar una base de datos de forma
sencilla, a base de controlar los registros y sus campos. Con un fichero binario podemos almacenar
cualquier información. (texto y cualquier tipo de datos) .
Para abrir un fichero secuencial se abre utilizando la instrucción :
Open Nombrefichero For Binary As # Numerocanal
Como siempre en VB, Numerocanal puede ser un número comprendido entre 1 y 255, que define ea
fichero. No pueden existir al mismo tiempo 2 ficheros abiertos con el mismo Numero de canal.
Nombrefichero es el nombre completo del fichero, con su Path.
Una vez abierto un fichero se binario, podemos leer o escribir datos en él.
Para escribir uno o varios caracteres en un fichero binario, usaremos la instrucción Put.
Put # Numerocanal, Posición, Variable
Donde Posición es el Byte donde comenzará la escritura, y Variable es el nombre de la variable que
contiene el dato a escribir. Este dato puede ser un byte o varios bytes.
Para escribir varios bytes podemos hacerlo de dos formas :
- Si se puede conocer de antemano el número de bytes a escribir, puede declararse Variable como un
string de ese número de caracteres mediante la instrucción Dim, por ejemplo :
Dim Variable As String * numero de bytes
y en este caso siempre escribirá el número de bytes declarado. ¡ Cuidado ! Si los datos a introducir
sobrepasan el número de bytes declarados para Variable, los datos sobrantes no se escribirán en el
fichero. Si los datos a escribir en el fichero fuesen menos que los declarados para Variable, la diferencia
se rellenará con el byte nulo ( 0 ).
- Si no se conoce de antemano el número de bytes a escribir, podemos declarar la variable sin
especificar el número de bytes que tiene, y de esta forma se escribirán todos los bytes que componen la
variable :
Dim Variable As String
Pero en este caso debemos volver a decir ¡ Cuidado !, si no conocemos el número de bytes que vamos
a escribir, puede que “machaquemos” parte de la información que ya tenemos en el fichero, pues la
instrucción Put va a colocar los bytes que componen Variable en la posición especificada por Posición y
siguientes, hasta que quepa toda la cadena de bytes que le queremos introducir. Si la posición en la que
introducimos esos bytes es una posición intermedia, y no controlamos bien el número de bytes a
introducir y las informaciones que ya existen en el fichero en las posiciones colindantes con las que
vamos a introducir los datos, es muy probable que perdamos esa información al introducir la nueva.
Si se omite el dato Posición, se tomará como byte de inicio de la escritura el siguiente al último usado
por la instrucción Put. Si quiere omitir este dato, debe conservar las comas que lo separan :
Put # Numerocanal, , Variable
¿Qué pasará si el dato Posición indica una posición mayor que la que tiene realmente el fichero ?
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 208
Simplemente que rellenará las posiciones intermedias que se formarán con un byte (puede verlo con el
Block de Notas ÿÿÿ)
Un fichero binario es, como se decía al principio, una sucesión de bytes, que no tiene ningún tipo de
separación entre bytes. Cada dato (byte o conjunto de bytes) que introduzcamos en un fichero binario se
escribirá en el fichero tal y como se introducen. Machacando información ya existente si no se controla
bien donde se mete. Por lo tanto, aunque parece que los ficheros binarios pueden ser mucho mas
versátiles que los secuenciales y los Random, exigen mucho mas control que los anteriores. Limite el
uso de este tipo de ficheros a las aplicaciones en que sea realmente imprescindible.
Para leer datos de un fichero binario, utilizaremos la instrucción Get.
Get # Numerocanal, Posición, Variable
Donde Posición es el número del primer byte leído, que como en el caso de Put, si se omite, tomará
como valor el byte siguiente al usado en la última instrucción Get. Variable es el nombre de una variable
que contendrá los datos leídos.
Pueden leerse uno o varios Bytes, pero ahora surge un pequeño problema. ¿Como le decimos cuantos
bytes debe leer ? Sencillamente los especificados al declarar la variable . Imaginemos que la
declaración de la variable fue :
Dim Variable As String * 10
Con Variable declarada de esta forma, leerá 10 bytes a partir del byte Posición. (Incluido)
De esta forma, siempre leeremos un número determinado de caracteres (10 en el caso del ejemplo).
Esta es una limitación para el uso de Get. Esta función viene muy bien en aquellas aplicaciones en las
que tenemos que extraer un número fijo de bytes (En la práctica, en la mayor parte de las aplicaciones
se extrae de uno en uno)
Pero pueden existir aplicaciones en las que sea necesario leer una vez un número de caracteres, y otra
vez otro. Ese problema lo tenemos resuelto con la instrucción Input.
Podemos leer caracteres de un fichero secuencial mediante la instrucción Input :
Variable = Input (Numero de bytes, # Numerocanal)
Mediante la instrucción Input podemos leer el número de caracteres que queramos, pero no podemos
controlar el byte de comienzo. Por lo tanto deberemos ayudarnos de la instrucción Seek para posicionar
el puntero de lectura encima del primer byte que queramos leer :
Seek (Numerocanal), Número del primer Byte a leer
Por ejemplo, si queremos leer 35 bytes de un archivo binario, abierto con el número de canal 1,
comenzando por el byte 48 (el 48 será el primer byte leído), ejecutaremos las dos siguientes
instrucciones :
Seek (1), 48
Variable = Input (35, #1)
Variable contendrá ahora los 35 bytes deseados.
Al igual que se hizo para los ficheros secuenciales y Random, vamos a ver con un ejemplo práctico
como se manejan los ficheros binarios.
El formulario del ejemplo tiene esta forma :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 209
Con el botón ABRIR se abre el fichero deseado. Si no existe en el disco, lo crea, ya que la instrucción
Open Nombrefichero For Binary As # Numerocanal
intenta abrir un fichero existente llamado Nombrefichero, y si este no existe, lo crea. Si existe el fichero,
presenta todo su contenido en el TextBox inferior, para poder tener una referencia de que lugar ocupan
los distintos caracteres (un fichero binario puede guardar cualquier byte, por lo que si abre un fichero
generado con cualquier programa puede ser que muchos de los bytes no contengan información de un
carácter, por lo que le recomendamos haga esta práctica con un fichero creado por la misma práctica)
El botón CERRAR cierra el fichero. SALIR sale de la aplicación. El TextBox superior (variable) sirve para
introducir la variable a escribir en el fichero, o para presentar la variable leída en caso de lectura . El
TextBox posición sirve para indicar la posición del primer byte. Posición por defecto presenta la posición
que se extrae mediante la función Seek cada vez que se hace una lectura o escritura en el fichero.
Longitud de la variable permite introducir esa longitud, para leer mediante la instrucción Input.
El botón ESCRIBIR escribe el dato Variable en el fichero, LEER (GET) lee un único byte, y LEER
(INPUT) lee una cadena de caracteres, de longitud la especificada en el TextBox Longitud de la variable.
Se enumera a continuación el código de cada uno, dejando para las explicaciones del profesor en clase,
o el estudio del alumno, la interpretación de cada una de susu partes.
FORMULARIO. DECLARACIONES
Option Explicit
‘Obliga a declarar todas las variables
Dim LONGVAR As Integer
‘Se declara la variable LONGVAR
Dim COMIENZA As Long
‘Se declara la variable COMIENZA
Dim TESTO As String
‘Se declara la variable TESTO
Dim pospordef As Long
‘Se declara la variable pospordef
BOTON ABRIR
Private Sub BABRIR_Click()
CD1.ShowOpen
‘CD1 es un CommonDialog para buscar el fichero
Open CD1.filename For Binary As #1 ‘Abre el fichero indicado en CD1
TESTO = Input(LOF(1), #1)
‘Lee de un golpe el fichero y lo mete en la variable TESTO
TBFICHERO.Text = TESTO
‘Presenta el fichero en el TextBox TBFICHERO
End Sub
BOTON CERRAR
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 210
Private Sub BCERRAR_Click()
Close
End Sub
BOTON ESCRIBIR
Private Sub BESCRIBIR_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
Dim escribe As String
escribe = TBVAR1.Text
Put #1, Val(TBVAR3), escribe
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
BOTON LEER (GET)
Private Sub BLEER_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
TBVAR2.Text = "1"
If Seek(1) >= LOF(1) Then
Seek #1, 1
End If
Dim TEXTO As String * 1
If TBVAR3.Text <> "" Then
COMIENZA = Val(TBVAR3.Text)
ElseIf Lvar5.Caption <> "" Then
COMIENZA = Val(Lvar5.Caption)
Else
COMIENZA = Seek(1)
End If
Get #1, COMIENZA, TEXTO
TBVAR1.Text = TEXTO
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
‘La instrucción Close cierra todos los ficheros abiertos
‘Pone el TB long. De la variable en rojo
‘Declara la variable escribe como string, sin limitación
‘Pasa el contenido de TBVAR a la variable escribe
‘Instrucción Put. Val(TBVAR3) es la posición del 1er byte
‘Analiza donde quedó el puntero del fichero
‘y pone este valor en la etiqueta Lvar5
‘Pone en rojo el TB TBVAR2 (long. de la variable)
‘e indica que la longitud leída es 1
‘Si está al final del archivo
‘pone el puntero en la posición 1
‘
‘Declara la variable TEXTO de un byte
‘Si se le ha indicado donde tiene que comenzar
‘le dice que comience en la posición indicada en TBVAR3
‘si no, si existe posición por defecto
‘le indica que comience en la posición por defecto
‘ si no
‘pone el puntero en la posición 1 (byte 1)
‘lee un byte
‘y lo presenta en TBVAR1
‘busca la nueva posición por defecto
‘y pone ese valor en Lvar5
BOTON LEER (INPUT)
Private Sub BLLERINPUT_Click()
TBVAR2.BackColor = RGB(255, 255, 255)
‘Pone TBVAR2 en blanco
LONGVAR = Val(TBVAR2.Text) ‘pasa el valor para long. de variable a LONGVAR
‘si ese valor existe (TBVAR3 es distinto de nada)
If TBVAR3.Text <> "" Then
‘la variable COMIENZA toma ese valor
COMIENZA = Val(TBVAR3.Text)
Seek (1), COMIENZA
‘coloca el puntero en ese valor
End If
‘
Dim TEXTO As String
‘Declara la variable TEXTO sin limitación
TEXTO = Input(LONGVAR, #1)
‘Lee LONGVAR bytes del canal 1 y los pasa a TEXTO
TBVAR1.Text = TEXTO
‘y lo presenta en el TB TBVAR1
pospordef = Seek(1)
‘analiza la nueva posición por defecto
Lvar5 = Str(pospordef)
‘y la presenta en Lvar5
End Sub
‘
BOTON SALIR
Private Sub BSALIR_Click()
End
End Sub
‘Sale de la aplicación.
Private Sub TBVAR2_Change()
TBVAR2.BackColor = RGB(255, 255, 255)
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
‘Vuelve a color blanco si introducimos un dato en
‘este Text Box
Página 211
FIN DE LA APLICACIÓN PARA MANEJO DE FICHEROS BINARIOS
Funciones y propiedades aplicables a todos los ficheros
DIR
Devuelve el nombre de un archivo, directorio o carpeta que concuerda con el patrón o atributo de archivo
especificado o la etiqueta de volumen de una unidad de disco.
Sintaxis
Dir[(nombreruta[, atributos])]
nombreruta
Expresión de cadena que especifica un nombre de archivo. Puede incluir el
directorio o carpeta y la unidad de disco. Si no se encuentra nombreruta, devuelve
Null.
atributos
Constante o expresión numérica, cuya suma especifica atributos de archivo. Si se
omite, devuelve todos los archivos normales que satisfacen el nombreruta.
El argumento atributos tiene estas constantes y valores:
Constante
Valor
Descripción
vbNormal
vbHidden
vbSystem
vbVolume
vbDirectory
0
2
4
8
16
Normal.
Oculto.
Sistema
Etiqueta de volumen; si se especifica se ignoran todos los atributos
Directorio o carpeta.
En Microsoft Windows, Dir permite el empleo de los caracteres comodín '*' (múltiples caracteres) y '?'
(un solo carácter) para especificar varios archivos.
La primera vez que se llama a la función Dir se debe especificar el nombreruta, de lo contrario se
produce un error. Si además se especifican atributos de archivo, se debe incluir el nombreruta.
Dir devuelve el primer nombre de archivo que coincide con el nombreruta. Para obtener más nombres de
archivo que coincidan con el nombreruta, se debe volver a llamar a Dir sin argumentos.
Cuando no hay más nombres de archivo coincidentes, Dir devuelve una cadena de caracteres de
longitud cero. Cuando se devuelve una cadena de longitud cero, en las siguientes llamadas se debe
especificar nombreruta o se producirá un error. Se puede cambiar el nombreruta sin haber obtenido
todos los nombres de archivo que coinciden con el nombreruta actual. Sin embargo, no se puede llamar
a la función Dir.
FILECOPY
Copia un archivo.
Sintaxis
FileCopy fuente, destino
fuente Expresión de cadena que especifica el nombre de un archivo a copiarse puede incluir el
directorio o carpeta y la unidad de disco..
destino Expresión de cadena que especifica el nombre del archivo de destino se puede incluir el
directorio o carpeta y la unidad de disco.
Si intenta utilizar la instrucción FileCopy en un archivo abierto actualmente, se produce un error.
FILEDATATIME
Devuelve una fecha que indica la fecha y hora en que un archivo fue creado o modificado por última vez.
Sintaxis
LSB
Variable = FileDateTime(nombreRuta)
Visual Basic – Guía del Estudiante
Capítulo 1
Página 212
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo. Se puede incluir el directorio o carpeta y la unidad de disco.
FILELEN
Devuelve la longitud de un archivo en bytes.
Variable = FileLen(nombreRuta)
Sintaxis
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo se puede incluir el directorio o carpeta y la unidad de disco.
Si el archivo especificado está abierto cuando se llama la función FileLen, el valor devuelto representa el
último tamaño de ese archivo cuando se guardó la ultima vez en el disco.
Para obtener la longitud de un archivo abierto, utilice la función LOF.
GETATTR
Devuelve un número, que representa los atributos de un archivo, directorio o carpeta o una etiqueta de
volumen.
Sintaxis
Variable = GetAttr(nombreRuta)
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo se puede incluir el directorio o carpeta y la unidad de disco.
Valores devueltos
El valor devuelto por GetAttr es la suma de los siguientes valores de atributos:
Valor
Constante
Descripción
0
1
2
4
16
32
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Sólo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado después de efectuar la última copia de
seguridad.
SETATTR
Establece los atributos de un archivo.
Sintaxis
nombreRuta
atributos
SetAttr nombreRuta;atributos
Expresión de cadena que especifica un nombre de archivo se puede incluir el
directorio o carpeta y la unidad de disco.
Constante o expresión numérica cuya suma especifica los atributos de
archivo.
Las constantes y valores de atributos son los mismos que para la instrucción GetAttr
Si se trata de establecer los atributos de un archivo abierto, se producirá un error en tiempo de
ejecución.
FREEFILE
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 213
Devuelve el siguiente número de archivo disponible para ser usado con la instrucción Open.
Sintaxis
FreeFile[(númerodeintervalo)]
El argumento númerodeintervalo especifica el intervalo desde el que el siguiente número de archivo libre
se va a devolver. Se especifica 0 (predeterminado) para devolver un número de archivo en el intervalo 1
a 255, inclusive. Se especifica 1 para devolver un número de archivo en el intervalo 256 a 511.
Observaciones Se usa FreeFile cuando se necesita proveer un número de archivo y se quiere asegurar
que el número de archivo no está ya en uso.
Visual Basic - Guía del Estudiante Cap. 8
LA FUNCION SHELL
LA FUNCION COMMAND PARA PASAR PARAMETROS
LA FUNCION DoEvents
Cajas de mensaje (Mensaje Box)
Cajas de entrada de datos (Input Box)
El Objeto APP (La Aplicación)
LA FUNCION SHELL
La función Shell se utiliza para ejecutar un programa ajeno a la aplicación que se está ejecutando.
Imaginemos que tenemos una aplicación Visual Basic que necesita, por ejemplo, establecer una
comunicación telefónica, y que esa comunicación telefónica nos la realiza un programa desarrollado en
C++ , llamado MARCADOR.EXE que funciona perfectamente y no queremos desaprovechar.
Imaginemos que ese programa tiene la posibilidad de introducirle el número telefónico que debe marcar
como un parámetro. Este parámetro se le introduce, supongamos, añadiendo el número al nombre del
programa ejecutable. Por ejemplo:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 214
MARCADOR.EXE 1234567
En nuestra aplicación Visual Basic introduciremos una línea invocando la función Shell seguida del
nombre (y Path) del ejecutable y del parámetro que le vamos a introducir al ejecutable:
Shell "C:\VB\MARCADOR.EXE 080"
Mediante esta línea, lo que hacemos es ejecutar el programa MARCADOR.EXE e introducirle como
parámetro el número a marcar. Resultado: el programa MARCADOR.EXE llama al número 080
(Bomberos), y una vez establecida la llamada podemos pasarle a ese Organismo datos o lo que nuestra
aplicación haga.
Veamos que dice la Ayuda de VB respecto a la Función Shell:
Ejecuta un programa ejecutable.
Sintaxis
Variable = Shell ( rutaDeAcceso [, estiloDeVentana] )
donde:
Variable es identificador de la tarea (ID)
rutaDeAcceso es el nombre del programa por Ejecutar (con su Path) y cualquier argumentos o
conmutadores (switches) de línea de comando requeridos; puede incluir directorio o carpeta y unidad de
disco. También puede ser el nombre de un documento que se ha asociado con un programa ejecutable.
estiloDeVentana es el número correspondiente al estilo de la ventana en la cual se va a ejecutar el
programa. En Microsoft Windows, si se omite estiloDeVentana, el programa se inicia minimizado con
enfoque.
El argumento con nombre estiloDeVentana tiene estos valores:
Constante
Valor
Descripción
vbHide
vbNormalFocus
0
1
vbMinimizedFocus
vbMaximizedFocus
vbNormalNoFocus
2
3
4
vbMinimizedNoFocus
6
Se oculta la ventana y se pasa el foco a la ventana oculta.
La ventana recupera el foco y vuelve a su posición y tamaño
original.
La ventana se muestra como un icono con foco.
La ventana se maximiza con foco.
La ventana vuelve al tamaño y posición más recientes. La
ventana activa actual permanece activa.
La ventana se muestra como un icono. La ventana activa
actual permanece activa.
Comentarios
Si la función Shell ejecuta con éxito el archivo nombrado, devuelve la identificación de la tarea (ID) del
programa iniciado. La ID de la tarea es un número exclusivo que identifica el programa en ejecución.
Este número debe ser un Long. Si la función Shell no puede iniciar el programa nombrado, ocurrirá un
error. Si desea conocer el ID de la tarea, realice una aplicación con un botón (cmbCalculadora) y un
label (label1). Ponga en ese botón en su procedimiento click, el siguiente código. - Observe que esta
aplicación inicia la calculadora de Windows Private Sub cmbCalculadora_Click()
Dim variable As Long
variable = Shell("C:\windows\calc.exe", 1)
label1.Caption = Str(variable)
End Sub
Posiblemente lo único que le importe sea el ejecutar esa aplicación, sin dar mayor importancia al ID de la
tarea. Utilice una línea con la siguiente expresión :
Shell ("C:\windows\calc.exe"), 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 215
(Observe en las dos formas de ejecutar la función Shell, que la colocación de los paréntesis y la coma
separadora es distinto.
El programa a ejecutar puede ser un programa Windows caso anterior de la calculadora) o un programa
DOS.
Nota La función Shell ejecuta otros programas de manera asíncrona. Esto quiere decir que no se
puede esperar que un programa iniciado con Shell termine su ejecución antes de que se ejecuten las
instrucciones que siguen a la función Shell en la aplicación. Esto es un gran inconveniente de la función
Shell. Excepto en contadas ocasiones, siempre es necesario conocer cuando se ha terminado de
ejecutar el programa iniciado mediante Shell. Y no es ese el único problema. La mayoría de los
programas DOS que se ejecutan con Shell no se cierran automáticamente. Esto significa que si
podemos evitar el uso de Shell debe evitarse. Pero si es completamente necesario, tampoco pasa nada.
Pero hay que controlar, tanto la terminación del proceso DOS como su cierre.
Podemos usar para ello APIs. No las hemos explicado todavía. Por eso, y adelantar un poco como se
trabaja con ellas, vamos a presentar, sin grandes explicaciones, lo que hay que hacer para poder
detectar que se ha terminado de ejecutar el programa DOS y para cerrarlo. Verá mas APIs mas
adelante.
El programa DOS elegido para este ejemplo es el popular ARJ.EXE, un compresor de datos que, sin
ánimo de publicidad, es uno de los mejores que existen. Pero trabaja solamente en DOS. Se utiliza un
Procedimiento que he llamado ExecCmdNoFocus , para detectar que el proceso abierto para comprimir
o descomprimir ha finalizado, y proceder a cerrarlo.
La declaración de las Apis y Constantes (En la sección de Declaraciones de un Módulo) es la siguiente:
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As _ String, ByVal
lpWindowName As String) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, _ ByVal wMsg
As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal _ bInheritHandle
As Long, ByVal dwProcessID As Long) As Long
Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode _ As Long)
As Long
Declaramos las constantes
Public Const WM_CLOSE = &H10
Public Const STILL_ACTIVE = &H103
Public Const PROCESS_QUERY_INFORMATION = &H400
El Procedimiento podemos ponerlo en el Módulo anterior o en el formulario. Variará el tipo de declaración
de las APIs:
Public Sub ExecCmdNoFocus(ByVal CmdLine As String)
(CmdLine es el parámetro que le vamos a pasar cuando invoque este procedimiento).
'Este procedimiento inicia un proceso en DOS y espera a que termine
'Una vez terminado este proceso, cierra la ventana, que se mostrará minimizada y sin foco
Declaramos las variables locales en ese procedimiento
Dim hProcess As Long
LSB
'handle del proceso donde se invoca la función Shell
Visual Basic – Guía del Estudiante
Capítulo 1
Página 216
Dim RetVal As Long
'Valor donde la función GetExitCode coloca el resultado
Dim winHwnd As Long ' manipulador de la ventana que contenga el Caption
‘Finalizado - ARJ
Dim RetValls As Long 'valor de retorno de PostMessage
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, Shell(CmdLine, _
vbMinimizedNoFocus))
Do
GetExitCodeProcess hProcess, RetVal
Sleep 100
'en este apartado comprueba si está abierta la ventana "Finalizado - ARJ"
winHwnd = FindWindow(vbNullString, "Finalizado - ARJ")
If winHwnd <> 0 Then
RetValls = PostMessage(winHwnd, WM_CLOSE, 0&, 0&)
End If
Loop While RetVal = STILL_ACTIVE
End Sub
La ventana DOS del ARJ tiene el Caption Finalizado - ARJ cuando ya ha terminado el proceso. En el
procedimiento ExecCmdNoFocus se analiza si esa ventana está presente (prueba de que ARJ ya ha
terminado, pues antes de terminar tiene otro Caption).
Para llamar a ese procedimiento hay que citarle por su nombre (ExecCmdNoFocus) que como lo
hemos declarado Public en un Módulo, podemos llamarle desde cualquier parte de la aplicación.
Debemos pasarle el parámetro CmdLine, que será el programa que vamos a ejecutar con Shell y los
parámetros adicionales que este programa necesite (En este caso, el programa es ARJ.EXE y a
continuación debe indicársele el nombre del archivo ya comprimido, a continuación a para que añada
mas ficheros a ese archivo, y a continuación el nombre de ese fichero o ficheros a añadir :
El parámetro CmdLine del procedimiento es todo lo que va entre paréntesis.
ExecCmdNoFocus ("C:\DirA\ARJ.EXE a C:\DirB\Fichero1.Ext")
NO se preocupe si no lo entiende ahora. Es difícil.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 217
LA FUNCION COMMAND
En el ejemplo anterior usábamos un ejecutable realizado en C++ para marcar un número telefónico que
le introducíamos como parámetro. ¿Podemos hacer eso en una aplicación VB? La respuesta debe ser
SI. Usaremos para ello la función Command. Esta función nos devuelve el parámetro introducido tras el
nombre del ejecutable realizado en VB, cuando iniciamos la aplicación VB mediante la línea de
comandos de Windows (línea Archivo | Ejecutar del Menú de Windows 3.xx o línea Ejecutar de W95),
o desde otra aplicación utilizando la función Shell.
Veamos también en este caso lo que dice la Ayuda de VB:
Command (Función)
Devuelve parte del argumento de la línea de comandos utilizada para lanzar Microsoft Visual Basic o un
programa ejecutable desarrollado con Visual Basic.
Cuando se inicia Visual Basic desde la línea de comandos, la parte de la línea de comandos que sigue a
/CMD se pasa al programa como un argumento de la línea de comandos. En el siguiente ejemplo,
cmdlineargs representa la información de argumento devuelta por la función Command.
VB /CMD cmdlineargs
En las aplicaciones desarrolladas con Visual Basic y compiladas en un archivo .EXE, Command
devuelve los argumentos que aparezcan en la línea de comandos tras el nombre de la aplicación. Por
ejemplo:
MyApp cmdlineargs
En la ventana Código, puede usted cambiar el texto devuelto por Command eligiendo Opciones del
proyecto en el menú Herramientas.
Veamos con un par de ejemplos como se pueden usar estas dos funciones:
Marcador Telefónico
Esta aplicación debe marcar un número telefónico. El número a marcar se le pasará como parámetro
tras el nombre de la aplicación. La aplicación ya compilada se llamará MARCADOR.EXE. Para marcar
un número debemos poner, en la línea de Comando de Windows:
Marcador.exe 1234567
o como ya sabemos, introducirle el parámetro mediante una llamada con la función Shell desde otra
aplicación:
Shell Marcador.exe 1234567
Como no vamos a realizar llamada alguna, sino comprobar que esto puede funcionar, nuestra pequeña
aplicación tendrá solamente un Label llamado FRMARCADORL1 donde presentaremos el número a
marcar. Todo el código necesario se lo metemos en el procedimiento Activate del formulario:
Private Sub Form_Activate()
FRMARCADORL1.Caption = Command
End Sub
También podemos pasar parámetros a un ejecutable, mediante el Drag & Drop de Windows.
Hemos visto mas atrás como podemos hacer Drag & Drop en una aplicación VB. Pero como
comentábamos, el D&D no es una función de VB, sino de Windows. Y Windows lo utiliza en su
Explorador de Windows para pasar como parámetro a una aplicación el nombre del fichero que
arrastremos hacia el icono que representa a esa aplicación. Como estoy seguro que se ha liado, vamos
con un ejemplo.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 218
Si Vd. hace un editor de textos (Editor.EXE) que soporta un formato determinado (por ejemplo el
RichTextFormat RTF), para ejecutar su programa y meterle como parámetro el nombre del fichero
Carta.RTF de forma que al arrancar lea directamente el fichero Carta.RTF, basta con ir al Explorador de
Windows, abrir la carpeta que contenga Carta.RTF, arrastrar el nombre de ese fichero y llevarlo al icono
que representa a Editor.EXE, que imaginemos que le ha preparado un acceso directo. Suelte el botón
del ratón y su editor se ejecutará, y además, le meterá como parámetro el nombre del fichero Carta.RTF
(con su Path correspondiente) Si Ud. había previsto la captura del Command tal como se explicó mas
atrás, y ha preparado su aplicación para que tome el contenido de Command y entienda que tiene que
abrir y cargar ese fichero, su aplicación Editor.EXE cargará automáticamente ese fichero. Observe que
esta es la forma de trabajar de los procesadores de texto usados normalmente (Word, WordPerfect,
Write, etc.)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 219
La Función DoEvents
Cede el control de la ejecución al sistema operativo, para que éste pueda procesar otros eventos.
También nos permite conocer el número de formularios abiertos en una aplicación.
Sintaxis
DoEvents
Cede el control al sistema operativo
Sintaxis
variable=DoEvents
variable contendrá un número indicando el número de formularios abiertos en
este momento.
La función DoEvents es una instrucción obligada en todos los bucles por condición para evitar que, en
caso de meterse en un bucle infinito, podamos salir de el aunque sea teniendo que pulsar las teclas CtrlAlt-Sup. Si no lleva esa línea DoEvents, es posible que tenga que resetaear el ordenador. El siguiente
bucle se pone para esperar a que el programa envíe un mensaje a través del control de comunicaciones.
Este, una vez terminada la comunicación, pone la variable Transmitido a True. Imagínese que se corta
la comunicación y Transmitido nunca llega a ser True.
Do Until Transmitido = True
Rem Si Transmitido no llega nunca a ser true, nunca podrá salir del bucle
DoEvents
‘Esta función devuelve el control al sistema operativo cada vez que se ejecuta
‘y puede comprobar si se han pulsado las teclas Ctrl -Alt-Sup
Loop
La función DoEvents devuelve también el número de formularios abiertos por una versión única de
Visual Basic, como la versión estándar de Visual Basic. DoEvents devuelve 0 en el resto de las
aplicaciones.
El control no se devuelve hasta que el sistema operativo haya terminado de procesar los eventos en cola
y que (sólo para Microsoft Windows) se hayan enviado todas las teclas en la cola SendKeys.
Si partes de su código consumen demasiado tiempo de procesamiento, use periódicamente DoEvents
para ceder el control al sistema operativo, de manera que eventos como la entrada por el teclado o los
clics del mouse (ratón) se puedan procesar sin grandes retrasos. Utilice esta función sobre todo, cuando
tenga bucles demasiado largos que puedan interrumpir la entrada de datos por teclado o ratón.
Precaución Asegúrese de que el procedimiento que ha cedido el control con DoEvents no se ejecute
de nuevo desde una parte diferente del código antes de que regrese la primera llamada a DoEvents.
Esto podría causar resultados impredecibles. Además, no use DoEvents si existe la posibilidad de que
otras aplicaciones interactúen con el procedimiento, de formas imprevistas, durante el tiempo en éste ha
cedido el control.
EJEMPLO
Para explicar la función DoEvents se ha preparado un pequeño ejercicio con un formulario principal
(Form1) y dos formularios auxiliares, estos últimos solamente a efectos de contar, mediante DoEvents
el número de formularios abiertos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 220
Se declara la variable PARAR como booleana en las declaraciones del Form1
El botón COMENZAR introduce un bucle que no pararía nunca. También pone Label1 de color Verde.
Private Sub Command1_Click()
Label1.BackColor = RGB(0, 255, 0)
Do While PARAR = False
N=N+1
If N = 1000 Then
'Cada vez que N=1000 ejecuta la función DoEvents.
DoEvents
N=0
End If
Loop
End Sub
En el formulario Form1, al que previamente le hemos puesto la propiedad KeyPreview a True, se le ha
puesto este código en su procedimiento KeyPress:
Private Sub Form_KeyPress(KeyAscii As Integer)
PARAR = True
Label1.BackColor = RGB(255, 255, 0)
End Sub
Si no hubiésemos puesto DoEvents en una parte del bucle del contador, nunca se podría acceder al
Procedimiento KeyPress del formulario, pues el programa lo único que haría será dar vueltas en el bucle
indefinidamente.
El botón ROJO tiene este código:
Private Sub Command2_Click()
PARAR = True
Label1.Caption = DoEvents
Label1.BackColor = RGB(255, 0, 0)
End Sub
'Aquí comprobamos los Formularios que tenemos
'abiertos en este momento.
Lo mismo ocurriría con el botón ROJO. Al estar el programa haciendo el bucle continuamente, nunca
podríamos entrar el Procedimiento Click de este botón.
Los botones FORM2, cierra Form2, FORM3, cierra Form3, lo único que hacen es mostrar u ocultar
Form2 y Form3 a efectos de poder comprobar cuantos formularios tenemos abiertos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 221
Private Sub Command4_Click()
Form2.Show
End Sub
Private Sub Command6_Click()
Form2.Hide
End Sub
Private Sub Command5_Click()
Form3.Show
End Sub
Private Sub Command7_Click()
Form3.Hide
End Sub
Por último SALI nos saca del programa. Observe que si no hubiésemos puesto DoEvents en el medio
del bucle, tampoco podríamos salir del programa, puesto que el sistema operativo no podría comprobar
que hemos hecho Click en este botón.
Private Sub Command3_Click()
End
End Sub
Realice esta pequeña práctica con la línea DoEvents del botón COMENZAR activada y desactivada
(Con una comilla simple). Prepárese para, en este último caso, detener la aplicación pulsando CtrPausa, pues de otra forma no la podrá detener.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 222
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 223
Presentación Modal de formularios. Ventana modal
(Este tema ha sido tomado parcialmente de las páginas de Mundo Visual - Visual Basic.)
Se dice que un Formulario o cualquier tipo de ventana se presenta de forma Modal cuando un elemento
de ese formulario o ventana toma el foco en el momento de mostrarse, y exige que se realice alguna
gestión sobre ella antes de permitir que otra parte de la aplicación tome de nuevo el foco. La actuación
que generalmente exige un formulario o ventana es ocultarse.
Para ver esto, cree una aplicación con dos formularios. El primero (Form1) puede ser el formulario donde
se realizan todas las operaciones de la aplicación. El segundo (Form2) puede ser el típico formulario
donde se presenta la información del fabricante de la aplicación, al que se accede normalmente desde el
menú, con la palabra Acerca de...
Cree un menú en el primer formulario con esa palabra y ponga este formulario como formulario inicial de
la aplicación. En el procedimiento click de este menú ponga el siguiente código :
Form2.Show 1
El 1 detrás de la expresión Show indica que el formulario Form2 debe mostrarse de forma Modal, lo que
significa que no se podrá volver a operar con ningún elemento de Form1 hasta que se oculte o
descargue el formulario Form2. Ponga en este Form2 el típico botón de Aceptar, cuyo código puede ser
simplemente :
Me.Hide
Ejecute la aplicación y comprobará como se comporta un formulario mostrado como Modal.
Lo dicho para un formulario puede aplicarse para otro tipo de ventanas. El MessageBox y la ventana del
CommonDialog son dos ejemplos de ventanas modales. Veamos la primera :
La caja de Mensajes. MessageBox o MsgBox
Las cajas de mensajes o MessageBox, tienen una función clara, que es la de mostrar una determinada
información, aviso, o pregunta para que el usuario tenga conocimiento de ella y actúe.
Hay 2 formas diferentes de mostrar información:
1 - El aviso es sí, que tiene por objetivo mostrar una información de interés.
2 - El aviso con espera de respuesta, que muestra una información esperando que el usuario seleccione
una de las respuestas posibles para que el programa la trate.
Una caja de mensaje, puede ser por ejemplo, la instrucción M s g B o x " H o l a ". Por defecto, la caja de
mensaje será similar a esta:
Debe darse cuenta de algunas cosas:
En primer lugar el mensaje, "Hola" que se escribe a continuación de la palabra MsgBox, también debe
darse cuenta del botón Aceptar que tiene el Focus de la ventana activa y que sólo hay ese botón, y por
último el título de la ventana.
Podemos modificar estos parámetros para alcanzar nuestros objetivos, por eso, vamos a escribir ahora
este código: MsgBox "Hola", ,"Ejemplo" .
El resultado es:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 224
Como podemos apreciar en el código, la caja de mensaje posee un título Ejemplo y el mensaje, pero es
posible que deseemos escribir un mensaje en varias líneas con salto de párrafo. Nada tan fácil como
este código por ejemplo: MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", , "Ejemplo" .
El resultado es:
Habrá observado en la expresión anterior que se ha utilizado vbCrLf (Visual Basic Carriage Return Line
Feed, VB retorno de carro y avance de línea) Vea mas adelante la aclaración de esta expresión. Con
ella logramos introducir un salto de línea.
Supongo que se habrá percatado de que entre el mensaje y el título de la ventana, hemos escrito dos
comas, esto es porque entre las comas, debe ir un número que representará el icono a mostrar. Existen
cuatro iconos diferentes además de la posibilidad de no mostrar ninguno. Los iconos son:
Estos iconos corresponden a los siguientes mensajes:
Mensaje crítico.
Mensaje de pregunta.
Mensaje exclamativo.
Mensaje de información.
(Sólo en W32. En Windows 3.xx dispone de otros diferentes, aunque con el mismo significado)
Para mostrar el icono en cuestión o para que Visual Basic lo entienda, es necesario escribir lo siguiente:
Mensaje crítico.
Mensaje de pregunta.
Mensaje exclamativo.
Mensaje de información.
VbCritical
VbQuestion
VbExcalamqtion
VbInformation
ó
ó
ó
ó
16
32
48
64
Note que es lo mismo insertar VbCritical o 16.
Vamos a ver un ejemplo añadiendo un icono al último ejemplo:
MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion , "Ejemplo"
El resultado es:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 225
Ahora bien, es posible que queramos mostrar algún otro botón que o bien no sea el de Aceptar o que
además del botón de Aceptar haya más botones. Para este propósito, tenemos los siguientes
parámetros:
Aceptar
Aceptar y Cancelar
Anular, Reintentar, Ignorar
Sí, No y Cancelar
Sí y No
Reintentar y Cancelar
Aplicación modal
vbOKOnly
vbOKCancel
vbAbortRetryIgnore
vbYesNoCanceló
vbYesNo
vbRetryCancel
vbApplicationModal
ó
ó
ó
3
ó
ó
ó
0
1
2
4
5
0 (Es la caja de mensaje sin
icono)
La forma de hacer esto es sumar al parámetro del icono que queremos mostrar el valor de los botones
que deseamos que aparezcan.
Así por ejemplo:
MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo , "Ejemplo"
El resultado es:
Aún así, es posible que deseemos que el Focus lo adquiera otro un botón determinado. Por ejemplo, en
este caso el Focus lo tiene el botón Sí, pero es posible que deseemos que lo tenga el botón No por
ejemplo. Esto se consigue con los siguientes parámetros:
Primer botón predeterminado vbDefaultButton1
ó
0
Segundo botón predeterminado vbDefaultButton2
ó
256
Tercer botón predeterminado vbDefaultButton3
ó
512
Por ejemplo: MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo +
vbDefaultButton2, "Ejemplo"
El resultado es:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 226
Si no se señala el botón predeterminado, Visual Basic seleccionará el primer botón. En caso de
seleccionar como predeterminado un botón que no existe, (por ejemplo el tercero), Visual Basic
seleccionará el primero.
Ahora bien, si decidimos mostrar un mensaje esperando una respuesta, o queremos saber que botón ha
pulsado el usuario, esto lo podemos conseguir mediante el siguiente código de respuestas:
Aceptar
vbOK
ó
1
Cancelar
vbCancel
ó
2
Anular
vbAbort
ó
3
4
Reintentar
vbRetry
ó
Ignorar
vbIgnore
ó
5
Sí
vbYes
ó
6
No
vbNo
ó
7
Así por ejemplo, el siguiente código:
Dim Resp As Integer
Resp = MsgBox("Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo + vbDefaultButton2,
"Ejemplo")
If Resp = 6 Then
MsgBox "Ha pulsado SI"
Else
MsgBox "Ha pulsado NO"
End If
Tiene el resultado siguiente:
Si pulsamos el botón Sí obtendremos una acción, y si pulsamos el otro botón otra acción.
Ahora bien, para elegir o seleccionar un evento o acción, el usuario debe saber combinar los códigos,
sabiendo que un MsgBox posee la siguiente sintaxis principal:
MsgBox Mensaje, Botones, Título de la ventana
InputBox
El InputBox o caja de entrada es otra de las partes más utilizadas para la interacción del usuario con la
aplicación. Es importante que el usuario interactúe con la aplicación para ser el protagonista de esta.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 227
El InputBox nos permite sacar una caja donde el usuario pasará un parámetro, valor o dato para que el
programa lo trate y lo ejecute.
El mensaje que quiere que aparezca se realiza de forma casi idéntica al MessageBox. Puede escribirse
varias líneas de texto seguidas por la constante de Visual Basic vbCrLf o salto de línea o párrafo.
La sentencia es:
Val = InputBox (Mensaje, Titulo, ValorPredeterminado)
Val almacenará el texto escrito por el usuario, que puede ser una cantidad, cadena string, … etc.
Por ejemplo:
Dim Val As String
Val = InputBox("Deme su nombre", "Ejemplo")
MsgBox "Su nombre es: " & Val
Tiene como resultado:
(El usuario teclea el nombre - Mundo Visual - y hace click en Aceptar. A continuación se muestra el
MsgBox - 2ª línea del código anterior )
Ahora bien, podemos determinar un texto predeterminado a la caja de entrada, como por ejemplo:
Dim Val As String
Val = InputBox("Deme su nombre", "Ejemplo", "Mundo Visual")
MsgBox "Su nombre es: " & Val
Obtendremos como resultado:
Es importante determinar que si el usuario elige el botón Cancelar, el programa devolverá una cadena de
caracteres igual a 0, es decir, Val ="".
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 228
La caja de entrada puede ser sin embargo más personalizada mediante dos parámetros como son la
posición de la ventana de entrada de datos en la pantalla. Estos parámetros se ponen a continuación del
ValorPredeterminado.
Por ejemplo:
Dim Val As String
Val = InputBox("Deme su nombre", "Ejemplo", "Mundo Visual", 1200, 1400)
Situará la ventana en el eje de las X a 1200 Twips (posición horizontal) y la Y a 1400 twips (posición
vertical).
Reitero mi agradecimiento a Mundo Visual
http://www.ciudadfutura.com/visualbasic/
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 229
El Objeto App
El objeto App representa a la aplicación. Es el objeto Visual Basic que contiene diversas informaciones
acerca de la Aplicación.
Alguna de estas informaciones se le pueden introducir al proyecto en tiempo de diseño, en el cuadro de
Opciones. Para ello basta con ir, en la Barra de Menú de Visual Basic a Herramientas | Proyecto |
Opciones y hacer click en Proyecto. Otra parte donde se introducen es en el cuadro de diálogo
Opciones de EXE. Para ver este cuadro proceda de la misma forma que si fuese a crear un archivo .EXE
de la Aplicación, Haga click en Archivo | Crear Archivo EXE de la Barra de Menú, y una vez que le
aparezca el cuadro de diálogo para introducir el nombre, haga click en OPCIONES.
Estas informaciones son las Propiedades del objeto App. Este objeto no tiene Métodos ni Eventos.
Comments (Propiedad)
Devuelve o establece una cadena que contiene comentarios sobre la aplicación en ejecución. Es de sólo
lectura en tiempo de ejecución.
Sintaxis
MiVariable = App.Comments
Se establece esta propiedad en tiempo de diseño usando el cuadro Opciones de EXE.
CompanyName (Propiedad)
Devuelve o establece un valor de tipo String que contiene el nombre de la empresa o del creador de la
aplicación en ejecución. Es de sólo lectura en tiempo de ejecución.
Sintaxis
Mivariable = App.CompanyName
Se establece esta propiedad en tiempo de diseño usando el cuadro de Opciones de EXE. Visual Basic
toma por defecto el nombre de la compañía con que se cargó VB.
EXEName
(Propiedad)
Devuelve el nombre raíz (sin la extensión) del archivo ejecutable que se está ejecutando actualmente. Si
se utiliza en el entorno de desarrollo, devuelve el nombre del proyecto.
Sintaxis
MiVariable = App.EXEName
Esta propiedad se establece bien en el cuadro de Opciones, bien al guardar el archivo .EXE
FileDescription (Propiedad)
Devuelve o establece un valor de tipo String que contiene información de los archivo de la aplicación en
ejecución. Es de sólo lectura en tiempo de ejecución.
Sintaxis
Mivariable = App.FileDescription
Se establece esta propiedad en tiempo de diseño usando el cuadro Opciones de EXE.
HelpFile (Propiedad)
Ya comentada mas atrás. Especifica el nombre (con su Path) del fichero de ayuda. Se introduce en
tiempo de diseño en el cuadro de Opciones. Puede cambiarse en tiempo de ejecución.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 230
hInstance (Propiedad)
Devuelve el controlador de la instancia de la aplicación. Es un Long
Sintaxis
VariableLong = App.hInstance
Cuando se trabaja en un proyecto dentro del entorno de desarrollo de Visual Basic, la propiedad
hInstance devuelve el controlador de la instancia de Visual Basic.
El valor de esta propiedad lo pone directamente Windows.
LegalCopyright (Propiedad)
Devuelve o establece un valor de tipo String que contiene información de derechos de autor sobre la
aplicación en ejecución. Es de sólo lectura en tiempo de ejecución.
Sintaxis
Mivariable = App.LegalCopyright
Esta propiedad se establece en el cuadro de diálogo Opciones de EXE.
LegalTrademarks (Propiedad)
Devuelve o establece un valor de tipo String que contiene información de marca registrada sobre la
aplicación en ejecución. Es de sólo lectura en tiempo de ejecución.
Sintaxis
MiVariable = App.LegalTrademarks
Establezca esta propiedad en tiempo de diseño usando el cuadro de diálogo Opciones de EXE.
Major Minor (Propiedades)
Devuelven o establecen el número mayor (menor) de la versión del proyecto. Es de sólo lectura en
tiempo de ejecución.
Sintaxis
MiVariable = App.Major MiVariable = App.Minor
El valor de estas propiedades están dentro del rango 0 a 9999.
Proporcionan información sobre la versión de la aplicación en ejecución. Se establecen en tiempo de
diseño usando el cuadro de diálogo Opciones de EXE.
Revision (Propiedad)
Devuelve o establece el número de revisión de la versión del proyecto. Es de sólo lectura en tiempo de
ejecución.
Sintaxis
MiVariable = App.Revision
Mediante las propiedades Major, Minor y Revision obtenemos la versión del programa. Es muy util
conocer la version del programa para saber si lo hay que actualizar. Por ejemplo, la instrucción:
MiVariable = App.Major & “.” & App.Minor & “.” & App.Revision
Puede devolver un dato parecido a este:
MiVariable = 2.1.4
Así conocemos que la versión del programa es la 2.1.4. Estos datos de Major, Minor y Versión hay que
introducirlos en el programa durante el tiempo de diseño. Se usa para ello la caja de Propiedades del
Proyecto
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 231
Path (Propiedad)
Especifica la ruta de acceso del archivo .VBP de proyecto cuando se ejecuta la aplicación desde el
entorno de desarrollo o la ruta de acceso del archivo .EXE cuando se ejecuta la aplicación como un
archivo ejecutable.
Esta propiedad es sumamente útil. Cuando se realiza una aplicación, no es prudente obligar al usuario a
meterla dentro de un determinado directorio impuesto por el programador. Si no es así, no sabremos en
qué directorio está el ejecutable, y es muy conveniente saberlo, sobre todo cuando se utilizan ficheros
auxiliares de inicialización, que deberían estar en el mismo directorio de la aplicación. Si queremos abrir
el fichero MiAplicacion.Cfg que estará obligatoriamente en el mismo directorio de la aplicación (aunque
no conocemos su nombre), solamente tenemos que poner la línea de código :
Open App.Path &
“\MiAplicacion.ICfg” For Input as # 1, sin importarnos cual es el nombre real de ese directorio.
PrevInstance (Propiedad)
Devuelve un valor booleano que indica si hay ya en ejecución una instancia anterior de una aplicación.
Es muy utilo saber que hay una instancia del programa en ejecución para impedir que se vuelva a abrir
otra.
Sintaxis
VariableBooleana = App.PrevInstance
Puede utilizar esta propiedad en un procedimiento de evento Load para determinar si el usuario ya está
ejecutando una instancia de una aplicación. Dependiendo de la aplicación, puede ser conveniente que
sólo haya una instancia de la misma en ejecución al mismo tiempo en el entorno operativo Microsoft
Windows.
ProductName (Propiedad)
Devuelve o establece un valor de tipo String que contiene el nombre de producto de la aplicación en
ejecución. Es de sólo lectura en tiempo de ejecución.
Sintaxis
MiVariable = App.ProductName
Establezca esta propiedad en tiempo de diseño usando el cuadro de diálogo Opciones de EXE.
El valor de la propiedad Revision está dentro del rango 0 a 9999.Esta propiedad proporciona información
sobre la versión de la aplicación en ejecución. Esta propiedad se establece en tiempo de diseño usando
el cuadro de diálogo Opciones de EXE.
StartMode (Propiedad)
Devuelve o establece un valor que determina si una aplicación se inicia como proyecto independiente o
como servidor de automatización OLE. De sólo lectura en tiempo de ejecución.
Sintaxis
VariableLong =App.StartMode
Donde Valor es un número o una constante que determina la forma de inicio :
Constante
Valor
Descripción
vbSModeStandalone
0
vbSModeAutomation
1
(Predeterminado) La aplicación se inicia como proyecto
independiente.
La aplicación se inicia como servidor de automatización OLE.
TaskVisible (Propiedad)
Devuelve o establece un valor que determina si la aplicación aparece en la lista de tareas de Windows.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 232
Sintaxis
VariableBooleana = App.TaskVisible
Donde booleano puede tomar los valores True o False :
True (Predeterminado) La aplicación aparece en la lista de tareas de Windows.
False La aplicación no aparece en la lista de tareas de Windows.
La propiedad TaskVisible sólo puede establecerse a False en aplicaciones que no presenten interfaz,
como servidores OLE que no contengan o presenten objetos Form. Mientras la aplicación disponga de
interfaz gráfica, la propiedad TaskVisible se establece automáticamente a True.
Title (Propiedad)
Devuelve o establece el título de la aplicación que aparecen en la Lista de tareas de Microsoft Windows.
Si se modifica en tiempo de ejecución, los cambios no se guardarán con la aplicación.
Sintaxis
App.Title = “Esto es lo que va a figurar en la barra de Titulo”
Valor será una expresión de cadena que especifica el título de la aplicación. La longitud máxima de valor
es 40 caracteres.
Esta propiedad está disponible en tiempo de diseño en el cuadro de diálogo del comando Crear EXE del
menú Archivo.
Todos estos datos figuran en el archivo de proyecto (.VBP). Puede verse editándolo con el Block de
Notas de Windows, e incluso pueden modificarse estas propiedades directamente sobre ese archivo.
Visual Basic - Guía del Estudiante Cap. 9
INTERFACE DE DOCUMENTOS MULTIPLES. (Multiple Document Interface MDI )
EL CONTROL RICH TEXT BOX
INTERFACE DE DOCUMENTOS MULTIPLES.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 233
Lo que se va a explicar en este capítulo le será bastante familiar aunque nunca haya reparado en ello.
Posiblemente haya utilizado un procesador de texto en el que está escribiendo una carta, y antes de
terminar de escribir esa carta, comienza a escribir otro documento, y posiblemente otro, y tenga los tres
documentos en la pantalla al mismo tiempo, bien en ventanas escalonadas, (cascada), bien en ventanas
en forma de mosaico, o simplemente tapando unas a otras completamente. Los tres documentos están
en su procesador de textos, y puede actuar sobre uno u otro simplemente eligiendo el deseado
mediante el mecanismo que le proporciona su procesador de textos. Este sistema no es ni mas ni
menos que una interface de documentos múltiples. En programación, a este tipo de aplicaciones las
denominamos MDI
Para crear una aplicación MDI debe hacerse mediante un Formulario Padre al que se le añaden tantos
Formularios Hijo como documentos tengamos. Al formulario padre le denominamos Formulario MDI,
y a los formularios hijo en Visual Basic se les denomina formularios MDIChild. En esta Guía del
Estudiante se usarán indistintamente una u otra denominación.
La única diferencia entre un formulario normal y un formulario Hijo es que éste tiene la propiedad
MDIChild a True.
Para realizar una aplicación MDI, lo primero que hay que hacer es introducir en ella un formulario MDI.
Para introducirlo, basta con hacer click en Insertar | Formulario MDI de la barra de menú. Solamente se
puede tener un formulario MDI en una aplicación. Puede observar que una vez que ha introducido uno, la
palabra Formulario MDI del submenú Insertar queda deshabilitada.
Una vez que tiene un formulario MDI puede introducir tantos formularios hijo como desee. Para que un
formulario sea formulario hijo basta con poner a True su propiedad MDIChild.
En una aplicación MDI pueden coexistir formularios hijo y formularios normales.
Propiedades de los formularios MDI
Aparte de las propiedades de un formulario normal, un formulario MDI tiene las siguiente propiedades :
AutoShowChildren. Muestra los formularios hijo nada mas cargarlos.
Esta propiedad puede verse si se carga un formulario hijo mediante la sentencia :
Load NombreFormularioHijo
Si la propiedad AutoShowChildren está a True, el formulario cargado se verá inmediatamente. Si está a
False, será necesario ejecutar la sentencia NombreFormularioHijo.Show para presentarlo.
ActiveForm Mediante esta propiedad podemos conocer el formulario activo dentro de una aplicación
de documentos múltiples. (El formulario activo es aquel que tiene el foco)
MiVariable = ActiveForm.caption
MiVariable contendrá el Caption (Barra de Titulo) del formulario activo.
ActiveForm.Backcolor = RGB (255,0,0)
pondrá el fondo del formulario activo de color rojo.
ScrollBars
Hace que el Formulario MDI (padre) muestre barras de Scroll para presentar en toda su
extensión a un formulario hijo, cuando las dimensiones de áste superan las de aquel.
Aparte de estas propiedades que diferencian un Formulario MDI de un Formulario normal, los
Formularios MDI presentan otras particularidades.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 234
Inserción de Controles
Solamente podrán introducirse en un formulario MDI aquellos controles
que tengan la propiedad Align. (Picture, Data, DBGrid) y solo permiten que se presenten con alineación
a uno de los lados del Formulario (Top, Bottom, Left o Right)
El control Picture puede trabajar como contenedor de otros controles. Por lo tanto, para poder introducir
cualquier control (TextBox, Label, CommandButton ...) será necesario introducir un control Picture, y
sobre el, poner los controles que se necesiten.
Línea de Menú. Cuando existe la línea de Menú en un Formulario MDI y en el Formulario Hijo que
introduzcamos en él, la línea de menú del Formulario MDI se sustituye por la línea de menú del
Formulario Hijo introducido.
Barra de Título. La Barra de Título del Formulario MDI se conserva siempre. Pero si el Formulario Hijo
insertado dentro de él está maximizado (ocupa toda la extensión del Formulario MDI), a la barra de título
se le añadirá la barra de Título del Formulario Hijo entre paréntesis.
Para hacer que un Formulario sea un formulario hijo basta con ponerle su propiedad MDIChild a True.
Puede preparar los formularios hijo uno a uno e introducirlos dentro del formulario MDI según las
necesidades de la aplicación. Este sería el caso de una aplicación con varias pantallas, todas ellas
colocadas sobre una pantalla fija (Formulario MDI) del que se aprovecha quizás alguna parte como parte
común de toda la aplicación (Menú, Título, Barra de herramientas montada sobre un Picture, etc.)
Puede también darse el caso de introducir un número indeterminado de ventanas iguales para realizar
varias veces la misma función, pero sobre ventanas diferentes. (Caso del procesador de texto que tiene
varias ventanas de texto, cada una con un documento. Lo que desconocemos a priori es el número de
documentos que vamos a editar)
Para el primer caso, será necesario crear cada una de las ventanas, e introducirlas y quitarlas según
pida la aplicación.
En segundo caso, bastará con crear un formulario hijo con todas las partes necesarias para su correcto
funcionamiento, y luego, realizar tantas “fotocopias” de ese formulario como ventanas necesitemos. Lo
que introducimos en la aplicación son precisamente esas “fotocopias”, pero no el original, que lo
seguimos manteniendo intacto para volver a copiarlo si fuese necesario.
A esas “fotocopias” de un formulario las llamamos Instancias. Al original le llamaremos Clase.
En realidad una Clase es la definición de un objeto Visual Basic. Un objeto Visual Basic puede ser un
Formulario, un control, un objeto de acceso a datos.
La Instancia es la réplica de una clase. Puede ser la réplica de un Formulario, de un control o de otro
objeto. La Instancia lleva las mismas Propiedades que la clase. Se dice que hereda las propiedades.
(Excepto la propiedad Visible, que siempre, por defecto, aparece a False). Cuando se varía una
propiedad de una Instancia, no se altera el valor de esa propiedad en la Clase ni en ninguna de las
restantes Instancias.
Después de toda esta teoría, ¿podemos saber como se crea una Clase de un formulario ? O dicho de
manera mas coloquial, ¿Cómo se crea un Formulario para poder hacer varias “fotocopias” de él ?
La respuesta es obligatoriamente mas sencilla que la teoría. Con el formulario vacío que tengamos en el
proyecto (Insertemos un Formulario si fuese necesario) pongámosle todos los controles que deseemos.
Le podemos poner un Menú y cambiar a nuestro antojo todas sus propiedades. Entre ellas, la propiedad
MDIChild. Si vamos a introducir las Instancias de ese Formulario en un Formulario MDI esa propiedad
debe estar a True, y por lo tanto sus Instancias saldrán igualmente con esa propiedad a True.
Pongámosle un nombre y ya está creada la clase. Supongamos que ese nombre es FormularioHijo
Para crear ahora Instancias de ese Formulario podemos hacerlo de dos formas :
Declarar una variable tipo Objeto. No se asuste. Para declarar que una variable es un Formulario basta
con declararla de la siguiente forma :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 235
Dim MiVentana As Form
Esta variable debe declararla en sitio adecuado para su aplicación, y el ámbito de esa variable objeto
será el mismo que para cualquier tipo de variable. (Vea Ambito de las Variables) La sentencia a utilizar
para la declaración será Dim, Private, Public o Global tal como se explicó para las variables.
Una vez declarada como variable puede hacerla igual a un objeto existente que servirá de modelo (Una
Clase) que estará definida por un nombre: (P.e. FormularioHijo)
Set MiVentana = New FormularioHjo
Podemos hacer las dos operaciones a un tiempo : declarar y crear la copia :
Dim MiVentana As New FormularioHijo
Una vez creado la instancia del formulario debemos cargarlo en el Formulario Padre. Para cargarlo
debemos emplear la sentencia Load MiVentana, con lo que quedará cargado en la memoria, pero,
dependiendo de como está la propiedad AutoShowChildren del Formulario Padre se mostrará o no se
mostrará. Para que se muestre, independientemente de como esté esa propiedad, basta con ejecutar
MiVentana.Show. En realidad mediante el método Show un formulario no solamente se muestra, sino
que también se carga en la memoria si no estuviese previamente cargado. Por lo tanto podíamos
habernos ahorrado la instrucción anterior para cargarlo Load MiVentana
Es muy práctico poner un Caption distinto a cada formulario que se introduzca, caso de introducirse
varios formularios hijo iguales. El Caption es una propiedad y por lo tanto todas las instancias heredan el
Caption de la Clase. Sería prudente distinguir un formulario de otro mediante su Caption, es decir
mediante su barra de título.
Para ello podemos crear un contador en el mismo procedimiento en el que creamos una nueva instancia,
y poner el Caption de cada nuevo Formulario siguiendo un orden numeral.
Documento 1, Documento 2, Documento 3, etc.
Ese procedimiento quedará de la siguiente forma :
Static contador As Integer
Dim MiVentana As New FormularioHijo
MiVentana.Caption = “Documento “ & Str (contador)
MiVentana.Show
Referencias a los Formularios. ActiveForm y Me
Si queremos nombrar un Formulario Hijo dentro de una aplicación MDI el primer problema con el que
nos encontramos es que todos los formularios hijo (Instancias de la misma Clase) tienen el mismo
nombre. Por lo tanto no podemos nombrarlas con ese nombre, ya que la aplicación no sabría a cual de
ellas nos referimos.
Si el código donde vamos a nombrar ese formulario está fuera de él (P.e. en el Formulario Padre)
deberemos referirnos al formulario hijo mediante ActiveForm. ActiveForm nos va a indicar cual es el
formulario que está actualmente activo. Un formulario está activo cuando estamos trabajando sobre él.
En ese momento tiene el foco. Permanece activo desde que hacemos click con el ratón sobre cualquiera
de sus partes, hasta que activamos otro formulario. Es sencillo reconocer cual es el formulario activo
pues tiene su barra de título con el color vivo.
Cada vez que hacemos una operación sobre una parte de un formulario éste se pondrá activo. Por
ejemplo, si el formulario es un documento de texto, y contiene el texto en un RichTextBox de nombre
RTB1, si queremos hacer una operación con el texto desde un botón colocado en el formulario padre
(poner en negrita el texto seleccionado), haríamos lo siguiente :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 236
ActiveForm.RTB1.SelBold = True
ya que siempre estaremos seguro de que el Formulario Activo es aquel en el que acabamos de
seleccionar el texto.
Si el botón donde hemos puesto el botón no es el formulario padre, sino el hijo, tenemos un problema
similar. Su nombre será (con los ejemplos anteriores) MiVentana, y pueden existir varios formularios con
ese nombre, tantos como documentos hayamos introducido. No podemos por tanto nombrarlo con su
nombre, pues hay (o puede haber) varios. Tampoco lo podemos nombrar con ActiveForm, ya que esta
propiedad corresponde al Formulario Padre. La solución es nombrarle mediante Me. Me siempre se
refiere al formulario que contiene al procedimiento donde está esa palabra. Por lo tanto, si tenemos un
botón en el formulario hijo con la instrucción :
Me.RTB1.SelBold = True
Me se refiere concretamente a ese formulario.
Colocación de los Formularios Hijo - Método ARRANGE
Mediante el método Arrange podemos distribuir los formularios hijo dentro del formulario padre. Pueden
colocarse en cascada, mosaico horizontal, mosaico vertical o como iconos.
Sintaxis NFMDI.Arrange distribución
donde
NFMDI = Nombre del Formulario MDI
distribución puede tomar los siguientes valores o constantes :
Constante
Valor
Descripción
vbCascade
0
vbTileHorizontal
1
vbTileVertical
2
VbArrangeIcons
3
Dispone todos los formularios MDI secundarios no minimizados
en cascada.
Dispone todos los formularios MDI secundarios no minimizados
en mosaico horizontal.
Dispone todos los formularios MDI secundarios no minimizados
en mosaico vertical.
Dispone los iconos de los formularios MDI minimizados.
Las ventanas o los iconos se pueden distribuir incluso si el objeto MDIForm está minimizado. Los
resultados son visibles cuando el objeto MDIForm se maximiza.
Posición de los Formularios en el Eje Z - Método ZOrder
Cuando tenemos varios formularios hijo, unos ocultan a los otros. Mucho mas si los formularios están
maximizados. Podemos colocar un formulario hijo en la parte frontal del montón de formularios (para que
se vea completamente) o llevarle a la posición mas atrás mediante el Método ZOrder.
Sintaxis
NFH.ZOrder posición
Donde NFH = Nombre del Formulario Hijo
posición puede se 0 ó 1. Si es 0 (o si se omite) el formulario se coloca en primer plano. Si es 1 el
formulario se coloca en el fondo del eje Z.
ZOrder es un método que no solamente se puede emplear con formulario hijo, sino con cualquier
instancia. Puede emplearlo también con cualquier control. Pero lea detenidamente la Ayuda de este
método, ya que no todos los controles la admiten.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 237
Mostrar los Formularios existentes mediante el Menú -- Propiedad WindowList
Al explicar el Editor de menús casi se pasó por alto una propiedad del menú : WindowList. Cuando se
activa esta propiedad (Puede activarse para una sola palabra del menú. Si se pretende activar para mas
de una dará un error), esa palabra que tiene activada la propiedad WindowList mostrará al hacer click
sobre ella, en un menú desplegable, el Caption (Barra de Título) de todos los formularios hijo cargados
en ese instante en la aplicación. Pueden estar incluso minimizados.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 238
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 239
EL CONTROL RICH TEXT BOX
El control RichTextBox es una caja de texto con mas prestaciones que el TextBox. No está
normalmente en la caja de herramientas, por lo que habrá que ir a Proyecto | Componentes y elegir
Microsoft RichTextBox Control. El icono que presenta en la caja de herramientas es el siguiente :
Frente a la rigidez del TextBox, este control nos permite escribir un texto utilizando distintos tipos de
fuentes en el mismo texto, e introducir mas de 65.536 caracteres, límite máximo del TextBox. Aparte de
estas, tiene otras características respecto a la forma de guardar y leer el texto en un fichero, que le
convierten en una herramienta muy útil para el diseño de aplicaciones en las que haya que introducir
documentos de texto.
El RichTextBox puede utilizar indistintamente formato de texto Ascii (que le llamaremos Texto Plano) o
formato RTF (RichTextFormat, que llamaremos Texto enriquecido) El formato de Texto enriquecido es
un formato de intercambio entre procesadores de texto. Vea al final del capítulo una explicación más
detallada de este formato de texto. De momento basta con decir que permite poner tipos distintos de
letras, de tamaños, de colores, introducir gráficos, y toda una serie de ventajas que le van a permitir
realizar procesadores de texto casi tan perfectos como los editores comerciales mas conocidos. Esto
nos permite por ejemplo, guardar estrictamente las letras que componen el texto (Propiedad Text de
RichTextBox) o guardar el texto, con sus letras y todos los adornos que queramos ponerles (Tipos
distintos de fuente, negrita, cursiva, …). Esto lo logramos con la propiedad TextRTF del RichTextBox.
Cuando hablamos de guardar, nos estamos refiriendo lógicamente a guardarlo en un fichero en el disco,
y también a guardarlo en el portapapeles. Si tenemos un RichTextBox de nombre RTB (así le
llamaremos en todos los ejemplos) con un texto tal como
Te creías muy listo Flanahan , pero tus vacas no pasarán por mis tierras
La propiedad Text contendrá los siguiente
RTB.Text = Te creías muy listo Flanahan, pero tus vacas no pasarán por mis tierras
La propiedad TextRTF contiene toda la información, pero eso sí, en formato RTF
RTB.TextRTF={\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswissMS
Sans
Serif;}{\f1\froman\fcharset2
Symbol;}{\f2\fswiss\fprq2Arial;}}{\colortbl\red0\green0\blue0;}\deflang1034\pard\li708\plain\f2\fs20
Te
cre\'edas muy listo \plain\f2\fs20\b\i Flanahan\plain\f2\fs20 , pero tus \plain\f2\fs24 vacas\plain\f2\fs20 no
pasar\'e1n por \plain\f2\fs20\ul mis tierras\plain\f2\fs20
\par \pard\plain\f0\fs17
\par }
(Puede que el texto anterior tenga alguna diferencia sobre el real, debido a que hubo que introducirle
algún retorno de carro para poder presentarlo)
Veamos las propiedades de este control
Propiedades del RichTextBox
El RichTextBox tiene todas las propiedades del TextBox, y además otras que son las que le dan las
características excepcionales a este control. Las tres siguientes propiedades son idénticas para ambos
controles :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 240
SelLenght
Devuelve o establece el número de caracteres seleccionados. Los caracteres
seleccionados son aquellos que se ponen en vídeo inverso cuando arrastramos con el
ratón.
SelStart
Devuelve o establece el número del carácter de comienzo del texto
seleccionado.
SelTextDevuelve o establece la cadena de caracteres seleccionados. Si no hay ningún
carácter seleccionado devuelve la cadena “” (cadena vacía)
En el ejemplo, el texto seleccionado es ejemplo nos permitirá, texto que hemos seleccionado con el
ratón. Las propiedades anteriores tomarán estos valores para ese texto seleccionado :
SelLenght = 21
(Recuerde que el espacio también es un carácter)
SelStart = 5
(La e de ejemplo es la sexta letra, pero empieza a contar por la 0)
SelText = ejemplo nos permitirá
Recuerde que estas propiedades son tanto de lectura como de escritura. Es decir, puede seleccionar un
texto con el ratón y analizar ese texto seleccionado, o seleccionar el texto dándole valores a estas
propiedades.
Las diferencias entre uno y otro control comienzan ahora. En un RichTextBox, con un texto
seleccionado, podemos cambiar el tipo de letra, su tamaño, su color, etc.
Tipos y tamaño de las fuentes.
El RichTextBox tiene la propiedad Font, propiedad que podemos cambiar e tiempo de diseño o en
tiempo de ejecución, y que se refiere a la globalidad del RTB. Debemos señalar que en el RTB, la
propiedad Font es en sí un objeto más. Objeto que tiene sus propiedades (Name, Size, Bold, Italic, etc.)
Esto ocurre con los controles modernos, dada la tendencia de VB de ser cada día más un lenguaje
orientado a objetos. No ocurre lo mismo con otros controles ya conocidos (CommonDialog, por ejemplo)
que deben mantenerse con la nomenclatura anterior por razones de compatibilidad con versiones
anteriores de VB. Veamos esto en el siguiente ejemplo, en el que se modifica la propiedad Font de RTB
con el CommonDialog CD1
RTB.Font.Name = CD1.FontName
RTB.Font.Size = CD1.FontSize
RTB.Font.Bold = False
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 241
RTB.Font.Italic = False
(Observe que en el RTB ponemos Font.Name y en el CD1 ponemos FontName)
Con la propiedad Font podemos escribir en el RTB usando la misma letra para todo el texto. Sin
embargo verá que esta propiedad prácticamente no se va a usar, ya que el RTB tiene la gran ventaja
que puede usar varios tipos de letra y tamaños dentro de un mismo texto. Puede usar también varios
colores. Para poder cambiar de letra no usaremos Font.Name, sino SelFontName, (Fíjese que esta
propiedad no lleva ningún punto intermedio) que cambia el tipo de letra en el texto que hayamos
seleccionado, y si no hemos seleccionado ningún texto, y el cursor de escritura se encuentra al final del
texto escrito, lo que hará será cambiar el tipo de letra a partir de ese punto.
Propiedades SelBold, SelItalic, SelStrikethru, SelUnderline
Estas propiedades son del tipo Booleano (True/False) y nos permitirán poner el texto seleccionado en
Negrita, Cursiva, Tachada y Subrayada respectivamente.
Por ejemplo,
RTB.SetBold = True pondrá el negrita el texto seleccionado.
RTB.SelItalic = True pondrá en cursiva el texto seleccionado.
RTB.SelStrikethru = True pondrá en tachado el texto seleccionado.
RTB.SelUnderline = True pondrá en subrayado el texto seleccionado.
( RTB = Nombre del control RichTextBox )
Si el texto seleccionado está en la parte final del texto, o si el cursor de escritura está al final del escrito y
no se ha seleccionado ningún texto, la propiedad elegida permanecerá vigente para la escritura que se
realice a partir de ese punto.
SelFontName
Esta propiedad devuelve o establece el nombre de la fuente en el texto
seleccionado. P.e. RTB1.SelFontName = “Arial”
SelFontSize
Devuelve o establece el tamaño de la fuente en el texto seleccionado.
P.e. RTB1.SelFontSize = 10
SelColor
Devuelve o establece el color del texto seleccionado. Para definir el
color puede usarse cualquiera de los métodos explicados en un capítulo anterior.
Los ejemplos siguientes cambiarán el texto seleccionado a color rojo
RTB.SelColor = RGB (255,0,0)
RTB.SelColor = 255
RTB.SelColor = &HFF
Al igual que las otras propiedades, si el texto seleccionado está al final del texto, o si el cursor de
escritura está al final del escrito, la propiedad elegida permanecerá vigente para la escritura que se
realice a partir de ese punto.
Propiedades Text y TextRTF
Las vimos al principio. La propiedad Text contiene TODO el texto del RichTextBox en formato de texto
plano. La propiedad TextRTF contiene TODO el texto del RichTextBox en formato de texto enriquecido.
Estas propiedades son de lectura y escritura, de forma que pueden tener estas dos sintaxis:
Escritura:
RTB.Text = “Siempre nos quedará París”
Esta instrucción sustituye todo el contenido del RTB por el texto Siempre nos quedará París
Lectura:
MiVariable = RTB.Text
MiVariable contendrá todo el contenido de RTB en formato de texto plano
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 242
La propiedad TextRTF es similar, pero con texto en formato enriquecido. Si la usamos como lectura:
MiVariable = RTB.TextRTF
MiVariable contendrá el texto, más los caracteres que definen el tipo de letra, tamaño, etc, como vimos
al principio.
Si la usamos como escritura:
RTB.TextRTF = TuVariable
Si TuVariable contiene un texto en formato RTF, el contenido de RTB será justamente ese texto, con
todas sus florituras de tipo de letra, tamaño, negrita, etc. Si TuVariable contuviese un texto en formato de
texto plano, lo escribirá tal cual, con el tipo y tamaño de letra que tenga en su propiedad Font.
Propiedades SelText y SelRTF
Es conveniente no confundirlas con las anteriores. Aquellas contenían TODO el texto del
RichTextBox. Estas, solo el texto que está seleccionado.
SelText
Devuelve o establece el texto seleccionado en formato de texto plano. No está disponible en tiempo de
diseño.
Al ser una propiedad de lectura y escritura, nos permite:
añadir texto (que se colocará en la posición en la que esté el curso) o cambiar el texto
seleccionado por otro. La instrucción
Escritura:
RTB.SelText = “Siempre nos quedará París”
Introducirá el texto anterior en la posición donde estuviera el cursor, o si teníamos texto seleccionado,
cambiará el texto anterior por este.
Lectura: Teniendo un trozo de texto seleccionado,
MiVariable = RTB.SelText
MiVariable tomará el valor del texto que estuviese seleccionado en formato de texto plano.
SelRTF
Devuelve o establece el texto seleccionado en formato .RTF. Al igual que SelText es de lectura y
escritura. No está disponible en tiempo de diseño.
Sintaxis (Escritura)
RTB.SelRTF = MiVariable
Si el contenido de MiVariable está en formato RTF, sustituirá el texto que tuviésemos seleccionado por el
contenido de MiVariable, y lo escribirá con todos los detalles de tipo de letra, tamaño, etc., que
contuviese el formato RTF. Si no hubiésemos seleccionado previamente ningún texto, escribirá ese
texto en el lugar donde estuviese colocado el cursor.
Si el contenido de MiVariable fuese un texto plano, escribirá ese texto, usando las mismas propiedades
para la letra que tuviese el texto seleccionado previamente, o las del punto donde se encontrase el
cursor.
Sintaxis de Lectura)
MiVariable = RTB.SelRTF
MiVariable contendrá el texto que estuviese seleccionado, en formato RTF.
Esta propiedad es equivalente a la propiedad SelText y funciona de forma idéntica, pero en este caso el
texto reemplazado o devuelto mediante la propiedad SelRTF está en formato RTF. Esta propiedad
devuelve una cadena de longitud cero ("") si no hay texto seleccionado en el control.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 243
Alineación y márgenes del texto
El RichTextBox permite crear un margen desde el borde izquierdo hasta el comienzo de la escritura,
(Propiedad SelIndent), y otro margen desde el borde derecho hasta el final de la línea (Propiedad
SelRightIndent), o limitar el ancho de la línea (Propiedad RightMargin). También se puede poner una
sangría a las líneas segunda y siguientes respecto a la primera línea del párrafo (Propiedad
SelHangingIndent). Este tipo de sangría es la sangría francesa, sangría que no se suele usar (a lo
mejor se usa en Francia). En realidad lo que se usa mucho es separar la primera línea del párrafo un
poco más que el resto de las líneas. Esto puede conseguirse dando un valor negativo a la propiedad
SelHangingIndent. Lo verá mas adelante.
La medida de estos márgenes y sangrías se realiza en las unidades de medida del formulario que
contiene al RichTextBox. Veamos un ejemplo comentado de estas propiedades.
Margen izquierdo. Con la instrucción
RTB.SelIndent = Val(TBSangria)
Separa el párrafo correspondiente a la línea donde está en ese momento al cursor. (Que a partir de
ahora la llamaremos Línea en curso) El espacio que separa ese párrafo del borde izquierdo del
RichTextBox es un valor igual al que hayamos introducido en el TextBox TBSangría, medido en las
unidades de medida del formulario que contiene a RTB. Recuerde, sólo hace la sangría con el párrafo
que contiene la línea en curso.
Si queremos separar varios párrafos, debemos seleccionar esos párrafos antes de ejecutar la instrucción
anterior. Para poner una separación desde el borde izquierdo de todas los párrafos del texto
deberemos primero, seleccionar todo el texto, y luego ejecutar la instrucción anterior. Esto podemos
lograrlo combinando estas tres instrucciones:
RTB.SelStart = 1
RTB.SelLength = Len(RTB.Text)
RTB.SelIndent = Val(TBSangria)
Margen derecho. Usaremos la propiedad SelRightIndent. Con la instrucción:
RTB.SelRightIndent = Val(TBMargenDcho)
Separamos el final del párrafo donde está la línea en curso una distancia igual al valor de
TBMargenDcho. Esta propiedad es completamente equivalente a la anterior, esta referida al margen
derecho y aquella al margen izquierdo. Es aplicable todo lo que se dijo para SelIndent.
Longitud máxima de la línea desde el borde izquierdo. Parece un poco largo la definición de esta
propiedad. Se refiere a la propiedad RightMargin. Esta propiedad marca la distancia desde el borde
izquierdo del RichTextBox hasta el límite máximo utilizable por el texto. Este valor es el que se toma
como fin de la zona utilizable por el texto, por lo tanto, ese punto será la referencia que utilice la
propiedad SelRightIndent para determinar el punto a partir del cual creará el margen derecho. También
será la referencia derecha cuando centremos un texto o lo alineemos a la derecha.
RTB.RightMargin = Val(TBAncho)
La instrucción anterior fija como distancia máxima que puede ocupar una línea de texto la cantidad
introducida en TBAncho. Por supuesto, expresada como siempre en las unidades de medida del
formulario. La línea puede ser mas ancha que el ancho del RichTextBox. En este caso la línea no cabe
en el RTB, pero puede visualizar la línea completa usando baraas de scroll horizontales (Vea propiedad
ScrollBars más adelante)
Sangría francesa. La sangría francesa consiste en separar la segunda línea y siguientes cierta medida
a la derecha respecto a la primera línea. Algo así
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 244
Esta es la primera línea de este texto donde se explica lo que es una sangría francesa
en realidad desconozco si en Francia usan este tipo de sangría, pero a mí
me gusta más la sangría española, siempre que esté bien fresquita.
Esto se logra mediante la propiedad SelHangingIndent y afecta únicamente al párrafo donde se
encuentra la línea en curso.
Puede hacer lo que parece mas lógico, separar la primera línea un poco respecto a las demás, dando un
valor negativo a la propiedad SelHangingIndent. Pero para que esto resulte, debe poner un valor al
menos igual a la propiedad SelIndent. En el ejemplo siguiente, hacemos una sangría solamente a la
primera línea del párrafo donde está la línea en curso:
RTB.SelIndent = Val(TBSangriaEsp)
RTB.SelHangingIndent = -Val(TBSangriaEsp)
(Observe el signo menos en la segunda línea) El valor de la sangría de la primera línea será el
contenido en TBSangriaEsp
Centrado, Alineación a la izquierda o a la derecha.
El centrado de una línea o párrafo se logra mediante la propiedad SelAlignment Puede tomar los
valores 0 (alineado a la izquierda), 1 (a la derecha) ó 2 (centrado) Siempre se refiere a la línea en
curso o al párrafo que contiene la línea en curso. Si quiere alinear varios párrafos, debe seleccionarlos
antes de ejecutar la instrucción de alineamiento.
RTB.SelAlignment = 0 ‘alinea a la izquierda
RTB.SelAlignment = 1 ‘alinea a la derecha
RTB.SelAlignment = 2 ‘centra el texto
En la alineación se tiene en cuenta la propiedad RightMargin, es decir, si alinea a la derecha, lo hará
tomando como parte mas derecha del escrito el valor de la propiedad RightMargin, no el borde lateral
derecho del RTB. Lo mismo le ocurre con el centrado.
Viñetas
El RichTextBox es, como decíamos al principio, un control que nos permite realizar editores de textos
muy potentes. Incluso podemos poner viñetas
Una viñeta es un párrafo marcado con un punto en su comienzo, y que lleva una cierta sangría respecto
al borde izquierdo del RichTextBox. Para poner una viñeta es necesario jugar con dos propiedades:
SelBullet, propiedad Booleana que si la hacemos True convertimos el párrafo donde está la línea en
curso en una viñeta. Si está en False, ese párrafo será un párrafo normal.
BulletIndent, propiedad a la que le pondremos un valor numérico igual a la separación que queremos
poner en el texto de la viñeta.
Para que tenga efecto la propiedad BulletIndent, la propiedad SelBullet debe estar puesta a True. No
tendrá efecto alguno si SelBullet = False. Por ejemplo, para poner una viñeta podemos poner
RTB.SelBullet = True
RTB.BulletIndent = 500
Una vez puesta una viñeta en el RichTextBox, insertará otro cada vez que pulsemos ENTER. Para
quitarlo, basta con ejecutar la sentencia
SelBullet = False
La propiedad BulletIndent es de lectura y escritura. La instrucción siguiente nos devuelve la separación
de la viñeta donde tengamos el cursor. La propiedad BulletIndent devuelve 0 si la selección abarca
múltiples párrafos con distintos ajustes de margen o si el párrafo no es una viñeta.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 245
También podemos leer el valor de SelBullet. Devolverá
Null. La selección abarca más de un párrafo y contiene una mezcla de estilos de viñeta y no viñeta.
True. Los párrafos de la selección tienen estilo de viñeta.
False. La párrafos de la selección no tienen estilo de viñeta.
Tabulación del RichTextBox
Si queremos crear un editor de texto de la categoría de cualquiera de los comerciales, debemos poder
tabular. Tabular significa crear unos hitos o marcas a una determinada distancia del borde izquierdo del
papel, de forma que cada vez que pulsemos la tecla Tabulador el cursor de escritura se coloca al inicio
del siguiente de esas marcas.
El primer problema es que si estamos escribiendo sobre el RichTextBox y pulsamos Tabulador, el foco
se nos escapa hacia el siguiente control, según el orden de la propiedad TabIndex. Existe una solución,
que es pulsar la combinación de las teclas Ctrl + Tab. Sin embargo esa posibilidad no es recomendable,
dado que un usuario normal no está acostumbrado a realizar esa combinación para forzar una
tabulación.
La solución está en poner la propiedad TabStop de todos los controles a False, cada vez que el
RichTextBox toma el foco. Es decir, en su procedimiento GotFocus. De esta forma, al dar el tabulador
ningún control se “querrá” quedar con el foco, y por lo tanto el foco seguirá en el RichTextBox. En estas
condiciones el resultado es que el cursor de escritura pasará a la siguiente tabulación.
Vamos a ver como se puede poner la propiedad TabStop a False en todos los controles del formulario.
Para ello vamos a explicar un nuevo objeto Visual Basic, el objeto Controls. Este objeto es una
colección, y está formada por todos los controles del formulario. Como cualquier colección tendrá una
propiedad, la propiedad Count que toma el valor igual al número de controles existentes en el formulario.
Como cualquier cosa de VB formada por varios elementos, cada uno de ellos se distingue por su índice.
Y este índice comienza por el 0 y termina por el n-1, siendo n = número de elementos de esa colección.
Para poner la propiedad TabStop a False en todos los controles de la colección Controls del formulario,
basta con poner este código en el procedimiento GotFocus del RTB
Private Sub RTB_GotFocus()
Dim I As Integer
‘Con la siguiente línea se evita el error producido en aquellos controles que no tienen la ‘propiedad
TabStop
On Error Resume Next
For I = 0 To Me.Controls.Count - 1
Controls(I).TabStop = False
Next I
End Sub
Podemos hacerlo de otra forma. Declaremos una variable tipo Objeto Control
Private Sub RTB_GotFocus()
Dim Pepe As Control
On Error Resume Next 'De esta forma se evita el error producido en aquellos controles que no tienen
la propiedad TabStop
For Each Pepe In Controls
Pepe.TabStop = False
Next
End Sub
Nota. Si va a la información del RichTextBox podrá ver un ejemplo de esto, con el siguiente código:
For Each Control In Controls
Control.TabStop = False
Next Control
Milagros del Visual Basic: Así no funciona
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 246
Ya funciona perfectamente el tabulador en el RichTextBox. Pero cuando salgamos del RichTextBox,
debemos volver a poner la propiedad TabStop de todos los controles a True. Para ello, en el
procedimiento LostFocus del RTB pondremos el código anterior, poniendo True en vez de False en la
propiedad TabStop.
Programar las medidas de las tabulaciones.
Propiedad SelTabCount
Establece el número de tabulaciones en un RTB. P.e., si queremos crear 5 tabulaciones
RTB.SelTabCount = 5
Propiedad SelTabs
Establece el valor numérico (separación desde el borde izquierdo) de las tabulaciones. Dado que pueden
existir varias tabulaciones, deberemos distinguirlas entre ellas mediante un índice. El índice para la
primera tabulación es el 0
RTB.SelTabs(0) = 1000
RTB.SelTabs(1) = 2000
RTB.SelTabs(2) = 3000
RTB.SelTabs(3) = 4000
RTB.SelTabs(4) = 5000
Con estas líneas determinaríamos la posición de tabulación de
los 5 tabuladores.
Antes de darle valor a la propiedad SelTabs deberemos haber creado los tabuladores mediante
SelTabCount. Si pretende darle valor a un tabulador mayor que el número de tabuladores real (por
ejemplo, si pone en el caso anterior RTB.SelTabs(5) = 5000) le dará un error.
Recuerde que los valores de los tabuladores debe darlos en las unidades de medida del formulario.
OTRAS PROPIEDADES
Propiedad SelCharOffset
Nos permite crear subíndices y superíndices. La sintaxis es:
RTB.SelCharOffset = Número
Donde Número indica la separación del superíndice o subíndice en Twips. Si Número es positivo,
obtendremos un superíndice, si es negativo, un subíndice.
Esta forma de escribir subíndices y superíndices se debe aplicar cada vez que queramos escribir uno de
ellos, e inmediatamente, poner esa propiedad a 0, ya que si no lo hacemos así, escribiría como
subíndice o superíndice el resto del texto. P.e. para poner un superíndice:
TamIni = RTB.SelFontSize
RTB.SelFontSize = TamIni - 4
RTB.SelCharOffset = 40
RTB.SetFocus
Para restaurar los valores anteriores
RTB.SelFontSize = TamIni
RTB.SelCharOffset = 0
RTB.SetFocus
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 247
Propiedad SelProtected
Es una propiedad Booleana, que nos permite proteger contra cualquier cambio a una parte del texto (o
todo el texto) que contiene el RTB. Para proteger una parte del texto basta con seleccionarla y a
continuación ejecutar la instrucción
RTB.SelProtected = True
Una vez protegida una parte del texto, esa parte no se puede variar. Puede desprotegerse, volviendo a
seleccionarla y ejecutando la instrucción:
RTB.SelProtected = False
Propiedad ScrollBars
Pone barras de desplazamiento al RichTextBox.
Esta propiedad puede establecerse a 0 (None, ninguna), a 1 (Horizontal), 2 (Vertical) o 3 (Both, ambas).
Cuando las barras de desplazamiento no son necesarias, bien porque hay pocas líneas, bien porque hay
pocos caracteres por línea, las barras de desplazamiento están desactivadas.
Es frecuente pensar que las barras de desplazamiento horizontal no funcionan. Y eso ocurre porque
siempre se ven desactivadas. En realidad lo que pasa es que solamente se activan cuando la línea de
texto es mas ancha que el ancho del RichTextBox. Puede ocurrir eso cuando la propiedad RightMargin
tiene un valor superior a la anchura del control, circunstancia que nos permite escribir saliéndonos del
control, y es en solamente en ese caso en el que se activa la barra de scroll horizontal.
Las barras de desplazamiento pueden desactivarse mediante la propiedad DisableNoScroll.
Propiedad DisableNoScroll
Devuelve o establece un valor que determina si están desactivadas las barras de desplazamiento en el
control RichTextBox.
Sintaxis
NombredelRichTextBox.DisableNoScroll = True / False
Si es False, las barras de desplazamiento aparecen normalmente. Si es True, las barras de
desplazamiento aparecen atenuadas.
Propiedad Appearance
Plano o tridimensional, como en el resto de los controles.
Propiedad AutoVerbMenu
Propiedad Booleana que indica si se presenta un menú emergente cuando el usuario hace click con el
botón derecho del ratón. El menú emergente muestra los comandos de Deshacer (Ctrl-Z) cortar (Ctrl-X),
copiar (Ctrl-C), pegar (Ctrl-V) y Eliminar (Supr) Pero no es necesario escribir código en ninguna parte
para que se realicen estas operaciones (Por una vez, VB nos regala unas operaciones. No es VB, es
Windows directamente)
Sintaxis
NombredelRichTextBox.AutoVerbMenu = True / False
Si esta propiedad está a True muestra el menú. False no lo muestra.
Propiedad BorderStyle
Sin borde o con borde (None o Fixed Single)
Propiedad Enabled
Propiedad Booleana. Activa o desactiva el RichTextBox
FileName
Esta propiedad devuelve o establece el nombre del fichero .RTF cargado en el RichTextBox. Si
ejecutamos la línea de código :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 248
RTB1.Filename =”C :\CursoVB\Mitexto.rtf”
lo que ocurrirá es que nuestra aplicación cargará el fichero C :\CursoVB\Mitexto.rtf en el RichTextBox
RTB1. Es decir, hace lo mismo que el Método LoadFile (Vea mas abajo).
Sólo puede especificar los nombres de archivos de texto o archivos .RTF válidos para esta propiedad.
Le recomendamos que para cargar un texto en un RTB use siempre el método LoadFile en vez de la
propiedad Filename.
Si lo que hacemos con esta propiedad es consultar el fichero cargado en el RTB :
Variable = RTB1.Filename
obtendremos en Variable el nombre (y Path) del fichero que tenemos cargado en el RTB
HideSelection
Devuelve o establece un valor que determina si el texto seleccionado aparece resaltado cuando el
RichTextBox pierde el enfoque. Esto es justamente lo que ocurre cuando seleccionamos un trozo de
texto (Por ejemplo para pasar ese texto a negrita) y hacemos click sobre otro control (Por ejemplo, sobre
un botón de comando para cambiar a Negrita) Si tenemos esta propiedad a False el texto seleccionado
sigue seleccionado. Si está a True, el texto se deselecciona.
NOTA Le recomiendo que cuando tenga un control para cambiar el tipo de letra, hágalo sobre un control
que no acepte el foco (Label, p.e.)
Sintaxis
NombreRTB.HideSelection = True / False
para establecer la propiedad
Variable = NombreRTB.HideSelection
para leerla
Propiedad Locked
Igual que le ocurre al TextBox, si ponemos esta propiedad a True impedimos que se pueda cambiar el
texto existente en el RichTextBox mediante el teclado.
MaxLength
Esta propiedad marca el número máximo de caracteres que puede contener. Si se pone a 0
(Predeterminado) admite cualquier número de caracteres.
MousePointer
Igual que para el resto de los controles.
Multiline
Igual que para el TextBox. Si está a True (predeterminado) el RichTextBox puede contener varias líneas.
Si está a False, una solo.
OLEDragMode
OLEDropMode
Estas dos propiedades son similares a la DragMode de otros controles. Se verán con mas detalle al
estudiar el Drag & Drop.
METODOS DEL CONTROL RichTextBox
El control RichTextBox cuenta con unos métodos especiales para abrir un fichero y guardar el texto que
contiene un poco especiales. Estos métodos (SaveFile y LoadFile) se pueden usar solamente cuando
queremos guardar o leer el texto en formato .RTF. Con ellos no es necesario abrir el fichero (con Open
Nombrefichero .....) ni cerrarlo, pero siempre para guardar o leer texto en formato RTF. Podemos leer o
guardar el texto de un RichTextBox como texto plano (Como los ficheros ASCII .TXT). Para ello
debemos utilizar los métodos Open Nombrefichero For Input / Output vistos en el capítulo de ficheros.
METODO SaveFile
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 249
Guarda el contenido de un control RichTextBox en un archivo.
Sintaxis NombredelRTB.SaveFile(nombre_ruta, tipo_archivo)
Donde nombre_ruta (Parámetro requerido) es una expresión de cadena que define la ruta de acceso y el
nombre del archivo que va a recibir el contenido del control, y tipo_archivo es un entero o una constante
que especifica el tipo de archivo cargado, como se describe a continuación :
0
1
rtfRTF
rtfText
El control RichTextBox guarda su contenido como un archivo .RTF.
El control RichTextBox guarda su contenido como un archivo de texto.
El valor predeterminado es 0. Si no se pone este parámetro, toma el valor 0 por defecto.
Ejemplo
RTB1.SaveFile “C :\CursoVB\mitexto.rtf”, 0
Guarda el contenido del RichTextBox RTB1 en un fichero llamado mitexto.rtf que está en el directorio
CursoVB, con formato RTF
Aparte del método SaveFile, puede utilizar la función Print de Visual Basic y las propiedades TextRTF y
SelRTF del control RichTextBox para escribir archivos .RTF. Por ejemplo, puede guardar el contenido de
un control RichTextBox en un archivo .RTF de este modo:
Open "mitexto.rtf" For Output As 1
Print #1, RichTextBox1.TextRTF
Close #1
METODO LoadFile
Carga un archivo .RTF o un archivo de texto en un control RichTextBox.
Sintaxis NombreRTB.LoadFile nombre_ruta, tipo_archivo
Donde nombre_ruta (Parámetro requerido) es una expresión de cadena que define la ruta de acceso y el
nombre del archivo que se va a cargar en el control, y tipo_archivo
es un entero o una constante
que especifica el tipo de archivo cargado, como se describe a continuación
0
1
rtfRTF
rtfText
El archivo cargado debe ser un archivo .RTF válido.
El control RichTextBox carga cualquier archivo de texto.
Al cargar un archivo con el método LoadFile, el contenido del archivo cargado reemplaza a todo el
contenido del control RichTextBox. Esto hace que cambien los valores de las propiedades Text y rtfText.
También puede usar la función Input de Visual Basic y las propiedades TextRTF y SelRTF del control
RichTextBox para leer archivos .RTF. Por ejemplo, puede cargar el contenido de un archivo .RTF en el
control RichTextBox de este modo:
Open "C :\CursoVB\mitexto.rtf" For Input As 1
RichTextBox1.TextRTF = Input$(LOF(1), 1)
Close #1
METODO Find
Busca una cadena específica en el texto de un control RichTextBox.
Sintaxis Variable = NombreRTB.Find (cadena, inicio, fin, opciones)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 250
Donde :
cadena (Necesario)
inicio (Opcional)
(Opcional)
fin
Opciones (Opcional)
Valor
Una expresión de cadena que desea buscar en el control.
Un índice de caracteres de tipo Integer que determina dónde comienza
la búsqueda. Cada carácter del control tiene un índice entero que lo
identifica de forma única. El primer carácter de texto del control tiene
un índice 0.
Un índice de carácter de entero que determina dónde termina la
búsqueda.
Una o más valores o constantes utilizadas para especificar
características opcionales, como se describe a continuación.
Constante
Descripción
1
rtfWholeWord Determina si una coincidencia se basa en una palabra completa o en
parte de una palabra.
4
rtfMatchCase Determina si una coincidencia se basa el uso de mayúsculas y
minúsculas de la cadena especificada además del texto de la cadena.
8
rtfNoHighlight Determina si una coincidencia aparece resaltada en el control
RichTextBox.
Puede combinar múltiples opciones si utiliza el operador Or.
Si se encuentra el texto buscado, el método Find resalta el texto especificado y devuelve un número con
la posición del primer carácter resaltado. Si no se encuentra el texto especificado, el método Find
devuelve –1.
Si utiliza el método Find sin la opción rtfNoHighlight aunque la propiedad HideSelection sea True y el
control RichTextBox no tenga el enfoque, el control seguirá resaltando el texto encontrado. Los usos
posteriores del método Find sólo buscarán el texto resaltado hasta que se mueva el punto de inserción.
El comportamiento de búsqueda del método Find varía según la combinación de valores especificados
para los argumentos inicio y fin. Esta tabla describe los comportamientos posibles:
Inicio
Fin
Comportamiento de búsqueda
Especificado
Especificado
Especificado
Omitido
Omitido
Especificado
Omitido
Omitido
Busca desde la ubicación inicial especificada hasta la
ubicación final especificada.
Busca desde la ubicación inicial especificada hasta el final del
texto del control.
Busca desde el punto de inserción actual hasta la ubicación
final especificada.
Busca en la selección actual si el texto está seleccionado o en
todo el contenido del control si no hay texto seleccionado.
METODO GetLineFromChar
Devuelve el número de la línea que contiene una posición de carácter especificado en un control
RichTextBox.
Sintaxis
Variable = NombreRTB.GetLineFromChar (pos_carácter)
Donde po s_c aráct er (Requerido) es un entero largo que especifica la posición del carácter cuya línea
desea identificar. El índice del primer carácter del control RichTextBox es 0.
Utilice el método GetLineFromChar para averiguar qué línea del texto de un control RichTextBox
contiene una determinada posición de carácter. Es posible que necesite hacerlo porque puede variar el
número de caracteres de cada línea, lo que hace muy difícil averiguar qué línea del texto contiene un
determinado carácter, identificado por su posición en el texto.
METODO SelPrint
Envía texto con formato de un control RichTextBox a un dispositivo de impresión.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 251
Sintaxis
NombreRTB.SelPrint(hdc)
Donde hdc es el contexto de dispositivo del dispositivo que va a utilizar para imprimir el contenido del
control.
Si hay texto seleccionado en el control RichTextBox, el método SelPrint sólo enviará el texto
seleccionado al dispositivo de destino. Si no hay texto seleccionado, se enviará el contenido completo del
control RichTextBox al dispositivo.
El método SelPrint no imprime texto desde el control RichTextBox. En su lugar, envía una copia del
texto con formato a un dispositivo que pueda imprimirlo. Por ejemplo, puede enviar el texto al objeto
Printer utilizando código como éste:
RichTextBox1.SelPrint(Printer.hDC)
Observe que la propiedad hDC del objeto Printer se utiliza para especificar el argumento de contexto de
dispositivo del método SelPrint.
Nota Si utiliza el objeto Printer como destino del texto desde el control RichTextBox, deberá inicializar
en primer lugar el contexto de dispositivo del objeto Printer. Esto es necesario, ya que Visual Basic no
conoce el hDC del Printer hasta que se imprime algo. La información de Microsoft recomienda imprimir
una cadena de longitud cero.
(Ejecutar la instrucción Printer.Print “”) Sin embargo esa no es buena solución ya que da un error de
impresora. Vale mas forzar la posición del papel, aunque no hiciese falta
Printer.Orientation = 1
Mediante SelPrint nos podemos ahorrar la tediosa programación del Printer, pero tiene también
inconvenientes: No controlamos el cambio de página, si tenemos papel preimpreso es muy difícil
ajustarlo, etc.
METODO Span
Selecciona texto en un control RichTextBox basándose en un conjunto de caracteres especificado.
Sintaxis NombreRTB.Span juego_caracteres, hacia_adelante, negado
donde :
ju eg o _c ar ac ter es (Requerido) Una expresión de cadena que especifica el juego de caracteres que se
va a buscar al ampliar la selección, basándose en el valor de negado.
hacia_adelante (Opcional) Una expresión booleana que determina en qué sentido se mueve el punto de
inserción, como se describe mas adelante.
Negado (Opcional) Una expresión booleana que determina si los caracteres de juego_caracteres
definen el conjunto de caracteres de destino o se excluyen del conjunto de caracteres de destino, como
se describe mas adelante.
Los valores para hacia_adelante son:
True (Predeterminado) Selecciona texto desde el punto de inserción actual o desde el principio de la
selección actual hacia delante, hacia el final del texto.
False Selecciona texto desde el punto de inserción actual o el principio de la selección actual hacia
atrás, hacia el principio del texto.
Los valores para negado son:
True
Los caracteres incluidos en la selección son los que no aparecen en el argumento
juego_caracteres. La selección se detiene en el primer carácter encontrado que aparece en el
argumento juego_caracteres.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 252
False (Predeterminado) Los caracteres incluidos en la selección son los que aparecen en el argumento
juego_caracteres. La selección se detiene en el primer carácter encontrado que no aparece en el
argumento juego_caracteres.
El método Span se utiliza principalmente para seleccionar fácilmente una palabra o una frase en el
control RichTextBox.
Si el método Span no encuentra los caracteres especificados basándose en los valores de los
argumentos, el punto de inserción o la selección actual permanece sin cambios.
El m é
tod o Sp an n o d evuelv e dato s.
METODO Upto
Mueve el punto de inserción hasta el primer carácter (sin incluirlo) que sea miembro del conjunto de
caracteres especificado en un control RichTextBox.
Sintaxis NombredelRTB.Upto (juego_caracteres, hacia_adelante, negado)
Donde :
ju eg o _c ar ac ter es (Requerido) Una expresión de cadena que especifica el conjunto de caracteres que
se va a buscar al mover el punto de inserción, basándose en el valor de negado.
hacia_adelante (Opcional) Una expresión booleana que determina en qué sentido se mueve el punto de
inserción, como se describe en Valores.
negado (Opcional) Una expresión booleana que determina si los caracteres de juego_caracteres definen
el conjunto de caracteres de destino o se excluyen del conjunto de caracteres de destino, como se
describe en Valores.
Valores
Los valores de hacia_adelante son:
True (Predeterminado) Mueve el punto de inserción hacia delante, hacia el final del texto.
False Mueve el punto de inserción hacia atrás, hacia el principio del texto.
Los valores para negado son:
True Los caracteres no especificados en el argumento juego_caracteres se utilizan para mover el
punto de inserción.
False (Predeterminado) Los caracteres especificados en el argumento juego_caracteres se utilizan
para mover el punto de inserción.
El Portapapeles y el RichTextBox
Imagínese que seleccionamos un texto en un RichTextBox y ese texto lo metemos al portapapeles.
Dado que el texto está escrito en RTF, ¿Como nos lo guarda el Portapapeles ?
La solución es que puede guardarlo en las dos versiones. En formato de texto plano (Guarda
estrictamente los caracteres ASCII del texto seleccionado) o como texto enriquecido (RTF), guardando
en este caso, además del texto limpio y puro, la información del tipo de letra, tamaño, color, etc. típicas
del formato RTF.
Para ello debemos indicarle al portapapeles en qué formato queremos guardarlo. La línea de código :
Clipboard.SetText RTB1.SelRTF, vbCFRTF
guarda en el portapapeles el texto seleccionado en ese momento, en formato RTF. La línea
Clipboard.SetText RTB1.TextRTF, vbCFRTF
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 253
guarda en el portapapeles todo el contenido del RichTextBox (llamado RTB1 en los ejemplos) en
formato RTF
Las líneas :
Clipboard.SetText RTB1.SelRTF, vbCFText
Clipboard.SetText RTB1.TextRTF, vbCFText
guardarán, respectivamente, el texto seleccionado y todo el texto de RTB1, en formato de texto plano
Pero esta no es la única forma de introducir texto procedente del RichTextBox en el portapapeles.
Podemos introducir el texto seleccionado con formato RTF de la forma :
ClipBoard.SetText RTB1.SelRTF
Y el texto plano con
Clipboard.SetText RTB1.SelText
Para introducir TODO el texto del RTB en formato RTF
Clipboard.SetText RTB1.TextRTF
Para meter TODO el texto del RTB en texto plano
Clipboard.SetText RTB1.Text
APENDICE
Constantes del control RichTextBox
Constante
Valor
Descripción
Propiedad Appearance
rtfFlat
0
Uniforme. Pinta sin efectos visuales.
rtfThreeD
1
(Predeterminado). 3D. Pinta con efectos tridimensionales.
Método Find
rtfWholeWord 2
rtfMatchCase
4
rtfNoHighlight
8
Determina si una coincidencia se basa en una palabra completa o en
parte de una palabra.
Determina si una coincidencia se basa en el uso de mayúsculas y
minúsculas de la cadena especificada además del texto de la cadena.
Determina si una coincidencia aparece resaltada en el control
RichTextBox.
Métodos LoadFile y SaveFile
(Predeterminado) RTF. El archivo cargado debe ser un archivo .RTF
rtfRTF
0
válido (método LoadFile) o el contenido del control se guarda en un archivo .RTF
(método SaveFile).
rtfText
1
Texto. El control RichTextBox carga cualquier archivo de texto
(método LoadFile) o el contenido del control se guarda en un archivo de texto
(método SaveFile).
Propiedad MousePointer
(Predeterminado) La forma está determinada por el objeto.
rtfDefault
0
rtfArrow 1
Flecha.
rtfCross
2
Cruz (cursor en forma de cruz).
rtfIbeam
3
Cursor en forma de I.
rtfIcon
4
Icono (cuadrado pequeño dentro de un cuadrado).
rtfSize
5
Tamaño (flecha de cuatro puntas que señala al norte, sur, este y oeste)
rtfSizeNESW 6
Tamaño NE-SO (flecha de dos puntas que señala al nordeste y al
sudoeste).
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 254
rtfSizeNS
7
rtfSizeNWSE 8
rtfSizeEW
9
rtfUpArrow
10
rtfHourglass
11
rtfNoDrop
12
rtfArrowHourglass
rtfArrowQuestion
rtfSizeAll
15
rtfCustom
99
Tamaño N S (flecha de dos puntas que señala al norte y al sur).
Tamaño NO, SE.
Tamaño EO (flecha de dos puntas que señala al este y al oeste).
Flecha hacia arriba.
Reloj de arena (espere).
No colocar.
13
Flecha y reloj de arena.
14
Flecha y signo de interrogación.
Ajustar todo.
Icono personalizado especificado por la propiedad MouseIcon.
Propiedad Selalignment
rtfLeft
0
(Predeterminado) Izquierda. El párrafo se alinea a lo largo del margen
izquierdo.
rtfRight
1
Derecha. El párrafo se alinea a lo largo del margen derecho.
rtfCenter
2
Centro. El párrafo se centra entre los márgenes izquierdo y derecho.
Propiedad Scrollbars
rtfNone
0
rtfHorizontal
1
rtfVertical
2
rtfBoth
3
(Predeterminado) Ninguna.
Sólo barra de desplazamiento horizontal.
Sólo barra de desplazamiento vertical.
Barras de desplazamiento horizontal y vertical.
El FORMATO RTF
Cuando se edita un texto mediante un procesador de textos, el fichero resultante se guarda don un
formato distinto para cada procesador. De esta forma, un texto editado en WP no es compatible con el
P.T. AmiPro, con Word o con cualquier otro. Los fabricantes de estos procesadores de textos han tenido
que incluir una herramienta capaz de convertir un formato a otro para poder alcanzar la compatibilidad
entre ellos que el mercado exigía.
El Formato de Texto Enriquecido pretende ser un nexo de unión entre todos los procesadores de texto,
para poder intercambiar ficheros editados en uno u otro. De hecho, las últimas versiones de los mas
importantes procesadores de textos incluyen la posibilidad de guardar y buscar el texto en este formato.
(WP, Word)
Este formato consiste en guardar mediante caracteres ASCII plenamente legibles tanto el texto escrito
como los tipos de letra, tamaño, saltos de carro, etc. Veamos un ejemplo comparativo del mismo texto
escrito en Word, guardado en RTF y en ASCII :
Texto1
Este texto está escrito en Word. Observe que podemos poner letra negrita, letra cursiva, letra
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el tamaño de las
letras a tamaño mas grande, mas pequeño, etc.
Fin Texto 1
El mismo texto en ASCII puro :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva, letra
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el tamaño de las
letras a tamaño mas grande, mas pequeño, etc.
Fin Texto 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 255
Y ahora el mismo texto en formato RTF. En este formato hubo que seccionar las líneas para poder
mostrarlas en una hoja, ya que RTF utiliza líneas sin retornos de carro. Se han seccionado las líneas
terminándolas con un guión bajo y comenzando en la línea siguiente también con un guión bajo.
{\rtf1\ansi \deff5\deflang1033{\fonttbl{\f5\fswiss\fcharset0\fprq2 Arial;}}_
_{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;_
_\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\_
_green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\_
blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue_
_192;}{\stylesheet{\widctlpar
\f5\fs20\lang1034 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}_
_}{\info{\author LUIS SUAREZ BERNALDO}{\operator LUIS SUAREZ BERNALDO}_
_{\creatim\yr1997\mo3\dy9\hr11\min8}{\revtim\yr1997\mo3\dy9\hr11\min9}_
_{\version1}{\edmins1}{\nofpages1}
{\nofwords38}{\nofchars220}{\*\company }{\vern57431}}\margl1701\margr1701\_
_margt1417\margb1417 \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\formshade_
_ \fet0\sectd \linex0\headery709\footery709\colsx709\endnhere {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstar_
_t1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\_
_pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcl_
_tr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\_
_pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pn_
_start1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{_
_\pntxtb (}{\pntxta )}}\pard\plain \qj\widctlpar \f5\fs20\lang1034 Texto1
\par
\par Este texto est\'e1 escrito en Word. Observe que podemos poner letra _
_{\b negrita}, letra {\i cursiva}, letra {\ul subrayada}. Podemos cambiar_
_ el color de las letras, {\cf6 rojo}, {\cf4 verde}, {\cf2 azul}. Podemos _
_cambiar el tama\'f1o de las letras a {
\fs24 tama\'f1o mas grande}, {\fs16 mas peque\'f1o}, etc.
\par
\par
\par Fin Texto 1
\par \pard \widctlpar
\par }
Como puede observar, el RTF incluye el texto escrito casi en ASCII, pero añadiendo una serie de datos
respecto al tipo de letra, codifica los acentos, las eñes, y hasta incluye, tomándolo del ordenador, el
nombre del operador que lo ha escrito. Estas informaciones también se guardan cuando se archiva un
texto en el formato propio del procesador de textos, pero lo hace en binario, por lo que no lo podemos
visualizar. El formato RTF, dentro de que mete toda esa información adicional, lo archiva con caracteres
ASCII.
MUY IMPORTANTE
Observe que el fichero .RTF comienza por {\rtf Cuando tenga que importar un texto hacia un
RichTextBox, puede que ese texto esté en formato RTF o como Texto Plano (Fichero ASCII puro) Para
saber si el texto está en RTF analice los Cinco primeros caracteres del texto a importar. Si son {\rtf es
que está en presencia de un texto RTF.
Para saber si un fichero contiene texto enriquecido, basta con abrirlo como un fichero secuencial,
(recuerde que un fichero .RTF tiene solamente caracteres ASCII) y leer los cinco primeros caracteres.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 256
Ejercicio Propuesto. Conlos conocimientos de los Documentos de Interfaces Multiples, y los del
RichTextBox que ha adquirido en este capítulo, y los conocimientos del menú y los ficheros que ya tiene
de los capítulos anteriores, ya está en condiciones de realizar un editor de textos, casi tan bueno como el
Word. Debe ponerle las funciones típicas de cortar, copiar y pegar, documento nuevo, cerrar, guardar,
guardar como, y cada vez que cierra un documento debe saber si ha habido cambios para proponer que
se guarden.
Visual Basic - Guía del Estudiante Cap. 10
Procedimientos y funciones en VB
CORRECCION DE ERRORES Y DEPURACION DE PROGRAMAS - EL OBJETO ERROR
LA AYUDA DE WINDOWS
Procedimientos
Un Procedimiento en Visual Basic es un trozo de código que realiza una determinada tarea. Un
procedimiento es el código que asociamos a un evento de un control (CommandButton_Click,
Form_Load, ...). Un control puede tener por lo tanto, muchos procedimientos asociados. Uno a cada uno
de sus eventos.
Si queremos realizar una determinada tarea en un programa, y esta tarea se repite muchas veces en ese
programa, podemos, por ejemplo, repetir el código tantas veces como sea necesario en los puntos del
programa que así lo pidan. Esto nos llevaría a escribir líneas y líneas repetidas en nuestras aplicaciones,
con el consiguiente incremento de trabajo y del volumen de la aplicación.
Podemos hacer otra cosa mas práctica y elegante. Escribir ese código una sola vez, creando con él un
Procedimiento. Este Procedimiento tendrá un nombre, y cada vez que queramos que se ejecute ese
código bastará con nombrar por ese nombre al Procedimiento.
Un procedimiento puede insertarse en un Módulo o en Formulario. Para crear un Procedimiento basta
con hacer click en la Barra de Menú de VB en Insertar | Procedimiento. Observará que la palabra
Procedimiento del Menú desplegable está deshabilitada si no está abierta ninguna ventana de código.
Para habilitarla, abra la ventana de código del Formulario o Módulo donde quiere insertar el nuevo
Procedimiento.
Una vez hecho Click en Insertar | Procedimiento le aparecerá esta ventana :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 257
En esta ventana debe teclear el nombre que quiere dar al Procedimiento. En tipo debe elegir la opción
Procedimiento (Veremos mas adelante la Función y en otro capítulo las opciones Propiedad y Evento) y
en el Ambito debe elegir Public o Private dependiendo del ámbito que quiera darle :
Public. Se podrá acceder a él desde cualquier Formulario o Módulo del programa.
Dependiendo de donde se haya insertado el Procedimiento (Formulario o Módulo), debe citarse de la
siguiente forma :
Si se ha insertado en un Módulo, puede citarse solamente por su nombre. Puede citarse también por el
nombre del módulo seguido por el nombre del procedimiento, separando ambos por un punto. Si el
procedimiento tiene por nombre NombreProcedimiento y se ha insertado en el Módulo1 puede citarse de
las dos formas siguientes en cualquier parte del programa:
NombreProcedimiento
Modulo1.NombreProcedimiento
Si se ha insertado en un Formulario, desde ese Formulario basta con citarle por su nombre. Desde otro
Formulario o Módulo, hay que citarlo mediante el nombre del Formulario donde está insertado, seguido
del nombre del procedimiento, separados por un punto.
Private. Si elige este ámbito, sólo se podrá acceder a ese Procedimiento desde el Formulario o Módulo
donde se haya insertado.
La caja de opción (Check) que pone Todas las variables locales como estáticas nos va a poner todas
las variables declaradas dentro del procedimiento como estáticas (No ponen a cero o nulo su valor
cuando salimos y volvemos a entrar en ese procedimiento). Puede ahorrarnos un poco de código.
El código de los Procedimientos se guarda en el General del Formulario o Módulo donde se han
insertado :
Para llamar a un procedimiento desde cualquier parte del código basta con escribir en una línea el
nombre del procedimiento.
fpublico
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 258
Muchos programadores anteponen la palabra Call
Call fpublico
No hace falta poner Call, aunque Visual Basic lo admite. Algunos programadores me dicen que al poner
Call, siempre se enteran mejor de que están llamando a un procedimiento. Me parece muy bien, y creo
que es una buena razón. Pero no existe otra razón para ello.
Los datos que se puedan generar en un procedimiento debe extraerlos de ese procedimiento mediante
variables. Verá que con las funciones es distinto.
Cuando se llama a un procedimiento, se lleva a ese procedimiento la condición de tratamiento de errores
que existe en el procedimiento desde el que se llamó. Por ejemplo:
Private Sub Boton1_Click()
On Error GoTo RutErr
Lineas de código de este procedimiento
‘Llamada al Procedimiento Calcula_Dietas
Calcula_Dietas
Mas líneas de código de este procedimiento
RutErr:
End Sub
Si al ejecutarse el procedimiento Calcula_Dietas ocurre un error, al detectarse ese error interceptable, el
programa salta a ejecutar la línea RutErr del procedimiento Boton1_Click.
Esto puede producirse serios problemas a la hora de depurar su programa. Para evitar que suceda eso,
y que se pare la ejecución del programa en la línea del procedimiento Calcula_Dietas en la que se
produjo el error, inicie este procedimiento con una instrucción que anule la condición de tratamiento de
errores:
Public Sub Calcula_Dietas()
On Error Goto 0
…………….
Ens Sub
Funciones
Una función es una forma especial de realizar un procedimiento. En realidad es un procedimiento al que
le pasamos una o varios parámetros con los que realizará una operación (cualquier operación, no tiene
porqué ser matemática) y obtendrá un resultado de esos parámetros. Este resultado puede leerse desde
otra parte de la aplicación en una variable que tienen el mismo nombre que la función. La forma de
obtener los datos de la función es llamar directamente a esa función, como verá un poco más adelante.
Para insertar una Función se procede de igual forma que para un Procedimiento, pero marcando el
botón de opción Tipo Función en la caja de diálogo de la figura anterior.
El ámbito de una Función es el mismo que el un Procedimiento. Si se declara Pública puede usarse en
toda la aplicación. Si se declara Privada, solamente en el Formulario o Módulo donde se haya insertado.
Para llamar a una Función son válidos igualmente los criterios expuestos para los Procedimientos en
cuanto a la sentencia Call.
Parámetros de una Función
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 259
Se dijo anteriormente que a una Función se le pasan uno o varios parámetros con los que va a realizar
alguna operación. Al declarar la Función, hay que decirle el nombre de los parámetros que se le van a
pasar, de que tipo son (String, Integer, Boolean, ...) y cómo se le van a pasar (ByVal, ByRef,
ParamArray). Esto hay que introducírselo en la propia declaración
Public Function MiFuncion(ByVal Variable1 as String, ByVal Variable2 as Integer)
End Function
La función MiFuncion sabe que debe recibir dos parámetros, y que el primero será una cadena de
caracteres y el segundo un integer. Los nombres Variable1 y Variable2 son los nombres que usa la
Función internamente. No tienen porqué coincidir con los nombres que tengan las variables que
contienen esos valores en otras partes del programa.
Una función siempre da un resultado. Este resultado se le introduce en una variable que tiene el mismo
nombre que la función. Esta variable no hace falta declararla, ya que la declaración de la función lleva
implícito que exista una variable con ese nombre.
Imaginemos que lo que va a hacer la función de este ejemplo es tomar una cadena de caracteres
(Variable1) y obtener de ella otra cadena con los caracteres iniciales de la primera, tantos caracteres
como nos indique la segunda variable (Variable2)
Si, por ejemplo, le pasásemos los valores :
Variable1 = Guía del Estudiante
Variable2 = 14
Obtendríamos como resultado la cadena
Guía del Estud
Ya se habrá dado cuenta de que debemos emplear Left para obtener los caracteres iniciales de una
cadena. Nuestra función quedará de la forma :
Public Function MiFuncion(ByVal Variable1 as String, ByVal Variable2 as Integer) As String
MiFuncion =Left (Variable1, Variable2)
End Function
(Observe que hemos añadido la expresión As String al final de la declaración. Esto quiere significa que le
estamos diciendo a la función que su resultado es un String,)
Donde MiFuncion es una variable que se ve en todo el ámbito de la función. Para llamar a la función,
basta con citarla por su nombre y ponerle los parámetros necesarios. Cuando esté tecleando el código,
Visual Basic le invitará a introducir los parámetros citándole su nombre. (En nuestro ejemplo, ByVal
Variable1 as String, ByVal Variable2 as Integer
En cualquier parte del programa podemos poner :
Label1.Caption = MiFuncion (Guía del Estudiante, 14)
y Label1 tomará como Caption la cadena Guía del Estud
Pruebe esto con una pequeña aplicación. En un formulario, ponga un TextBox (Text1) donde va a
introducir la cadena original, otro TextBox donde va a introducir el número de caracteres a tomar, y un
Label (Label1) donde va a ver el resultado. Ponga un Botón de comando (Command1) donde llamará a
la función. Inserte una función (MiFuncion) en ese formulario :
Private Sub Command1_Click()
Label1.Caption = MiFuncion(Text1.Text, Val(Text2.Text))
End Sub
Public Function MiFuncion(ByVal Variable1 As String, ByVal Variable2 As Integer) As String
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 260
MiFuncion = Left(Variable1, Variable2)
End Function
Puede pensar que para hacer esta cosa tan elemental no merece la pena hacer una función.
Efectivamente. Bastaría con poner en el botón Command1_Click el siguiente código :
Label1.Caption = Left(Text1.Text, Val(Text2.Text))
y funcionaría igual. Lógicamente, una función debe introducirse cuando vaya a realizar un código un
poco mas complejo, y sobre todo, cuando se va a repetir en muchos procedimientos.
Hemos visto que los parámetros de la función pueden pasarse Por Valor (ByVal), caso del ejemplo
anterior, y Por Referencia (ByRef). ¿Cuál es la diferencia ? La diferencia es que si le pasa un valor por
valor (ByVal) ese valor, aunque lo cambie la función internamente, ese cambio no se manifiesta fuera de
ella. Si se pasa por referencia (ByRef), y la función cambia el valor de esa variable, ese cambio se
mantiene fuera de la función.
Veamos esto de una forma muy sencilla : Vamos a hacer una función que multiplica dos números. Pero
dentro de la función vamos a cambiar uno de esos números, sumándole 2. Una vez realizada la
operación presentamos el valor de los dos factores en dos Label a ver si ha cambiado. Insertemos dos
funciones, MultiplicaA y MultiplicaB. En MultiplicaA le introducimos los datos Por Valor y en MultiplicaB
por Referencia.
Public Function MultiplicaA(ByVal X1 As Integer, ByVal X2 As Integer) As Integer
x1 = x1 + 2
MultiplicaA = x1 * x2
End Function
Public Function MultiplicaB(ByRef X1 As Integer, ByRef X2 As Integer) As Integer
x1 = x1 + 2
MultiplicaB = x1 * x2
End Function
Las dos funciones son idénticas, excepto en la forma de pasarle los parámetros. Pongamos un Botón de
Comando para multiplicarlo con MultiplicaA y otro con MultiplicaB. Al final del procedimiento click de cada
uno de ellos presentamos las dos variables que se pasan a la función en sendos Label. Cuando se usa
MultiplicaA el valor de X1 (pepe en el CommandButton) se mantiene. En MultiplicaB cambia al valor
pepe+2
Private Sub Command1_Click()
Dim pepe As Integer
Dim juan As Integer
pepe = Val(Text1)
juan = Val(Text2)
Label1 = MultiplicaA(pepe, juan)
Label2 = pepe
Label3 = juan
End Sub
Tras esto, se pone en Lable2 el valor pepe
Private Sub Command2_Click()
Dim pepe As Integer
Dim juan As Integer
pepe = Val(Text1)
juan = Val(Text2)
Label1 = MultiplicaB(pepe, juan)
Label2 = pepe
Label3 = juan
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 261
Tras esto, se pone en Label2 el valor pepe + 2 (se mantienen el cambio realizado en la función
MultiplicaB
x1 = x1 + 2
No queda ahí la cosa. Un valor puede pasarse también por ParamArray. En principio parece que esto ya
es para nota. No es para tanto.
Vamos a ver que sucede cuando queremos realizar una suma. La suma de los importes de varios
productos de un ticket de compra. En principio no sabemos cuantos productos va a comprar un cliente,
por lo tanto no sabemos a priori cuantos parámetros le tenemos que pasar. Para pode pasar un número
indeterminado de parámetros se los pasamos como PamArray :
Public Sub sumacifras(ParamArray cifra())
Dim I As Integer
Dim suma As Integer
For I = LBound(cifra) To UBound(cifra)
suma = suma + CInt(cifra(I))
Next I
Label1.Caption = suma
End Sub
Private Sub Command2_Click()
sumacifras 1, 2, 3, 4, 5, 6, 7, 8
End Sub
Este código nos suma las cifras 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
La variable que se pasa con ParamArray debe ser Variant
Existe otra forma de pasar parámetros : Optional
Cuando se declara una función con un determinado número de parámetros, es necesario pasárselos
todos. Si no se hace así, VB nos dará un error. Pero puede que algún parámetro no exista siempre.
Cuando uno o varios de los parámetros que se pasan a una función son opcionales, se le pueden pasar
como Optional.
Se pueden pasar uno o mas parámetros como Optional. Las condiciones para
opcionales es que ocupen los últimos lugares y que sean del tipo Variant
los parámetros
Hagamos un ejemplo en el que vamos a poner en un TextBox (TB4) el nombre y apellidos de una
persona. El segundo apellido se lo pasamos como Opcional. La declaración de la función será :
Public Function SUMANOMBRES(NOMBRE As String, APE1 As String, Optional APE2 _
As Variant)
‘ Debemos detectar si se le ha pasado el parámetro opcional. Usamos para ello IsMissing
If IsMissing (APE2) Then
TB4.Text = NOMBRE & " " & APE1
Else
TB4.Text = NOMBRE & " " & APE1 & " " & APE2
End If
End Function
Los parámetros los tomamos de tres TextBox (TB1, TB2 y TB3, siendo este último el que es opcional. En
un botón de comando ponemos este código :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 262
Private Sub Command1_Click()
If TB3 <> "" Then
SUMANOMBRES TB1, TB2, TB3
Else
SUMANOMBRES TB1, TB2
End If
End Sub
Salir de una función
La forma natural de salir de una función es cuando se ejecuta todo su código. Al final siempre tiene la
sentencia End Function
Se puede salir de una función antes de que termine. Por ejemplo, si se cumple una determinada
condición, se puede salir de la función mediante la sentencia Exit Function
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 263
CORRECCION DE ERRORES Y DEPURACION DE PROGRAMAS
EL OBJETO ERROR
Una vez que conocemos gran parte del Visual Basic, y que seguramente habremos hecho alguna
aplicación, es momento de pararnos en una de las cosas que un programador nunca debe olvidar: Un
programa no solo debe funcionar, sino que debe funcionar bien.
Parece que esta afirmación carece de sentido o que al menos es una afirmación gratuita. Sin embargo
es un defecto muy común entre programadores noveles, quizás por la alegría que da el trabajo
terminado, olvidarse de algo tan fundamental como la calidad del programa, y perder por ello la alegría
que da el trabajo bien hecho.
Cuando terminamos un programa, lo normal es que no funcione bien. Mucho antes de terminarlo ya
habremos tenido la sorpresa de que Visual Basic ha detectado un error y detiene la ejecución del
programa. Iremos corrigiendo los errores elementales que van apareciendo, errores de sintaxis, ficheros
que ya estaban abiertos, End If que nos faltaban, etc. Y el programa parece que ya puede funcionar
hasta el final. El programa debe entrar entonces en la fase de corrección de errores y optimización.
Corrección de Errores.
Denominamos Corrección de errores al proceso de la programación en la que se analizan y corrigen los
errores existentes en el código o en el funcionamiento del programa.
Podemos por tanto dividir los errores en errores de código y errores de funcionamiento.
Es un error de código, por ejemplo, la siguiente línea de programa:
Open A:\MiFicher.Txt For Input as #1
Habrá notado el error de bulto consistente en que A:\MiFicher.Txt debe ir entre comillas dobles. Este tipo
de error se detecta generalmente al ejecutar el código. En este caso, Visual Basic nos dará el mensaje
de error “Error de Sintaxis” nada mas terminar de escribir la línea. Errores como este, o el típico If sin
End If seguro que se los ha encontrado repetidas veces y no vamos a ahondar mas en ellos. Se corrige
el error sintáctico en el momento y el problema queda resuelto. Pero volvamos a la línea de código
anterior, esta vez ya bien escrita:
Open “A:\MiFicher.Txt” For Input as #1
Al estar escrita correctamente, esta línea no nos puede dar error de sintaxis. Pero, ¿Que ocurre cuando
estamos ejecutando el programa que contiene esa línea, y en el momento de ejecutarla no tenemos
metido un disquete en la unidad A:? O piense lo que ocurriría si tenemos un disquete en A:, pero no
existe en él el fichero MiFicher.Txt. No existe ningún error de sintaxis. El programa puede funcionar
correctamente si, en el momento de la ejecución de esa línea, tenemos un disco en la unidad A: y éste
contiene un fichero llamado MiFicher.Txt. Sin embargo no puede funcionar si no tenemos metido el
disquete, o si este no tiene el mencionado fichero.
En cualquiera de estos dos últimos casos se produce un Error de Ejecución.
Existen dos tipos de errores de ejecución: Errores Interceptables y Errores que no se pueden
interceptar.
Los errores interceptables son aquellos que Visual Basic conoce. Los dos errores anteriores son de este
tipo. Son errores no interceptables, aquellos que Visual Basic no puede detectar. No porque no los
conozca, sino porque el propio error deja sin trabajar a Visual Basic o incluso al sistema operativo.
Afortunadamente el sistema operativo está muy protegido, pero no por ello dejan de ocurrir estos
errores. ¿Recuerda la frase “El programa xxx ha causado un error de protección general en el Módulo.....
“ Bueno, acaba de producir un error No Interceptable.
No solamente existen estos errores, también hay errores no catalogados y aplicables solamente al
programador. Piense en un bucle infinito. Un bucle infinito es una secuencia de instrucciones tal como:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 264
Do While n < 2000
n=n+1
If n = 1000 then n = 0
Loop
Podrá advertir que este bucle no se termina nunca, ya que n no podrá alcanzar nunca el valor 2000 ya
que cada vez que llega a 1000 le cambiamos su valor a 0. Este tipo de error, más normal de lo que
parece, ni lo detecta VB ni produce una caída del sistema operativo. Sin embargo es un error, pero en
este caso será el propio programador quien se tenga que dar cuenta de él, ya que VB no puede
ayudarnos debido a que el código, línea a línea, está perfectamente escrito.
Vemos por tanto que VB solamente nos ayudará en los errores de sintaxis, durante el tiempo de diseño,
y los errores interceptables en tiempo de ejecución.
Errores Interceptables.
Veamos lo que dice la ayuda de VB para este tema:
Los errores interceptables pueden producirse cu and o está ejecut ando un a aplicaci ón , tanto en el
entorno de Visual Basic como en modo autónomo. Algunos de estos errores pueden ocurrir también en
ti em po de di se ñ
o o en durante la compilación .
Un error interceptable es, como decíamos anteriormente, un error que Visual Basic conoce. Para
conocerlos, VB dispone de un objeto que vamos a ver a continuación. El Objeto Error
Objeto Error
Contiene información sobre errores en tiempo de ejecución.
El Objeto Error tiene Propiedades y Métodos. Las propiedades del objeto Error las establece quien
genera el error. Por ejemplo, si el error se genera durante la ejecución, será VB quien genera las
propiedades del objeto Error. Pero puede ser también el programador quien genere el error. Lo veremos
mas adelante
Al objeto Error se le designa por Err
Las propiedades del Objeto Error son:
Description, HelpContext, HelpFile, LastDLLError, Number, Source
Propiedad Description
Devuelve o establece una cadena descriptiva asociada a un error.
Sintaxis
Variable = Err.Description
Err.Description = Cadena descriptiva del error
Veremos un ejemplo mas adelante.
Propiedad HelpContext
Devuelve o establece el identificador de contexto de un tema para un archivo de Ayuda de Microsoft
Windows.
Sintaxis
LSB
Err.HelpContext [= id_contexto]
Visual Basic – Guía del Estudiante
Capítulo 1
Página 265
Variable = Err.HelpContext
Esta propiedad y la siguiente le permiten presentar automáticamente la ayuda cuando se produce un
error.
Propiedad HelpFile
Devuelve o establece la ruta completa del archivo de Ayuda de Microsoft Windows que debe mostrarse
al producirse el error.
Sintaxis
Err.HelpFile = “C:\MiCarpeta\MiFicherodeAyuda.Hlp”
También puede leer el valor de esta propiedad:
Variable = Err.HelpFile
Cuando se especifica un archivo de Ayuda de Microsoft Windows en HelpFile, se le llama
automáticamente cuando el usuario presiona el botón Ayuda (o la tecla F1) del cuadro de diálogo del
mensaje de error. Si la propiedad HelpContext contiene un identificador de contexto válido para el
archivo especificado, se mostrará automáticamente el tema correspondiente. Si no se especifica nada en
HelpFile, aparecerá el archivo de Ayuda completo.
Propiedad LastDLLError
Devuelve un código de error de sistema producido por una llamada a una biblioteca de vínculos
dinámicos (DLL). Esto ocurre cuando falla la ejecución de una función API.
Propiedad Number
Esta es la propiedad mas importante del Objeto Error. Por ello es la propiedad predeterminada. Permite
conocer el número del error producido. También nos permite establecer el número de error, cuando nos
interesa provocar un error mediante código, con el método Raise
¡¡¡ Number es una variable tipo Long !!!
Sintaxis
Variable = Err.Number
Al ser la propiedad predeterminada, no es necesario poner Number. La siguiente línea es
operativamente igual a la anterior:
Variable = Err
Source
Devuelve o establece el nombre del objeto o aplicación que ha generado el error originariamente.
Sintaxis
Variable = Err.Source
Err.Source = expresión_cadena
Vea en la ayuda de VB la explicación (muy ilustrativa) de esta propiedad.
El Objeto Error tiene solamente dos métodos:
Método Clear
Borra los valores de todas las propiedades del objeto Err.
Sintaxis
LSB
Err.Clear
Visual Basic – Guía del Estudiante
Capítulo 1
Página 266
Puede utilizar Clear para borrar explícitamente el objeto Err una vez que se ha tratado un error. Visual
Basic llama al método Clear automáticamente siempre que se ejecuta alguna de las instrucciones
siguientes:
Cualquier tipo de instrucción Resume
Exit Sub, Exit Function, Exit Property
Cualquier instrucción On Error
De aquí se desprende que un error no “sale” del procedimiento en el que se generó. Para salir de un
procedimiento el programa debe pasar necesariamente por una instrucción Exit Sub. En ese momento,
desaparecen todas las propiedades del Objeto Error.
Método Raise
Genera un error en tiempo de ejecución.
Sintaxis
Err.Raise(Número, Origen, Descripción, ArchivoAyuda, ContextAyuda)
Los argumentos de Raise se describen a continuación.
Número Requerido. Entero de tipo Long que identifica la naturaleza del error.
Origen Opcional. Expresión de cadena que indica el objeto o aplicación que ha generado
originariamente el error.
Descripción Opcional. Expresión de cadena que describe el error.
ArchivoAyuda Opcional. Ruta del archivo de Ayuda de Microsoft Windows en el que se encuentra la
información sobre el error.
ContextoAyuda Opcional. Identificador de contexto que especifica el tema del archivo indicado en
ArchivoAyuda que contiene la información de ayuda del error.
Todos los argumentos son opcionales, excepto Número. Sin embargo, si utiliza Raise sin especificar
algunos argumentos, y si los valores de las propiedades del objeto Err no se han borrado, tales valores
se conservarán para el error actual.
Decíamos al principio del Objeto Error que sus propiedades las establece quien las generó. Con el
Método Raise se genera un error. Y vea que se pueden establecer sus propiedades.
Control de los errores
Ya sabemos que herramienta usa Visual Basic para detectar errores. Vamos a ver ahora como usarla.
Pero veamos previamente lo que es en Visual Basic una Rutina. No se extrañe si alguien le llama Label
o Etiqueta. En otros lenguajes se llama así, incluso en Q-Basic, donde no existían los controles Visual
Basic llamados etiquetas, se usaba esta denominación. En Visual Basic no podemos usarla, para no
confundirla con el control.
Una Rutina es un trozo de código escrito en un procedimiento, que tiene un nombre. El nombre de la
Rutina puede ser cualquiera, y debe terminar con el carácter dos puntos (:) Por ejemplo:
RutinaErrores:
El nombre de la rutina debe ocupar él solo una línea. Se accede directamente a la rutina cuando citamos
su nombre en el código del procedimiento donde está la Rutina.
Para citarla, debemos usar ese nombre, quitando el carácter dos puntos final. Podemos llamarla
mediante la sentencia GoTo. Veamos un pequeño ejemplo. Es un botón de comando, y un TextBox. Si
el TextBox (Text1) mantiene su texto original (Text1) hacemos que el programa pase por la rutina. Si lo
hemos variado, hacemos que no pase:
Private Sub Command1_Click()
If Text1 = "Text1" Then
GoTo Rutina
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 267
Else
MsgBox "No pasa por la Rutina"
End If
Exit Sub
Rutina:
MsgBox "Sí pasó por la Rutina"
End Sub
La rutina es en realidad un trozo de código del procedimiento que se ejecutará, bien porque hayamos
dirigido allí la ejecución del programa (mediante GoTo) o bien porque el programa pase por la rutina al
ejecutarse. Observe el Exit Sub que tiene en la línea inmediatamente anterior a la Rutina. Si no lo
ponemos, el programa pasará por la rutina una vez ejecutada la sentencia condicional If - Else - End
If, igual que si se tratase de cualquier otra parte del programa. Para evitar que pase por ella, ponemos
ese Exit Sub que hará que el programa salga del procedimiento sin llegar al final.
En el ejemplo anterior, la condición para que pasase por la rutina era que se cumpliese una determinada
condición en Text1. Para que pase por una rutina, al darse la condición de que ha ocurrido un error,
usaremos la instrucción On Error GoTo
Importante. Cuidado con GoTo
Hay un dicho entre los programadores de Visual Basic. Los programadores se dividen en tres grupos.
Los que nunca usan GoTo. Los que usan GoTo sin saber usarla y los que usan GoTo sabiendo usarla,
pero dicen que de estos últimos hay muy pocos.
Instrucción On Error GoTo
Activa una rutina de tratamiento de errores y especifica la ubicación de la misma en un procedimiento.
También puede utilizarse para desactivar una rutina de tratamiento de errores.
Sintaxis
On Error GoTo Rutina
On Error Resume Next
On Error GoTo 0
‘Va a la Rutina especificada
‘Pasa del error y continúa en la línea siguiente a
‘la que provocó el error
‘Desactiva todo el tratamiento de errores que
‘haya activado en el procedimiento actual.
Veamos el ejemplo anterior, con la instrucción On error GoTo.
Private Sub Command1_Click()
On Error Resume Next
‘Con la línea anterior le decimos que se olvide del error y siga en la línea siguiente
‘a la que provocó el error
If Text1 = "Text1" Then
GoTo Rutina
Else
On Error GoTo 0
‘La línea anterior desactiva el tratamiento de errores generado en la línea segunda (On
‘Error Resume Next). Pruebe a quitar y poner esta línea (On error GoTo 0)
Err.Raise 53
‘En la línea anterior generamos “artificialmente” el error 53
MsgBox "No pasa por la Rutina"
Exit Sub
End If
Rutina:
MsgBox "Sí pasó por la Rutina"
End Sub
Cuando insertamos la línea On Error GoTo Rutina, el programa sabe que nada mas producirse un
error, debe ir a la rutina señalada. En esa rutina tomaremos las medidas adecuadas para que se
subsane el error producido. Así por ejemplo, si en una línea le decimos al programa que vaya a leer un
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 268
fichero de la unidad A:, puede ocurrir que la unidad no tenga metido el disco. O que lo tenga metido pero
que no exista el fichero en ese disco.
La rutina de corrección de errores debe contemplar cada uno de esos dos casos, y actuar de forma
distinta en uno y en otro.
Hagamos un ejemplo donde al pulsar un botón (Command2) se busca el fichero Mificher.Txt en el disco
A: y el contenido de ese fichero se coloca en Label1
Private Sub Command2_Click()
Dim Variable As String
Open "A:\Mificher.Txt" For Input As #1
Line Input #1, Variable
label1.Caption = Variable
Close #1
End Sub
Si no está metido el disco en la unidad A nos dará el siguiente error:
Se ha producido el Error ‘71’ de tiempo de ejecución. El disco no está listo
Si estuviese metido el disco, pero no tuviera un fichero llamado Mificher.Txt, daría este error:
Se ha producido el Error ‘53’ de tiempo de ejecución. No se ha encontrado el archivo
En realidad estos errores no son de programa, sino de una utilización incorrecta del programa, ya que
debería estar metido el disco, y que contuviese un fichero llamado Mificher.Txt. Pero en programación
hay que prever estas eventualidades. Y lo lógico sería poner un aviso diciéndole al usuario que la unidad
A: no está preparada (caso 1) o que el disco no contiene el fichero buscado (caso 2)
Instrucción Resume
Hemos visto en el apartado anterior la sentencia On Error Resume Next, de la que decíamos que
“pasaba” del error y continúa en la línea siguiente a la que provocó el error. Es así ya que la Instrucción
Resume hace desaparecer el error mediante código (Pone Err.Numbber = 0). Si le añadimos Next el
programa sigue ejecutándose en la línea siguiente a la que generó el error.
La Instrucción Resume puede tener las siguientes sintaxis:
Sintaxis
Resume [0]
Resume Next
Resume Rutina
Resume [0] Si el error se ha producido en el procedimiento que contiene el controlador de errores, la
ejecución continúa con la instrucción que lo causó.
Puede ocurrir que el error no se haya producido en el mismo procedimiento que contiene la rutina de
tratamiento de errores, sino en otro al que se le ha llamado desde este. En este caso, la ejecución
continúa en la instrucción del procedimiento que contiene la rutina de tratamiento de errores desde la
que se llamó a otro procedimiento.
Resume Next Si el error se ha producido en el procedimiento que contiene el controlador de errores, la
ejecución continúa con la instrucción inmediatamente posterior a la que lo causó. Si el error se ha
producido en un procedimiento llamado, la ejecución continúa en la instrucción del procedimiento que
contiene la rutina de tratamiento de errores (o la instrucción On Error Resume Next) inmediatamente
posterior a aquélla desde la que se llamó a otro procedimiento.
Resume Rutina La ejecución continúa en la rutina citada en la instrucción. La rutina debe encontrarse
en el mismo procedimiento que el controlador de errores.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 269
Ya que conocemos las instrucciones On Error GoTo y Resume, veamos en el ejemplo anterior como
resolvemos el problema de que no exista disco en la unidad A: o que en el disco no exista el fichero
buscado:
EJEMPLO
Activemos la detección de errores e introduzcamos una rutina que detecte el error ocurrido y que haga
lo que tenga que hacer en cada caso:
Private Sub Command2_Click()
On Error GoTo RutinaErrores
Dim Variable As String
Open "A:\Mificher.Txt" For Input As #1
Line Input #1, Variable
Label1.Caption = Variable
Close #1
RutinaErrores:
If Err.Number = 71 Then
‘No hace falta poner Err.Number. Basta con Err
MsgBox "La Unidad A no tiene ningún disco. Introduzca uno"
‘Al poner Resume (sin mas) el programa seguirá ejecutándose
Resume
‘en la misma línea que provocó el error. Como hemos
‘intercalado un MsgBox, que lleva implícita una espera a que se
‘le haga click en su botón, durante esa espera el usuario puede
‘cambiar el disco y al reiniciarse el programa en esa línea, ya
‘puede tener un disco para que no se repita el error.
End If
‘Aquí hemos puesto solamente Err
If Err = 53 Then
MsgBox "El disco A no tiene ningún fichero llamado Mificher.Txt. Ponga el disco correcto"
Resume
End If
End Sub
Ventana de Depuración. El Objeto Debug
Es momento ahora de hablar de la ventana de depuración. Esta ventana permite que Visual Basic se
comunique con nosotros en tiempo de ejecución. Es la ventana de Debug. No está presente
normalmente en la pantalla, pero se presenta haciendo click en Ver | Ventana de Depuración de la barra
de menú de Visual Basic. En esta ventana se presenta lo que escribamos en un objeto preparado para
ayudarnos en la corrección de errores, que se llama precisamente Objeto Debug:
Este objeto no tiene propiedades y tiene solamente un método: el Método Print
En esta ventana podemos presentar otro tipo de datos, por ejemplo el valor de una variable en un
determinado momento:
Debug.Print MiVariable
Veremos en el ejemplo de este capítulo una aplicación de la ventana de depuración que le dejará claras
las ideas.
Si queremos que cuando se produzca un error se nos presente en esa ventana, basta con insertar esta
línea de código en la Rutina de Error:
Debug.Print Err.Number
Debug.Print Err
o simplemente
Hemos visto la forma de detectar un error y tomar las medidas oportunas para que el programa siga
funcionando. Aquí lo hemos hecho solicitándole una operación al usuario. En otros casos nos interesará
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 270
que el programa “pase” del error, en otras que repita un pr ocedimiento... El programador deberá ver en
cada caso la respuesta que debe dar el programa a un determinado error.
Un programa perfecto es aquel que contempla todas las posibilidades de error y les da solución a todas.
Esto quiere decir, que un programa debería tener en cada procedimiento una llamada a la detección de
errores (On error GoTo ... ) y una rutina de corrección. El trabajo es grande. La recompensa también.
Pero un error muy común entre programadores es autocomprobar sus errores. Realiza un programa y
comienza a ejecutarlo intentando descubrir los errores en los que puede caer. Le recomiendo que esa
labor la realice un compañero. La persona que realizó el programa sabe perfectamente lo que debe
hacer. Y aún queriendo, le cuesta mucho trabajo cometer errores. Una persona que nunca haya
trabajado con el programa, lo que le cuesta trabajo es no cometerlos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 271
LA AYUDA DE WINDOWS
NOTA sobre las ayudas de los programas Windows
Hasta ahora era normal presentar las ayudas en el formato cásico de fichero .Hlp. Sin embargo, dado el
auge que ha tomado el formato Html (sobre todo desde que Microsoft lo incluyó como una parte más de
Windows), actualmente se está usando más el formato .Html que el .Hlp. Las razones son bastante
obvias. La edición de un fichero Html es mucho mas sencilla que la de un Hlp (Y si no se lo cree, léase
este capítulo) Pese a todo, se sigue incluyendo este tema, ya que el formato Hlp sigue siendo actual.
Eso sí, este capítulo no se ha actualizado, y cuando se habla del HC.Exe deberíamos estar hablando del
HelpWorkShop (HWC.Exe), un programa que funciona en Windows, y para el que es aplicable todo lo
descrito aque de los fichero .Hpj.
Toda aplicación bien terminada debe tener una ayuda. Cualquier aplicación realizada en Visual Basic
puede tenerla, usando para ello los recursos que brida Windows.
La presentación de la ayuda podría hacerse mediante un formulario, donde se presentan distintos
ficheros según las necesidades del usuario. Sin embargo esta forma de presentar la ayuda nunca llegará
a ser tan completa como la que brinda Windows, y el trabajo a desarrollar para igualar la presentación de
Windows sería laborioso. Solución : utilizar los recursos de Windows.
El recurso de Windows es un programa capaz de presentar ficheros de ayuda. Estos ficheros son un
poco especiales y solamente se pueden presentar mediante ese presentador de ficheros de ayuda. Ese
es el programa WinHelp.Exe para las versiones de 16 bits y las primeras versiones de Windows 95, y el
WinHlp32.Exe para Windows 98 y Windows NT4. Como en todas las aplicaciones de Microsoft (MS)
tienen compatibilidad hacia arriba. Por lo tanto no se extrañe que una ayuda que le abre perfectamente
el WinHlp32.Exe, si la pretende abrir con el WinHelp.exe (que es más antiguo) le diga que no se trata de
un fichero de ayuda.
Windows dispone de otra utilidad, el programa HC.EXE (Help Compiler) que puede adaptar el fichero
.RTF donde escribirá la ayuda, a un formato capaz de ser interpretado por el WINHELP.EXE Lo vamos
viendo todo paso a paso.
Antes de comenzar a explicar como se realiza una ayuda Windows vamos a comentar el formato de
archivos RTF. Este formato posiblemente le sea familiar debido a que el control RichTextBox puede
guardar y leer ficheros en ese formato. Las siglas RTF vienen precisamente de Rich Text Format, en
castellano, Formato de Texto Enriquecido.
Cuando se edita un texto mediante un procesador de textos, el fichero resultante se guarda don un
formato distinto para cada procesador. De esta forma, un texto editado en WP no es compatible con el
P.T. AmiPro, con Word o con cualquier otro. Los fabricantes de estos procesadores de textos han tenido
que incluir una herramienta capaz de convertir un formato a otro para poder alcanzar la compatibilidad
entre ellos que el mercado exigía.
El Formato de Texto Enriquecido pretende ser un nexo de unión entre todos los procesadores de texto,
para poder intercambiar ficheros editados en uno u otro. De hecho, las últimas versiones de los mas
importantes procesadores de textos incluyen la posibilidad de guardar y buscar el texto en este formato.
(WP, Word)
Este formato consiste en guardar mediante caracteres ASCII plenamente legibles tanto el texto escrito
como los tipos de letra, tamaño, saltos de carro, etc. Veamos un ejemplo comparativo del mismo texto
escrito en Word, guardado en RTF y en ASCII :
Texto1
Este texto está escrito en Word. Observe que podemos poner letra negrita, letra cursiva, letra
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el tamaño de las
letras a tamaño mas grande, mas pequeño, etc.
Fin Texto 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 272
El mismo texto en ASCII puro :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva, letra
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el tamaño de las
letras a tamaño mas grande, mas pequeño, etc.
Fin Texto 1
Y ahora el mismo texto en formato RTF. En este formato hubo que seccionar las líneas para poder
mostrarlas en una hoja, ya que RTF utiliza líneas sin retornos de carro. Se han seccionado las líneas
terminándolas con un guión bajo y comenzando en la línea siguiente también con un guión bajo.
{\rtf1\ansi \deff5\deflang1033{\fonttbl{\f5\fswiss\fcharset0\fprq2 Arial;}}_
_{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;_
_\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\_
_green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\_
blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue_
_192;}{\stylesheet{\widctlpar
\f5\fs20\lang1034 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}_
_}{\info{\author LUIS SUAREZ BERNALDO}{\operator LUIS SUAREZ BERNALDO}_
_{\creatim\yr1997\mo3\dy9\hr11\min8}{\revtim\yr1997\mo3\dy9\hr11\min9}_
_{\version1}{\edmins1}{\nofpages1}
{\nofwords38}{\nofchars220}{\*\company }{\vern57431}}\margl1701\margr1701\_
_margt1417\margb1417 \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\formshade_
_ \fet0\sectd \linex0\headery709\footery709\colsx709\endnhere {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstar_
_t1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\_
_pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcl_
_tr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\_
_pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pn_
_start1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{_
_\pntxtb (}{\pntxta )}}\pard\plain \qj\widctlpar \f5\fs20\lang1034 Texto1
\par
\par Este texto est\'e1 escrito en Word. Observe que podemos poner letra _
_{\b negrita}, letra {\i cursiva}, letra {\ul subrayada}. Podemos cambiar_
_ el color de las letras, {\cf6 rojo}, {\cf4 verde}, {\cf2 azul}. Podemos _
_cambiar el tama\'f1o de las letras a {
\fs24 tama\'f1o mas grande}, {\fs16 mas peque\'f1o}, etc.
\par
\par
\par Fin Texto 1
\par \pard \widctlpar
\par }
Como puede observar, el RTF incluye el texto escrito casi en ASCII, pero añadiendo una serie de datos
respecto al tipo de letra, codifica los acentos, las eñes, y hasta incluye, tomándolo del ordenador, el
nombre del operador que lo ha escrito. Estas informaciones también se guardan cuando se archiva un
texto en el formato propio del procesador de textos, pero lo hace en binario, por lo que no lo podemos
visualizar. El formato RTF, dentro de que mete toda esa información adicional, lo archiva con caracteres
ASCII.
La utilidad que tiene Windows para presentar las ayudas utiliza precisamente este formato RTF. Por ello,
debemos disponer de un procesador de textos que pueda guardar el texto escrito en este formato.
(Word, WP5, WP6 y otros) Los ejemplos de estos apuntes se han realizado en Word.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 273
Antes de decidirnos a escribir el fichero de ayuda debemos pensar muy bien lo que vamos a poner en él.
Pensemos ante todo a que personas va dirigida la aplicación, sus posibles conocimientos de informática
y de otros temas que estarán relacionados con la aplicación. Es decir, planifiquemos la ayuda antes de
comenzar a hacerla.
Para acceder a la ayuda, Windows ofrece la posibilidad de pulsar F1 . Nuestras aplicaciones deben
sacar la ayuda pulsando F1. Lo podrán hacer mediante otros procedimientos. Comencemos por lo mas
sencillo, una ayuda de una única página.
Escriba el texto de ayuda con Word y guárdelo en formato RTF, en cualquier directorio, pero
preferentemente en uno que no se mezcle con otros ficheros para poder localizarlo mejor. Cree si es
necesario un directorio exclusivo para la ayuda. Imaginemos que lo creamos y es el C :\DIRAYUDA,
donde guardamos el fichero de ayuda con el nombre AYUDA1.RTF
Este archivo no lo puede utilizar directamente el programa WINHELP.EXE. Hay que compilarlo. Para
ello utilizamos el compilador HC.EXE. Este compilador no es una herramienta Windows, por lo que
tendrá que ir al DOS y ejecutarlo. El programa HC.EXE se encuentra en el directorio C :\ ..... \VB\HC
Pero al compilador HC.EXE hay que suministrarle la información para que pueda trabajar. Esa
información se la damos en un fichero que le pasaremos como parámetro, que debe tener extensión
.HPJ y que meteremos en el mismo directorio donde tengamos el fichero de ayuda AYUDA1.RTF
Este fichero estará editado en ASCII puro. Puede editarlo con el EDIT de MS-DOS o con el Block de
Notas de Windows. Imaginemos que lo vamos a llamar FICHAYUD.HPJ y como se dijo, se meterá en el
mismo directorio donde está el fichero de ayuda. (C :\DIRAYUDA) El nombre que decida para este
fichero con extensión .HPJ será el que tenga el fichero de ayuda (Que se obtendrá de la compilación y
tendrá por extensión .HLP) Tendrá, de momento, dos líneas.
[FILES]
AYUDA1.RTF
Vayamos al directorio C :\ ...... \VB\HC (en MS-DOS) y tecleemos
HC C:\DIRAYUDA\ FICHAYUD.HPJ
La compilación no suele dar problemas sobre todo en un fichero de ayuda tan simple de una única
página. Al compilar, obtenemos un fichero con el mismo nombre que el fichero .HPJ y extensión .HLP,
(FICHAYUD.HLP en nuestro caso) que lo dejará en el directorio donde estuviera el programa HC.EXE.
(Posiblemente el C :\VB\HC) Debe moverlo a otro directorio donde no estorbe y lo podamos localizar sin
problemas. Movámoslo al C :\DIRAYUDA Vayamos a nuestra aplicación VB y abramos el menú de
Herramientas | Opciones para sacar el cuadro de Opciones. Vaya a la pestaña de Proyecto y busque el
directorio y nombre del fichero .HLP haciendo click sobre el cuadrado con tres puntos (...) que está a la
derecha del TextBox de Archivo de Ayuda. Se le abrirá un CommonDialog para buscarlo.
NOTA : Para evitar liarse con los director ios, es medida siempre pru dente llevarse el comp ilador
de ayudas HC.EXE al directorio don de tengamo s el fichero .RTF y el .HPJ.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 274
Haga click en Aceptar y ejecute la aplicación. Pulse F1. ¡SORPRESA ! Tenemos en pantalla la ventana
de ayuda de Windows con el fichero que habíamos escrito. F1 ha invocado a WINHELP.EXE y este
programa presentó el fichero de ayuda asociado con el proyecto.
Observe que el texto se adapta a las dimensiones de la ventana. Y si supera en vertical las dimensiones
de la ventana, aparecen barras de scroll verticales. Puede de esta forma recorrer todo el fichero de
ayuda.
Sin embargo este procedimiento no sería el mas indicado para una información de ayuda extensa.
Deberemos poner varias páginas. Si lo hacemos así, al pulsar F1 siempre aparecerá la página 1. Si
aparece siempre la página 1, pongamos en esta primera página el índice de temas, y en las páginas
sucesivas cada uno de los temas. Ya veremos como acceder a cada una de las páginas haciendo click
sobre la línea del índice que contiene el título del tema deseado. Tal y como lo hace con cualquier
aplicación Windows.
Volvamos al editor Word y abramos el fichero que habíamos creado de una página, y añádale mas
páginas introduciendo avances de página manuales (Se introducen con Control + Intro)
Imaginemos que tenemos esta configuración del fichero :
INDICE
1 - Introducción a la aplicación
2 - Acceso a la Base de Datos
3 - Introducción de datos
4 - Lectura de datos
- - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introducción a la Aplicación
Esta aplicación está realizada para . . . . . . . . . .
- - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Acceso a la Base de Datos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 275
Para abrir la Base de datos . . . . . . . . .
- - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introducción de datos
Para introducir datos . . . . . . . . . . . .
- - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Lectura de datos
Para leer los datos . . . . . . . . . . . . . . . .
Ya tenemos hecho un fichero de ayuda con varias páginas. No es suficiente esto, ya que WINHELP.EXE
, pulsando F1, solamente nos mostrará la página 1. Debemos hacer algo para, una vez en la página 1,
que nos estará mostrando el índice, poder acceder a cada una de las páginas haciendo click sobre la
línea del índice que contiene el tema de interés.
Para ello debemos poner un identificador a cada una de las páginas. Este identificador debe ser único,
es decir, no pueden existir dos páginas con el mismo identificador.
Para introducir un identificador en una página, una vez que tenga el fichero de ayuda terminado, sitúese
con el cursor al comienzo del título de la primera página (después del índice), justamente al lado de
Introducción a la Aplicación . Inserte en ese punto una Nota al pié (Abra el Menú Insertar | Nota al
Pié del Word) Le aparecerá esta ventana :
Introduzca una almohadilla (#) en el TextBox Marca personal. Haga click sobre Aceptar.
Le aparecerá en la parte inferior de la pantalla un cuadro para introducir el identificador de esa página.
Repita el proceso para todas las páginas insertándoles una Nota al pié a cada una. Al final obtendrá este
resultado :
INDICE
1 - Introducción a la aplicación
2 - Acceso a la Base de Datos
3 - Introducción de datos
4 - Lectura de datos
- - - - - - - - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - # Introducción a la Aplicación
Esta aplicación está realizada para . . . . . . . . . .
- - - -- - - -- - - -- - - -- - - -#
salto de página manual - - - - - - - - - - - - - - - - - - - - - - -
Introducción
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 276
#
Acceso a la Base de Datos
Para abrir la Base de datos . . . . . . . . .
- - - - - - - - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - # Introducción de datos
Para introducir datos . . . . . . . . . . . .
- -- -- -- -- -- -- -- -- -- # Lectura de datos
salto de página manual - - - - - - - - - - - - - - - - - - - - - - -
Para leer los datos . . . . . . . . . . . . . . . .
EN ESTA PARTE DE LA PAGINA VERA UNA SEPARACION QUE PONE, A LA IZQUIERDA
Todas las notas al pie
Introducción
Acceso
# Meterdatos
# Leerdatos
#
#
(Observe que estamos simulando la ventana de Word. Donde ve - - salto de página manual - entienda que estamos simulando lo que Vd. ve en la ventana real)
En la parte inferior puede ver los identificadores que se han asociado a cada página. ¿Qué podemos
hacer para asociar estos identificadores a las líneas correspondientes del índice ? Muy sencillo, y es el
siguiente paso que debe hacer :
Volvamos a la primera página del documento Word, donde tenemos el índice.
INDICE
1 - Introducción a la aplicación
2 - Acceso a la Base de Datos
3 - Introducción de datos
4 - Lectura de datos
Habrá observado en las aplicaciones Windows que para seleccionar un tema hay que poner el puntero
del ratón sobre la línea deseada, que está en color verde, y en ese momento el puntero se convierte en
una mano. En nuestra aplicación ocurrirá lo mismo. Seleccione todas las líneas que quiere asociar a
cada uno de los identificadores (Una a una o todas a la vez, dependiendo de como las tenga dispuestas),
y vaya al menú Formato | Fuentes . Le aparecerá el cuadro de diálogo. Vaya al TextBox Subrayado de
ese cuadro de diálogo y elija Doble.
#
Acceso
Meterdatos
# Leerdatos
#
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 277
Al ponerles doble subrayado, le aparecerán en la ayuda de color verde, y el puntero se le transformará
en una mano cuando lo ponga encima de una de esas líneas. Pero todavía queda asociarlas a cada uno
de los identificadores. Para ello tiene que llevar el puntero del ratón justamente al final de cada una de
las líneas. Al hacer click el puntero de escritura se coloca en ese punto. Tiene que escribir a continuación
de cada línea el nombre del identificador que corresponda. Pero lógicamente no querrá que se vea en la
pantalla de ayuda. Por lo tanto debe hacerlo invisible. Para escribir un texto invisible en Word hay que
pulsar las teclas Control + Mayúsculas + O. Pulse las tres al mismo tiempo y a continuación escriba el
nombre del identificador que corresponda. No verá lo que escribe pues para eso está escribiendo con
texto invisible. Puede visualizarlo mediante el botón
del editor Word. Verá también todos los caracteres de control del documento. Si lo prefiere, vaya al
menú Herramientas | Opciones y sobre la pestaña Ver seleccione Texto oculto.
Proceda de igual forma con todas las líneas del índice. Cuando termine, guarde el documento en
formato RTF y compílelo de la forma explicada mas atrás. Posiblemente ahora le salgan errores de
compilación, pues el compilador comprueba que todos los identificadores se corresponden en el índice y
en las páginas. Si le falta algún pie de página o un salto de carro manual le dará error. También le dará
un error, mejor dicho una observación, indicándole que hay párrafos ocultos. Es lógico, ha detectado los
textos ocultos que contiene el fichero. Ni caso. Le habrá creado el archivo .HLP y le sugiero que lo
pruebe, moviéndolo al directorio C :\DIRAYUDA y ejecutando la aplicación. Pulse F1 y le saldrá la página
con el índice y las líneas del índice en verde. Si lo ha hecho todo perfectamente, al seleccionar una y otra
línea le aparecerá la página correspondiente.
¡ Ya tenemos una ayuda de varias páginas !
Ventanas Emergentes
Es posible que dentro de la información presentada en cualquiera de las páginas anteriores, exista una
palabra o frase que quisiera explicar con mas detalles. Habrá observado en las ayudas de Windows que
algunas frases dentro de las páginas de ayuda están en verde, y al acercar el puntero del ratón a ellas se
convierte en una mano. Para poder hacer lo mismo en nuestra ayuda, volvamos al documento Word.
INDICE
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 278
1 - Introducción a la aplicación
2 - Acceso a la Base de Datos
3 - Introducción de datos
4 - Lectura de datos
- - - - - - - - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - # Introducción a la Aplicación
Esta aplicación está realizada para . . . . . . . . . .
- - - - - - - - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - # Acceso a la Base de Datos
Para abrir la Base de datos . . . . . . . . .
- - - - - - - - - - - - - - - - - - - - - salto de página manual - - - - - - - - - - - - - - - - - - - - - - - # Introducción de datos
Para introducir datos . . . . . . . . . . . .
- -- -- -- -- -- -- -- -- -- # Lectura de datos
salto de página manual - - - - - - - - - - - - - - - - - - - - - - -
Para leer los datos . . . . . . . . . . . . . . . .
Observe unas palabras que están subrayadas. Imagínese que esas palabras tienen un significado que
queremos explicar con mayor detalle. Puestos en nuestro caso, queremos explicar con mas detalle lo
que es una aplicación, una Base de Datos, introducir y leer.
Pretendemos que, al hacer click sobre una de estas palabras se abra, dentro de la ventana de ayuda,
otra ventana con la explicación de lo que es esa palabra concreta. Por lo tanto, debemos introducir esas
informaciones a base de introducir nuevas páginas en el documento Word donde editamos el fichero de
ayuda. Añádalas de la misma forma insertándoles un pie de página y el identificador deseado, de la
misma forma que se explicó mas atrás. Recuerde que el identificador debe ser único.
Una vez terminado de introducir todas las nuevas páginas, vaya a las palabras o frases que quiere
explicar con el texto de esas páginas, selecciónelas y deles el atributo de subrayado simple (Hágalo de
forma similar a cuando hizo lo del subrayado doble, pero esta vez SIMPLE) Introduzca inmediatamente
después de la palabra o frase un texto oculto con el nombre del identificador seleccionado para la página
deseada en esa palabra. Guarde el documento Word y vuelva a compilar como anteriormente. Ejecute la
aplicación y compruebe como vamos avanzando en el tema de las ayudas de Windows.
Si repasamos las propiedades de los controles, seguro que se acuerda de la propiedad HelpContextID
que tenían la mayoría de los controles VB. En aquel momento decíamos que esa propiedad que
establece un número de contexto asociado para este control. Este número se aplica para determinar la
ayuda interactiva asociada a este control. Ha llegado el momento de sacarle partido a esa propiedad.
Podemos usar la tecla F1 para acceder al índice de la ayuda de una aplicación y movernos a lo largo de
la ayuda seleccionando una u otra información. A veces resulta práctico seleccionar directamente la
ayuda correspondiente a la función de un control. Para poder hacer esto, asociaremos una de las
páginas del documento Word anterior al número que figura en la propiedad HelpContextID. Cuando ese
control tenga el foco, al pulsar F1 saldrá como página por defecto la página asociada mediante la
propiedad HelpContextID.
#
Introducción
Acceso
# Meterdatos
# Leerdatos
#
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 279
Para establecer esta relación vayamos al fichero con extensión .HPJ que servía para introducir los datos
al Help Compiler. En nuestro caso se llamaba FICHAYUD.HPJ y tenía por el momento, solamente dos
líneas.
[FILES]
AYUDA1.RTF
En estas dos líneas le introducíamos el nombre del fichero de ayuda [FILE]. Añadamos ahora en otro
apartado [MAP] la relación entre los identificadores de página y los números de contexto de la propiedad
HelpContextID de cada uno de los controles que la tengan activada (valor distinto a 0). Se escribirá el
nombre del identificador de página, y separado por un espacio o un tabulador, el número de contexto :
[MAP]
Identificador1
Identificador2
Identificador3
Identificador4
1
2
3
4
En este caso, cuando un control que tiene en su propiedad HelpContextID el número 3 tiene el foco, al
pulsar F1 aparecerá como página por defecto la correspondiente a la explicación con identificador
nombre Identificador3. Lo mismo ocurrirá con el resto de los identificadores.
Añada a su aplicación 4 TextBox y asígneles los valores 1, 2, 3 y 4 a sus propiedades HelpContextID.
Vuelva a compilar la ayuda y ejecute la aplicación. Vaya pasando el foco de uno a otro TextBox y
comprobándolo.
Puede que las ayudas que quiera aportar a cada uno de los controles sea muy breve, caso por ejemplo
de la que puede introducir en los TextBox para indicar al usuario lo que se va a hacer con el dato
concreto que se va a meter en ese TextBox. Y que esas ayudas breves sean muy numerosas y tal vez
cambiantes de un usuario a otro. Esto complicaría su fichero de ayuda original, al que debería introducir
muchas páginas nuevas. Puede editar estas pequeñas ayudas en otro documento Word, de la misma
forma que se ha descrito, y darle un determinado nombre (AYUDA2.RTF para nuestro ejemplo) y
añadirlo como otro fichero en la lista [FILES]. Colóquelo tras el fichero anterior, pues el que lleva el
índice debe ser el primero que figure en la lista. Debe añadir la relación entre los nombres de
identificador que haya puesto en ese nuevo fichero y los números de contexto de cada control.
El fichero FICHAYUD.HPJ queda de momento con la siguiente forma :
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1
Identificador2
Identificador3
Identificador4
1
2
3
4
Este procedimiento de acudir rápidamente a la ayuda de un determinado control puede que no sea el
ideal, ya que en una aplicación, siempre tiene el foco algún control. Si ese control que ahora mismo tiene
el foco tiene activado el HelpContextID, y el usuario pulsa F1, con la intención de ir a ver cualquier cosa
no relacionada con el control que tiene actualmente el foco, se verá sorprendido con que aparece una
información que nada tiene que ver con la esperada (índice). En cualquier caso, siempre podrá ir al
índice haciendo click en el botón CONTENIDO de la ventana de ayuda, pero en principio no está bien
que le aparezca en pantalla una información no esperada. Tiene solución, incluya en el menú (palabra
Ayuda) o en un control Image con el símbolo ? una llamada al programa WINHELP.EXE, pasándole
como parámetro el nombre del fichero de ayuda. Esto lo podemos hacer mediante la función SHELL
SHELL “WINHELP.EXE C:\DIRAYUDA\ FICHAYUD.HLP “, 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 280
(Vea función Shell. No se olvide del 1 final, pues si no lo pone la ayuda le saldrá minimizada. Puede
poner también un 4)
También puede utilizar para este fin el CommonDialog. Introduzca un CommonDialog en su aplicación y
ponga en su propiedad HelpFile el nombre del fichero de ayuda. La propiedad HelpCommand de este
CommonDialog debe estar puesta a 3 para que comience mostrando el índice de la ayuda. En estas
condiciones, en vez de acudir a la función Shell para ejecutar el WINHELP.EXE, ejecute
CommonDialog.ShowHelp. Vea con mas detalles las propiedades del CommonDialog, pues le permite
presentar otras funciones de la ayuda de Windows (Ayuda de la Ayuda, etc.)
Titulo de la ventana de Ayuda
Habrá observado que la ventana de ayuda tiene, en la barra de título el siguiente texto : Ayuda de
Windows. Si deseamos personalizarlo y poner el nombre de nuestra aplicación, basta con añadir un par
de líneas al fichero FICHAYUD.HPJ. Las correspondientes al apartado [OPTIONS]. Este apartado debe
ir en primer lugar del fichero, y puede llevar la información de la barra de título y el CopyRight. Estos dos
parámetros se introducen de la siguiente forma :
[OPTIONS]
TITLE= Nuestra Aplicación VB - Fichero de Ayuda
COPYRIGHT= Nombre del Autor(a)
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1
Identificador2
Identificador3
Identificador4
1
2
3
4
El dato introducido en la línea COPYRIGHT sale en el menú de la pantalla de ayuda, en Ayuda |
Versión.
Gráficos en la ventana de Ayuda.
Si necesita introducir un gráfico en la ventana de ayudas puede hacerlo de dos formas :
- Introducirlo en el fichero Word. Esta opción es recomendable si el gráfico es muy pequeño.
- Introducirlo directamente desde un fichero .BMP ó .WMF (Metarchivo). Recomendable
gráfico es grande. Este método se denomina de referencia a un gráfico.
cuando el
Para introducirlo por el primer procedimiento, inserte el gráfico en el texto Word y proceda como
siempre.
Para introducirlo por el segundo método, tiene tres posibilidades : Introducir el gráfico en el centro de la
ventana de ayuda, introducirlo a la izquierda con texto a su derecha o a la derecha con texto a su
izquierda.
Se supone que el gráfico está en un fichero llamado GRAFICO1.BMP en el directorio C:\DIRAYUDA.
Vayamos al documento Word, y en el sitio donde desee introducir el gráfico inserte la(s) línea(s) :
{bmc c:\dirayuda\grafico1.bmp}Le colocará este gráfico en medio de la ventana de ayuda, y este texto
inmediatamente debajo del gráfico.
o
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 281
{bml c:\dirayuda\grafico1.bmp}Le colocará este gráfico a la izquierda de la ventana de ayuda, y este
texto a la derecha del gráfico.
o
{bmr c:\dirayuda\grafico1.bmp}Le colocará este gráfico a la derecha de la ventana de ayuda, y este
texto a la izquierda del gráfico.
Se han resaltado en negrita las tres opciones. Recuerde la llaves donde se encierra la posición y el
nombre (y path) del gráfico.
Debe tener cuidado al introducir gráficos, ya que el compilador (HC.EXE) trabaja en DOS, y me da la
impresión de que no utiliza mas que los primeros 640 Ks. de memoria. Con un gráfico de 470 Ks. usado
en la preparación de estos apuntes fue incapaz de compilarlo, dando error de memoria insuficiente. (Y
no es que el Ordenador no tenga RAM suficiente)
Historial
La Ayuda de Windows nos permite recordar todas las páginas sobre las que se hizo una consulta. Esto
puede ser muy útil, pues tenemos muy accesible los temas que hemos consultado, para poder realizar
una nueva lectura de los mismos si fuese necesario.
Para obtener la ventana de historial, basta con hacer click en la barra de menú de la ventana de Ayuda
en Opciones | Mostrar Ventana de Historial.
Pero para que se pueda mostrar el historial, es necesario darle un nombre a las páginas, y será ese
nombre el que figure en la ventana de historial. Ese nombre es distinto del identificador de página,
aunque no hay ningún problema porque sea el mismo. Ponga como nombre de la página una palabra
que identifique esa página de una forma única.
Para poner el nombre a la página, vaya al comienzo de cada página e introduzca una nota al pié de la
misma forma que cuando ponía el identificador. En este caso el símbolo a introducir en la Marca
personal es el $. Proceda a introducir el nombre en la parte de abajo de la pantalla de Word
Palabras Clave
La Ayuda de Windows nos permite accede a una página usando como criterio de búsqueda ciertas
palabras que ponemos como clave. Por ejemplo, si queremos que aparezca nuestra página de ejemplo
que habla de Acceso a la Base de Datos, cuando el usuario busca una de las siguientes palabras :
Tablas, Base, Registro, y a la de Lectura de Datos cuando busque Obtener, Leer y Visualizar
Volvamos al editor Word, a las dos páginas nombradas y al lado de las notas al pié anteriores,
introduzca otra, esta con la Marca personal K. En la parte inferior de la pantalla, donde pone el nombre
de la nota al pie, ponga introduzca las palabras clave para cada una de ellas, separadas con una coma.
Salve el fichero RTF y vuelva a compilar. Ejecute la aplicación y saque la Ayuda. Observará que el botón
Búsqueda de la ventana de ayuda está habilitado. Haga click en este botón y verá que esas palabras ya
figuran en la lista.
Usar los Gráficos de la Ayuda como enlaces a páginas
Lo mismo que hacíamos con las palabras, bien las del índice, a las que con un subrayado doble les
introducíamos un enlace a una página, o con cualquier palabra o frase de una página, que mediante un
subrayado simple les introducíamos un enlace a una ventana emergente, lo mismo podemos hacer con
la referencia a un gráfico. (Vea un poco mas arriba, las referencias a los gráficos del tipo {bmc
c:\dirayuda\grafico1.bmp} ) Si seleccionamos esa referencia y le ponemos el atributo de doble
subrayado, al acercar el puntero del ratón a ese gráfico (en la ayuda) nos mostrará una mano, y
haciendo click sobre el gráfico sacará la página correspondiente. Si le ponemos el atributo de subrayado
simple, nos sacará una ventana emergente. Eso sí, en cualquiera de los dos casos, deberemos poner, a
continuación de la referencia al gráfico, con texto invisible, el indicador de página que especifique la
página o ventana emergente que queremos mostrar.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 282
Páginas en secuencia
Si tenemos una ayuda muy larga y la queremos leer toda, con lo que sabemos deberíamos ir al índice y
desde allí acceder a la página 1, leerla, volver al índice, acceder a la página 2, leerla, volver al índice ....
Para evitar este proceso, y acceder secuencialmente a cada una de las páginas, podemos asignar a
cada una de las páginas un código de secuencia, que podrá estar formado por caracteres alfanuméricos.
Este código de secuencia será el que marque el orden de aparición de las páginas. Pero el orden de
aparición será según el código ASCII de los caracteres que formen ese código, comenzando por la
izquierda. Por lo tanto puede ocurrirle la paradoja de que aparezca primero la página 100 que la 65. Es
decir, si los códigos están formados por números aparecerán primero todas las páginas que comiencen
por 1, aunque el valor numérico de una de ellas sea superior a otra que comience por 2, 3, 4, ...
Para asignar este código de secuencia deberemos introducir otra nota al pié para cada página, en este
caso con la marca personal + (signo mas). También deberemos indicarle al WinHelp que deseamos
sacar los botones (<<) y (>>) para desplazarnos por las páginas. Esto se consigue añadiendo una
nueva sección al archivo .HPJ que se denomina [CONFIG] y le introduciremos en esta sección la
expresión BrowseButtons()
El fichero FICHAYUD.HPJ quedará de la siguiente forma :
[OPTIONS]
TITLE= Nuestra Aplicación VB - Fichero de Ayuda
COPYRIGHT= Nombre del Autor(a)
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1
Identificador2
Identificador3
Identificador4
1
2
3
4
[CONFIG]
BrowseButtons()
Encabezado de páginas
Habrá observado en la ayuda de Visual basic que una o dos líneas en la parte superior de la ventana de
ayuda se conservan allí continuamente aunque nos desplacemos hacia abajo mediante los cursores de
desplazamiento. Esas líneas son el Encabezado de página. Para conseguir esto en nuestra ayuda
deberemos escribir las líneas que queramos que se conserven como encabezado de página al principio
de cada página, seleccionarlas con el cursor del ratón y abrir el menú Formato | Párrafo (Se supone
que está utilizando el procesador de texto Microsoft Word) donde le aparecerá un cuadro de diálogo con
dos solapas, San gr ía y Es pa ci o y Presentación . Elija Presentación y dentro de esta solapa, active la
casilla Conservar con el Siguiente. Las líneas que hubiera seleccionado se le conservarán como
Encabezado de página.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 283
VENTANAS MULTIPLES
Con frecuencia es útil emplear varias ventanas para mostrar la información de una aplicación. El ejemplo
que tenemos mas a mano es el de la Ayuda de Visual Basic. Cuando tenemos seleccionada la ayuda de
un control, se pueden observar al menos dos palabras que nos llevan a una segunda ventana :
Propiedades y Eventos. Cuando elegimos una de estas informaciones aparece una segunda ventana
que nos muestra la información pedida, sin perder la información que tenemos en la primera ventana.
Esta segunda ventana se comporta de manera idéntica a la primera, en cuanto a llamadas a otras
páginas o a menús emergentes.
Para poder presentar esta segunda ventana es necesario primero definirla. Para ello volvamos a nuestro
fichero .HPJ y le añadiremos un nuevo apartado : WINDOWS, donde introduciremos el nombre de la
nueva ventana, el título de la misma (El título que aparecerá en su parte superior), y, entre paréntesis, su
posición y dimensiones.
El fichero .HPJ quedará de la siguiente forma, tras introducirle dos nuevas ventanas :
[OPTIONS]
TITLE= Nuestra Aplicación VB - Fichero de Ayuda
COPYRIGHT= Nombre del Autor(a)
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1
Identificador2
Identificador3
Identificador4
1
2
3
4
[CONFIG]
BrowseButtons()
[WINDOWS]
Ventana2 = “Titulo de esta Ventana”, (PosiciónX, PosiciónY, DimensiónX, DimensiónY)
Ventana3 = “Titulo de esta Ventana”, (PosiciónX, PosiciónY, DimensiónX, DimensiónY)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 284
Para llevar la información a una de estas ventanas, en vez de a la ventana principal, se añadirá tras el
identificador de la página que queremos enviar a la nueva ventana el símbolo > y a continuación el
nombre de la ventana.
El Objeto App
Introducimos aquí un nuevo objeto Visual Basic. El objeto App es un objeto global al que se accede con
la palabra clave App. (No se líe. El objeto App no es ni mas ni menos que un conjunto de datos acerca
de la aplicación) Determina o especifica información sobre el título de la aplicación, la ruta de acceso de
su archivo ejecutable y los archivos de Ayuda, y si está ejecutándose una instancia anterior de la
aplicación. Este objeto tiene solamente propiedades. No tiene ni Eventos ni Métodos. Una de sus
propiedades es HelpFile, propiedad que es de lectura y escritura. Es decir, podemos obtener el nombre
del fichero de ayuda de una aplicación consultando el valor de esa propiedad del Objeto App. En el
ejemplo siguiente introducimos el nombre del fichero de ayuda en el Label1
Label1.caption= App.HelpFile
Como la propiedad HelpFile también es de escritura, se puede cambiar en tiempo de ejecución el
fichero de ayuda. Piense lo útil que puede resultar esto para cambiar el idioma de la ayuda de una
aplicación. Para ello basta con imponer el nombre (con su Path) del nuevo fichero de ayuda :
App.HelpFile = "C:\ ..... \ ..... \ nuevaayuda.hlp"
(Vea un poco mas adelante mas información sobre el Objeto App)
Otros Compiladores de Ayuda (HCP.EXE, HCW.EXE, ...)
En este capítulo hemos citado como compilador del fichero de ayuda al programa HC.EXE que
habitualmente se encuentra en el directorio C :\ . . . . \ VB\HC. Este compilador trabaja perfectamente
con ficheros .RTF creados con las versiones primeras del Word.
Si Ud. realiza los ficheros .RTF con el Word para Windows95 (Word 6.0), no habrá tenido ningún
problema con lo descrito anteriormente. Si tiene Word de office97 (W97) habrá observado que al
compilar la ayuda con el HC.EXE le sale un error. No se preocupe. Es que el fichero RTF creado por
W97 es distinto del creado por W95, lo cual, aparte de dar una idea de como se trabajan los temas de
compatibilidad entre procesadores que deberían ser compatibles, nos obliga a buscar otro compilador de
ayudas.
No lo intente con el HCP.EXE. Tampoco vale. Busque por Internet un fichero llamado HCW.EXE,
compilador que tiene además la ventaja de que trabaja en Windows. Usa el mismo fichero .HPJ y acepta
los ficheros .RTF creados con W95 y W97
El aspecto de este compilador de ayudas es el siguiente :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 285
Aparte de este compilador, existen otros que funcionan de forma similar. No vamos a explicar cada uno
de los compiladores que podamos encontrar, que como se dijo hay bastantes y ( creo que) shareware.
Lo importante es que todo lo dicho respecto a la edición de los ficheros :RTF y .HPJ sigue siendo válida
para estos compiladores. Existen algunos compiladores que también crean el fichero .HPJ. Es
comprensible no intentar examinar uno a uno en esta Guía del Estudiante.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 286
Visual Basic - Guía del Estudiante Cap. 11
BASES DE DATOS EN VISUAL BASIC (1)
A mod o de introducc ión
Todo lo visto hasta ahora en este libro es el Visual Basic elemental que debe conocer necesariamente
para realizar una aplicación. Sin embargo hay algo que falta. El 90 % de las aplicaciones que va a
realizar van a llevar una base de datos. Es lógico. Una aplicación se hace normalmente para presentar
datos, datos que habrá que introducir y mostrar de forma conveniente. Lo de introducir y mo strar
datos son las materias que va a ver en los capítulos siguientes, pero no olvide lo de mostrarlos d e
forma conv eniente , y es en eso donde tendrá que aplicar todo lo que lleva aprendido hasta ahora. Se
observa con mucha frecuencia que el alumno tiene una prisa desmesurada por llegar a los temas que
tratan las bases de datos, dejando un poco de lado la interface necesaria para su introducción y
presentación, que es lo que da ergonomía y elegancia a una aplicación. El conocimiento de bases de
datos es necesario. Lo explicado hasta ahora, imprescindible.
Visual Basic nos permite trabajar directamente con distintas bases de datos (ACCESS, dBaseIII,
dBaseIV , dBase 5, Excel3, Excel4, Excel5, Excel7, FoxPro2.x, Foxpro3.0, LotusWK1, LotusWK3,
LotusWk4, Paradox3.x, Paradox4.x y Paradox5.x Esto lo logra mediante el Motor de Bases de Datos
Jet, herramienta de Microsoft para administrar los datos en bases de datos Access. Tiene un nombre
que mas parece de una materia de ingeniería aeronáutica, pero en realidad no es mas que un conjunto
de programas que se cargan en el disco duro cuando instala Access o Visual Basic. E esta forma de
acceder a las bases de datos se le llama Acceso mediante objetos DAO. Lo de DAO viene de Data
Access Objet. Y es la forma más sencilla y rápida de acceder a una base de datos Access instalada en
el propio disco duro o en un disco de red de área local rápida. (Lo de facilidad de acceso a una base de
datos Access viene implícito en la política de Microsoft de facilitar la compatibilidad entre sus
aplicaciones)
Pero esto se quedaría muy corto si solamente se pudiese conectar con las bases de datos citadas. No
se puede concebir un sistema de desarrollo que no pueda acceder a bases como Oracle, Informix, SQL
Server, etc. Estas bases de datos, aparte de tener su propia interface para acceso a datos, disponen de
una forma de acceso común a todas : ODBC
Lo de ODBC (Open Data Base Conectivity) es un mecanismo de conexión entre bases de datos
abiertas. Lo de abiertas significa que tienen esa interface de acceso común, interface a través de la cual
puede acceder a sus datos cualquier aplicación. Esta interface utiliza el lenguaje SQL, y es necesario
establecer una conexión ODBC en Windows. Lo veremos mas adelante.
Los objetos DAO pueden acceder también a bases de datos a través de ODBC. Esto podemos decirlo
con la versión DAO 3.5, no podemos decir lo mismo con la 2.5, procedimiento previsto pero que no
funcionaba.
Este pobre funcionamiento de DAO con ODBC llevó a Microsoft a crear otro tipo de acceso a datos: el
RDO (Remote Data Objet), y los objetos de acceso a datos RDO. Esto consiste en objetos parecidos a
los DAO, pero que en vez de atacar directamente a la base de datos como lo hace DAO, lo hacen a
través de una conexión ODBC previamente establecida en Windows. Así por ejemplo, en un objeto DAO
hablamos del nombre de la base de datos, refiriéndonos al nombre del fichero que contiene los datos
(C:\Mis Documentos\MiBase.Mdb), y en RDO nos referimos al nombre de la conexión ODBC
(Connection) refiriéndonos al nombre de una conexión ODBC ya establecida, que apunta a una base de
datos que es donde vamos a leer o escribir. Este método tiene la gran ventaja de que podemos
establecer hoy una conexión con una base determinada, y si queremos cambiar mañana la base de
datos sobre la que vamos a trabajar, basta con cambiar esa conexión apuntando hacia otra base de
datos. Así no es necesario realizar ningún cambio a nuestro código
Un error bastante general con los objetos RDO es pensar (seguramente por aquello de Remote Data
Objet) que solamente pueden trabajar con una base de datos que esté en otro ordenador, al cual
estaremos unidos por cualquier forma de conexión. No tiene nada que ver. RDO significa solamente que
accedemos a los datos a través de ODBC, y podemos hacerlo (al igual que con DAO) a una base que
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 287
esté en el mismo disco duro que la aplicación, o una que esté en un servidor unido a través de una Red
de Area Local.
Pero RDO no tiene las prestaciones que tiene DAO para trabajar con bases de datos Access. De hecho,
RDO pierde grandes facilidades que aporta DAO para este tipo de bases de datos. RDO trabaja sobre
una conexión ya instalada, que apunta a una base de datos ya creada. Con RDO no podemos crear esa
base de datos. Esto es obvio, con RDO podemos entrar en una base de datos Oracle, por ejemplo.
Nadie puede pretender que Visual Basic cree una base de datos de esa marca. Sin embargo, con ADO
sí podemos crear una base de datos Access. Piense en la facilidad para distribuir una aplicación que
tenga una base de datos Access cuyos campos puedan tener un tamaño definido por el propio usuario.
Bastaría poner una herramienta en la propia aplicación donde el usuario introdujese los tamaños de los
campos tipo texto, para adaptar la base de datos a sus necesidades. Esto puede hacerlo con DAO
puesto que nos permite crear bases de datos Access, pero no lo podemos hacer mediante RDO.
RDO utiliza una terminología ligeramente distinta de DAO. Por ejemplo, sonde en DAO ponemos
OpenRecordset, en RDO debemos poner OpenResultset. Es una pena que no se pueda trabajar con la
misma terminología y con todas las prestaciones que tiene DAO a través de ODBC. Esto mismo pensó
Microsoft, y esa fue la razón de implementar en los objetos DAO 3.5 la conexión ODBCDirect.
ODBCDirect nos permite trabajar con los mismos objetos DAO pero a través de una conexión ODBC,
que en este caso, funciona. Puede ser un poco más lenta que DAO, pero en esto hay opiniones para
todos. De esta forma es posible seguir utilizando los viejos métodos aprendidos para DAO (Y lo que es
mejor, reutilizar el código ya escrito en anteriores aplicaciones) a través de una conexión ODBC. Lo
veremos mas adelante.
Pero no debemos pensar que aquí se acaban los métodos de acceso a datos. Existe otro mas, muy
reciente denominado ADO. ADO quiere sustituir a DAO y RDO.
En este punto ponía hace dos años que eso lo va a determinar el mercado. Hoy (Nov.2002) se puede
decir que ADO ha sustituido en todas las aplicaciones nuevas a RDO, y ha dejado a DAO solamente el
mercado de las pequeñas aplicaciones domésticas. ADO es una maravilla. Por eso, la Guía del
Estudiante dedica un nuevo capítulo y un amplio ejemplo a ADO. Pero eso no implica que no haya que ir
paso a paso. Y primero hay que aprender DAO. Pero ahora todo lo que aprenda de DAO le va a servir
para ADO, pues en ADO sí coincide el código. Aprendamos pues DAO, y luego aplicaremos nuestros
conocimientos a ADO. La gran ventaja de ADO es que en aquellas aplicaciones que leen una base
situada en un servidor, ocupa menos la red de área local, ya que trabaja una aplicación Cliente –
Servidor.
Adelanto de términos. Aplicaciones Cliente servidor Piense en una base de datos instalada en una
red no muy rápida. Si creamos un acceso a datos (recordset) con DAO, el tráfico de datos por la red es
muy grande, dado que puede darse el caso de tener que ver toda la base de datos para extraer de ella
solamente un dato. Una aplicación Cliente – Servidor lo que hace es montar un programa en el
servidor, al cual le pedimos desde nuestra aplicación el dato deseado. Ese programa posiblemente tenga
que ver toda la base de datos para encontrar el dato que nos interesa, pero lo hace localmente en el
servidor, sin verter todos los datos a la red de área local. Una vez que lo ha encontrado, nos pasa a
través de la red el dato solicitado, con lo que bajamos el tráfico por la red de forma muy importante. Lo
veremos mas adelante pero no con una gran profundidad. Es un tema que se sale necesariamente de
este curso debido a su extensión. Existen multitud de libros que tratan el tema.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 288
No se preocupe de los que acaba de leer. Con las explicaciones anteriores parece que esto de las bases
de datos debe ser cosa de gurús informáticos, vedado al resto de los mortales. Nada mas lejos de la
realidad. Y para demostrarlo, en lo que queda de capítulo vamos a trabajar con bases de datos SIN
escribir una sola línea de código. No digo que sea lo mejor, pero puede hacerse. Esto se logra mediante
controles OCX creados por Microsoft, que controlan directamente a ese conjunto de programas que
habíamos dado en llamar Motor de bases de Datos Jet o a los programas similares de RDO o ADO.
Comenzaremos el estudio de bases de datos con los objetos DAO. Y para DAO el control que organiza
el trabajo al Motor Jet es el Control Data. Existen controles similares para RDO y para ADO. Pero no
corramos y centrémonos sobre DAO y nuestro motor Jet
DAO - Acceso a bases de datos mediante el Control Data
Para acceder a estas Bases de Datos basta con introducir un control Data en el formulario, y fijarle las
propiedades apropiadas para que trabaje sobre uno u otro tipo de base de datos. El control Data nos
permite acceder de una forma sencilla a cualquier base de datos de estos tipos, y sirve de enlace entre
la base de datos y los controles que son habilitados para presentar los datos de esa base. Utiliza el
motor de bases de datos Jet para el acceso a los datos.
El Control Data
El control Data puede tomarse directamente de la caja de herramientas. Al contrario que los controles
similares RDO y ADO, este está siempre en la caja de herramientas. En el formulario tiene el aspecto de
una barra deslizante :
Decíamos que el control Data sirve de enlace entre la base de datos y los controles que pueden
presentar datos. Estos controles a los que nos referimos son los llamados Controles Enlazados a
Datos, y que son viejos conocidos nuestros, al menos algunos de ellos.
Los dos más sencillos son el control Label y el control TextBox
Un control Label puede presentar un dato. Si queremos que ese dato sea un campo de una tabla de una
base de datos, basta que enlacemos la base de datos al control data, y que enlacemos luego el control
Label con el control Data. Si hacemos lo mismo con el TextBox, no solamente podremos presentar
datos de la BD, sino que los podemos introducir, al ser el TextBox un control bidireccional.
Veamos como se enlaza un control data a una base de datos. Se supone que el alumno conoce la
estructura de una base Access, BD con la que vamos a iniciar este estudio. De cualquier forma, y para
los que han suspendido la asignatura de base de datos Access, citar solamente que una base de datos
Access contiene dentro de un fichero (P.e. C:\MiCarpeta\MiBase.Mdb) varias Tablas (P.e. Tabla1,
Tabla2 y Tabla3) Cada tabla es en sí una base de datos en el sentido estricto. Tiene un número
indeterminado de registros, (filas) que guardan la información en varios Campos.
El fichero, que tiene por extensión Mdb es la base de datos, y ese nombre (Dirección completa de la
carpeta y nombre del fichero) es lo que debemos poner al control Data en su propiedad DataBaseName.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 289
Con esto, el control data ya sabe donde tiene que ir a leer los datos. Pero le falta todavía por saber en
que tabla dentro de esa BD los tiene que leer. El nombre de la tabla se lo indicamos al control Data en la
propiedad RecordSource. Para elegir esta propiedad basta con desplegar la lista de las tablas haciendo
click en la flecha de la línea de la propiedad RecordSource. Dado que el control Data ya sabe en que
base de datos debe leer los datos (Ya tiene puesta la propiedad DataBaseName), ya puede saber
cuantas tablas tiene y los nombres de estas tablas. Elija la tabla deseada. En nuestro ejemplo, Authors
Con esto ya podría trabajar, pero le faltan aún ciertos detalles. Por ejemplo, el tipo de recordset que debe
crear. (Dynaset, Snapshot, Table) Esto se lo indicamos en la propiedad RecordsetType, que por defecto
le va a poner Dynaset. (Ya veremos que es cada uno de ellos) Y ya tenemos casi todas las propiedades
del control Data cubiertas. Las demás son las típicas de todos los controles. Casi todas las
propiedades, porque hay una que se ha introducido en la versión 6 de VB para permitir las dos formas de
atacar a la base de datos, con el motor Jet o a través del citado ODBCDirect.. Esa propiedad es
DefaultType y nos permite elegir entre usar el motor de base de datos Jet (Poniendo a esta propiedad
el valor 2 o dbUseJet) o usar ODBCDirect (Poniéndole el valor 1 ó dbUseODBC) El valor por defecto es
usar el motor Jet y así trabajaremos en principio.
Ya tenemos enlazado el control Data a la base de datos. Falta ahora enlazar una etiqueta y un TextBox
al control Data para tener el enlace completo. Eso es aún más sencillo. Si desplegamos las propiedades
del TextBox por ejemplo, veremos que tiene unas propiedades que cuando lo estudiamos, las habíamos
pasado un poco por alto: DataSource y DataField.
En la figura puede ver que la propiedad DataSource puede desplegarse, mostrando en este caso el
nombre del único control Data que tenemos en el formulario: Data1 Si tuviésemos mas controles Data,
aparecerían los nombres de todos ellos. Se elige uno.
A continuación debemos señalarle qué campo queremos que nos presente. Podemos desplegar la lista,
donde podemos ver los campos de la tabla elegida para la propiedad RecordSource del control Data.
Elegimos uno y ejecutamos la aplicación.
Podemos observar que ya funciona. Si ponemos tantos TextBox como campos tiene la tabla elegida,
podemos ver todo el contenido de la Base de datos moviéndonos a lo largo de ella mediante las flechas
de cursor del control Data. Todo ello sin escribir una línea de código tal y como habíamos prometido.
Entremos ahora en un estudio un poco más avanzado del control Data.
El control Data proporciona acceso a datos almacenados en bases de datos usando uno de los tres tipos
de objetos Recordset. El control Data le permite ir de registro en registro y presentar y manipular los
datos de los en controles enlazados. Sin un control Data, los controles enlazados con datos de un
formulario no pueden tener acceso automáticamente a los datos.
Los controles enlazados solamente pueden tener acceso a un control Data si este está en el mismo
Formulario.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 290
En el tema de Bases de Datos se emplean términos no conocidos aún. Se irán viendo a lo largo del
curso, pero no queda otro remedio mas que comenzar a utilizarlos. Se irán haciendo avances de estos
términos, que serán explicados en profundidad en su momento.
Avance de términos.
Objeto Record set (conjunto de registros)
Es un conjunto lógico de registros. Los tres tipos de objetos Recordset son Dynaset , (Permite la lectura
y escritura de un registro) Snapshot (Realiza una lectura instantánea de los registros, no permitiendo
modificarlos) y Table . (Representación en el código de una tabla base que puede utilizarse para
agregar, modificar o eliminar registros de una sola tabla).
Contro les enlazados
Son los controles que pueden presentar directamente datos de uno o varios campos de una Base de
Datos. Los controles DBList, DBCombo y DBGrid tienen la posibilidad de presentar un conjunto de
registros cuando se asocian con un control Data. Los controles CheckBox, TextBox, Label, Picture,
Image, ListBox y ComboBox también son controles enlazados con datos y pueden asociarse a un único
campo de un Recordset administrado por un control Data.
La mayoría de las operaciones de acceso a datos se pueden realizar usando el control Data sin escribir
ningún código. Los controles enlazados con un control Data presentan de forma automática los datos de
uno o más campos del registro actual o, en algunos casos, de un conjunto de registros a ambos lados
del registro actual. El control Data realiza todas las operaciones sobre el registro actual.
Avance de términos
Registro Actual . Un registro es un conjunto completo de campos. Una base puede tener muchos
registros, pero el “puntero” de la base de datos apunta a un único registro en cada momento. Ese
registro al que apunta el puntero se llama registro actual.
Si el control Data recibe instrucciones de moverse a un registro diferente, todos los controles enlazados
pasan automáticamente los cambios al control Data para ser guardados en la base de datos. El control
Data se sitúa después en el registro requerido y pasa los datos del registro actual a los controles
enlazados donde son presentados. Esto significa que se pueden modificar los datos de una base de
datos simplemente cambiando los datos en los controles enlazados que lo permitan, y moviendo el
puntero de la base de datos, es decir, cambiando el registro actual.
Una vez iniciada la aplicación, Visual Basic usa las propiedades del control Data para abrir la base de
datos seleccionada, abrir un objeto Database y crear un objeto Recordset. Las propiedades Database y
Recordset del control Data hacen referencia a los objetos Database y Recordset recién creados que
pueden ser manipulados por el control Data. Siempre podremos conocer el Recordset usado por el
control Data leyendo esa propiedad
VariableTipoRecordset =Data1.Recordset
Y si tenemos otro control Data en la aplicación (Puede estar en otro formulario) siempre podemos hacer
que el recordset de este segundo control Data sea igual al del primero
Set Data2.Recordset = VariableTipoRecordset
(Obviamente el ámbito de VariableTipoRecordset debe permitir que se vea en los formularios donde está
Data1 y Data2
Cuando se usa un control Data para crear un objeto Recordset o cuando se crea un objeto Recordset en
el código y se asigna al control Data, el motor de base de datos Jet de Microsoft puebla
automáticamente el objeto Recordset. Como resultado, los marcadores (y en los objetos Recordset de
tipo snapshot, los datos del conjunto de registros) se guardan en la memoria local; el usuario no necesita
manipular el control Data y no es necesario invocar el método MoveLast en el código para conocer el
número total de registros. Los bloqueos de página usados para crear el Recordset se liberan más
rápidamente, haciendo posible que otros objetos Recordset accedan a los mismos datos. Los objetos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 291
Recordset creados en el código pero que no se asignan a un control Data no son poblados
automáticamente por el motor Jet. Se deben poblar desde el código.
El párrafo anterior, tomado casi literalmente de la información de Microsoft, exige al menos una
explicación.
Cuando se crea un Recordset mediante un control Data, se leen inmediatamente todos los registros que
forman parte de ese Recordset (Recuerde que un Recordset es un conjunto de registros). De esta forma,
en una base que estuviera compartida por varios usuarios a través de una Red de Area Local (RAL) un
usuario leería todos los datos en el mismo momento de la creación del Recordset por el control Data,
llevaría esos datos a su memoria RAM y no volvería a estorbar en la base de datos (cuando un usuario
de una RAL lee un dato en una BD, bloquea esta BD mientras dura su lectura y no pueden acceder a ella
otros usuarios) Si el Recordset se crea por código, se lee solamente un registro (la base se bloquea en
el momento de la lectura e inmediatamente se libera), y cuando se le pide otra operación (p.e. que
avance un registro) vuelve a bloquear la BD, lee ese registro y la desbloquea. En principio el leer el
Recordset de una vez parece que tiene ventajas en aquellas instalaciones que tienen una base de datos
compartida. Todo ello a un precio. Ocupar mas memoria RAM en cada uno de los PCs de los usuarios.
Esta limitación hace en algún caso que no sea posible utilizar un control Data por falta de memoria RAM
en los puestos de usuario.
El control Data puede manipularse con el mouse, moviéndose de registro en registro o al principio o al
final del Recordset. El control Data no permite que el usuario se pase de los límites del Recordset
usando el mouse. No se puede mover el enfoque al control Data.
Observación muy importante
El control Data crea un objeto Database y un objeto Recordset automáticamente. Estos objetos de
acceso a datos son idénticos a los creados mediante código, y tienen las mismas propiedades y
métodos. Podemos referirnos a ellos usando el nombre del control Data seguido del nombre del objeto
(Database o Recordset). Por ejemplo :
Data1.Database
Data1.Recordset
El objeto Database creado por un control Data no se cierra aunque se cambie la propiedad
DatabaseName del control Data. Lo mismo ocurre con el objeto Recordset. Solamente podemos
cerrarlos utilizando el método Close :
Data1.Database.Close
Data1.Recordset.Close
Esta observación debe ser tenida muy en cuenta sobre todo cuando el control Data abre la Base de
Datos de forma exclusiva, o cuando tenemos que hacer una operación con la Base de Datos que exija
que esté cerrada. Por ejemplo, el método CompactDatabase y otros métodos que veremos mas
adelante.
Objetos para acceso a datos
Los objetos para acceso a datos Database y Recordset creados por el control Data tienen cada uno sus
propiedades y métodos propios y se pueden escribir procedimientos que usen estas propiedades y
métodos para manipular los datos.
Por ejemplo, el método MoveNext de un objeto Recordset mueve el registro actual al siguiente registro
del Recordset. Para invocar este método, se podría usar el siguiente código:
Data1.Recordset.MoveNext
El control Data puede crear cualquiera de los tres tipos de objetos Recordset (Dynaset, Snapshot, Table)
Si no se indica el tipo a crear, se crea un Recordset de tipo Dynaset.
Nota. Las constantes usadas para requerir un tipo específico de Recordset cuando se usa un control
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 292
Data son diferentes de las constantes usadas para determinar el tipo de Recordset creado o que se va
crear usando el método OpenRecordset.
Para seleccionar un tipo específico de Recordset, establezca la propiedad RecordsetType del control
Data a:
Tipo de Recordset
Valor
Constante control Data
Constante OpenRecordset
Table
Dynaset
Snapshot
0
1
2
vbRSTypeTable
vbRSTypeDynaset
vbRSTypeSnapshot
dbOpenTable
dbOpenDynaset
dbOpenSnapshot
Diferencias entre la Edición Standard y la Edición Profesional de Visual B asic
En cuanto al acceso a datos, la diferencia principal entre las ediciones Estándar y la Profesional de
Visual Basic es la capacidad de crear nuevos objetos para acceso a datos. En la edición Estándar NO
se pueden declarar en el código (con la palabra clave Dim) variables como objetos para acceso a datos.
Esto quiere decir que sólo el control Data puede crear objetos Database y Recordset.
En la edición Profesional y Empresarial de Visual Basic, SI se puede crear un nuevo objeto Recordset
y asignarlo a la propiedad Recordset del control Data.
¡Esta diferencia ha llevado a la locura a muchos alumnos y programadores usando la versión de su casa
y la de su empresa o centro escolar !
En la pequeña aplicación realizada al comienzo de este tema ha visto que los controles enlazados a
datos permiten visualizar e introducir datos en la base de datos a través del control Data. Efectivamente,
no tendría sentido poner un control data sin enlazarlo a otros controles para que estos nos sirvan de
elementos de presentación y captura de datos. Veremos mas adelante en este capítulo los controles
enlazados a datos.
Consultas almacenadas
Otra opción importante cuando se usa el control Data es la posibilidad de presentar una consulta
realizada previamente en Access. Si se ha creado previamente una consulta, el control Data nos
mostrará esa consulta como si se tratase de una tabla más de la base de datos, al desplegar la lista de
tablas para cubrir la propiedad RecordSource. Puede por lo tanto presentar solamente los campos que
necesite en su aplicación, tomados de una tabla (o de varias tablas si ha establecido las relaciones
oportunas) y de esta forma su aplicación va a trabajar más rápido que si tuviese que seleccionar esos
campos mediante una instrucción SQL Para presentar una consulta, establezca la propiedad
RecordSource del control Data al nombre de esa consulta (En vez de poner el nombre de una tabla,
ponga el nombre de la consulta). Esto no puede hacerse si la consulta contiene parámetros. Esto le
ocurre cuando la consulta se ha creado partiendo de los datos de otra consulta.
Es mucho más rápida una consulta utilizando una consulta ya creada en Access que introduciendo la
consulta en SQL. La razón es muy sencilla. Al crear una consulta es Access quien crea una especie de
“tabla nueva” en la propia base de datos. Esta tabla nueva no c ontiene datos, sino referencias a registros
de una tabla. Por lo tanto, el motor de bases de datos se limita a recorrer esa “tabla nueva”, tomar el
número del registro que debe presentar, ir a ese registro y tomar el dato que contiene. Si lo que hace es
una consulta SQL, se debe obtener la información registro a registro según las condiciones establecidas
en la cláusula SQL. Esta segunda opción tarda logicamente más. Y si está leyendo la base de datos a
través de una red de área local, la ocupación de esta red es mucho menor si el recordset se crea con la
consulta de Access.
Estamos hablando de una consulta SQL establecida en el control Data. ¿Dónde? Justamente en la
propiedad RecordSource del control data. Hasta ahora habíamos puesto en esa propiedad el nombre de
una tabla o de una consulta ya hecha en Access. Si en vez del nombre de la tabla ponemos una consulta
SQL, la cosa también funciona:
Con una Tabla
Data1.RecordSource = “Autores”
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 293
Con una consulta SQL
Data1.RecordSource = “Select * From Autores Where Apellidos = ‘Cervantes Saavedra’”
Esta consulta obtiene de la tabla Autores, solamente los registros en los que el campo Apellidos sea
igual a “Cervantes Saavedra” Funciona, pero para averiguar el número de registros que tienen esos
apellidos deberá recorrerlos todos, comprobar si son iguales a los expresados en la sentencia SQL y en
caso afirmativo pasarlos al recordset creado. Si se hubiera creado una consulta previamente en Access,
y pusiésemos el nombre de la consulta en la propiedad RecordSource del control Data, éste iría
directamente a los registros que gozan de tan ilustres apellidos, ya que Access habría hecho una tabla
con los números de los registros que cumplen esa condición (esa tabla no contiene los datos, sino el
número de los registros que los contienen), el control data leería esos números e iría a los registros
indicados en esos números, evitando de esta forma tener que leer el contenido del campo Apellidos del
resto de los registros. De cualquier forma, si la base de datos está en el mismo ordenador que la
aplicación, esto empieza a ser importante cuando trate tablas con muchos registros. Si está en una red
de área local no hace falta tener muchos registros para comprobar que se ralentiza la aplicación.
Propiedades del control Data
Align El control Data puede programarse para que se ajuste automáticamente a la parte superior o
inferior de su formulario primario usando la propiedad Align. En cualquier caso, el control Data ajusta su
tamaño horizontal al de su formulario primario cuando el tamaño de éste cambia. Esta propiedad permite
situar un control Data en un formulario MDI sin requerir un control Picture que lo contenga.
Appearance Flat y 3-D
Backcolor
Color de fondo de la parte intermedia del control
Administración de BOF/EOF
Las propiedades BOFAction y EOFAction establecen el comportamiento del control Data cuando llega
al principio o final de los registros. En esos casos se produce el BOF y EOF respectivamente.
BOF (Begin Of File). Se produce el BOF cuando el control Data se posiciona sobre el registro
inmediatamente anterior al primero (No es un juego de palabras). Este registro será el -1.
EOF (End Of File) Se produce la condición EOF cuando el control Data se posiciona en el registro
inmediatamente posterior al último. Este registro será también el -1.
La propiedad BOFAction permite seleccionar el comportamiento del Data cuando nos hemos pasado de
registros por abajo. Tiene las opciones MoveFirst (se mueve al primer registro) o BOF (se queda donde
está)
La propiedad EOFAction establece el comportamiento del control Data cuando se sobrepasa el último
registro. Podemos indicarle que se mueva al último registro (MoveLast), que se quede donde está
(EOF), o que introduzca un nuevo registro (AddNew)
Caption
El nombre que figurará en la parte intermedia del control.
Connect Muy Importante. En esta propiedad debemos indicarle al control Data el tipo de base de datos
a la que va a conectarse. Admite todas las bases enumeradas al principio de este capítulo.
DatabaseName En esta propiedad se le indica el nombre (Con su Path) de la base de datos a la que
debe conectarse. Para facilitar la búsqueda de la base de datos, haciendo click en esta propiedad en la
caja de propiedades, podemos sacar un cuadro de diálogo haciendo click de nuevo en los tres puntos
que aparecen a la derecha de la propiedad. El cuadro de diálogo seleccionará directamente las
extensiones de los ficheros de bases de datos acordes con el tipo de base de datos seleccionada en la
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 294
propiedad Connect.
Database
(Solo en ejecución)
Esta propiedad es sólo de lectura. Devuelve una referencia a un objeto Database subyacente de un
control Data.
Sintaxis
Variable = nombredelcontroldata.Database
El objeto Database creado por el control Data se basa en las propiedades DatabaseName, Exclusive,
ReadOnly y Connect del control.
Los objetos Database tienen propiedades y métodos que puede utilizar para administrar los datos. Puede
utilizar cualquier método de un objeto Database con la propiedad Database de un control Data, como
Close y Execute. También puede examinar la estructura interna de la Database empleando su colección
TableDefs y, a su vez, las colecciones Fields e Indexes de objetos TableDef individuales.
NOTA. Aunque pu ede crear un ob jeto Recordset y pasarlo a la propiedad Recordset de un control
Data, no pu ede abrir u na base de d atos y p asar el objeto Database recié
n cread o a la prop iedad
Database del con trol Data.
DragIcon, DragMode , Enabled Igual que todos los controles.
DefaultType
Devuelve o establece un valor que indica el tipo del origen de datos (Motor Jet u ODBCDirect) que se
usan en el control Data.
Sintaxis
NombreDelControlData.DefaultType = 1
Puede tomar los valores 1 (Usa ODBCDirect) y 2 (Usa el Motor Jet) Pueden usarse también las
constantes dbUseODBC o dbUseJet respectivamente
EditMode
Solo lectura en tiempo de ejecución. Devuelve un valor que indica el estado de modificación del registro
actual.
Sintaxis
Variable = NombreDelControlData.EditMode
Variable tomará uno de los siguientes valores :
dbEditNone
dbEditInProgress
No se está realizando ninguna operación de modificación.
Se ha invocado el método Edit y el registro actual se encuentra en el
búfer de copia.
dbEditAdd
Se ha invocado el método AddNew y el registro actual del búfer de
copia es un registro nuevo que aún no se ha guardado en la base de datos.
La propiedad EditMode es especialmente útil cuando se desea partir de la funcionalidad predeterminada
de un control Data, o cuando no se utiliza un control Data en Visual Basic Edición profesional. Puede
comprobar el valor de la propiedad EditMode y el del parámetro acción del procedimiento del evento
Validate para determinar si se debe invocar el método Update.
También puede comprobar si el valor de la propiedad LockEdits es True y el de EditMode es
dbEditInProgress para determinar si la página de datos actual se encuentra bloqueada.
Exclusive Devuelve o establece un valor (True / False) que indica si la base de datos está abierta para
acceso de un único usuario o de múltiples usuarios.
Font, ForeColor, Height, Index, Left, MouseIcon, MousePointer , Name, igual que el resto de los
controles.
Negotiate Propiedad característica de los controles que tienen la propiedad Align. Establece un valor
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 295
que determina si se muestra un control que puede alinearse cuando un objeto activo del formulario
muestra una o más barras de herramientas. No está disponible en tiempo de ejecución.
Options Devuelve o establece un valor que especifica una o más características del objeto Recordset
de la propiedad Recordset del control Data. Puede ponerse en el cuadro de propiedades o en tiempo de
ejecución. Puede tomar los siguientes valores o nombres de constantes (estos nombres solo si los
introduce en tiempo de ejecución)
1
2
4
8
16
32
dbDenyWrite
En un entorno multiusuario, otros usuarios no pueden realizar
cambios en registros del Recordset.
dbDenyRead
En un entorno multiusuario, otros usuarios no pueden leer
registros (sólo Recordset de tipo tabla).
No se pueden realizar cambios en registros del Recordset.
dbReadOnly
Puede agregar nuevos registros al Recordset, pero no puede
dbAppendOnly
leer los registros existentes.
dbInconsistent Las actualizaciones pueden aplicarse a todos los campos del
Recordset, aunque infrinjan la condición de unión.
(Predeterminado) Las actualizaciones sólo se aplican a los
dbConsistent
campos que no infringen la condición de unión.
64
dbSQLPassThrough
256
dbForwardOnly
512
dbSeeChanges
Cuando se utilizan controles Data con una instrucción SQL en
la propiedad RecordSource, envía la instrucción SQL a una base de
datos ODBC, como SQL Server o Oracle, para su procesamiento.
El Recordset es un desplazamiento sólo hacia adelante. El
único método de movimiento permitido es MoveNext. Esta opción no
puede utilizarse en objetos Recordset manipulados con el control Data.
Genera un error interceptable si otro usuario está cambiando
datos que usted edita.
Para establecer mas de un valor de los descritos, basta con sumar sus valores. También puede
establecer más de un valor para esta propiedad, combinando opciones sumando valores entre sí. Por
ejemplo, para establecer dbReadOnly y dbInconsistent puede utilizar este código:
Data1.Options = dbAppendOnly + dbInconsistent
Para determinar si la propiedad contiene un valor específico, puede utilizar el operador And. Por ejemplo,
para averiguar si el Recordset está abierto para acceso de sólo lectura, podría usar este código:
If Data1.Options And dbReadOnly Then...
Si cambia la propiedad Options en tiempo de ejecución, deberá utilizar el método Refresh para que el
cambio sea efectivo.
ReadOnly Devuelve o establece un valor que determina si la Database del control está abierta para
acceso de sólo lectura.
RecordsetType
Devuelve o establece un valor que indica el tipo de objeto Recordset que desea que cree el control Data.
Los valores o nombre de la constante que puede adoptar son los siguientes:
0
1
vbRSTypeTable
vbRSTypeDynaset
2
vbRSTypeSnapshot
Un Recordset de tipo tabla.
(Predeterminado) Un Recordset de tipo hoja de respuestas
dinámica.
Un Recordset de tipo instantánea.
Si no especifica un RecordsetType antes de que el control Data cree el Recordset, se creará un
Recordset de tipo hoja de respuestas dinámica. (Dynaset)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 296
Recordset
Devuelve o establece un objeto Recordset definido por las propiedades de un control Data o por un
objeto Recordset existente.
Veremos mas adelante las propiedades de un objeto Recordset, propiedades que son en todo aplicables
al Recordset del control Data.
El Recordset es como se adelantó, un conjunto de registros. Si las propiedades Connect,
DatabaseName, Options, RecordSource, Exclusive, ReadOnly y RecordsetType establecidas para el
control Data son válidas, se crea un Recordset automáticamente basándose en dichas propiedades. Ese
será el Recordset del control Data. Pero también puede crearse previamente un Recordset mediante la
instrucción OpenRecordset y forzar que el Recordset del control Data sea justamente ese mediante la
instrucción Set Data1.Recordset = MiRecordset
Sea cual fuera la forma de crearlo, a partir del momento en que el Data tenga su Recordset podemos
referirnos a él, por ejemplo para ir al primer registro (Data1.Recordset.MoveFirst), avanzar un registro
(Data1.Recordset.MoveNext), al anterior (Data1.Recordset.MovePrevious)
ir al último (Data1.Recordset.MoveLast), añadir un registro (Data1.Recordset.AddNew), guardar los
cambios en la Base de Datos (Data1.Recordset.Update), o borrar el registro actual
(Data1.Recordset.Delete)
Si se cambia alguna de las propiedades citadas al principio que cambien el Recordset, es necesario
volver a crearlo. Para ello basta con utilizar el Método Refresh. (Data1.Refresh)
RecordSource
Devuelve o establece la tabla, el objeto QueryDef (Consulta) o la instrucción SQL subyacente para un
control Data. Esta propiedad puede fijarse en el cuadro de propiedades del control data, (el caso mas
usado) o introducirse como código. En los dos primeros casos, lo normal es introducir el nombre de una
tabla o una consulta de las existentes en la base de datos especificada en la propiedad DatabaseName,
nombres que se pueden elegir desplegando la lista que se obtiene haciendo click sobre la flecha que
aparece al lado de la casilla de esta propiedad. Observe que en la lista desplegada figuran los nombres
de las tablas y de las consultas que tiene la Base de Datos elegida en la propiedad DatabaseName. Ni
que decir tiene que para poder introducirla de esta forma es necesario fijar previamente la propiedad
DatabaseName.
Puede introducirse en tiempo de ejecución mediante código con la siguiente expresión :
NombreDelControlData.RecordSource = “NombredelaTabla
Donde NombredelaTabla es una expresión de cadena que especifica el nombre de una Tabla o una
Consulta, de las que componen la base de datos especificada en la propiedad DatabaseName, o una
consulta SQL válida que utiliza sintaxis apropiada para la base de datos especificada en la propiedad
DataBaseName. La propiedad RecordSource especifica el origen de los recursos accesibles a través
de controles enlazados del formulario. Si establece la propiedad RecordSource como el nombre de una
tabla existente en la base de datos, todos los campos de esa tabla serán visibles a los controles
enlazados adjuntos a este control Data. El orden de los registros recuperados lo establece el objeto
Index que selecciona mediante la propiedad Index del Recordset. Si no establece la propiedad Index, los
datos se devolverán sin ningún orden concreto.
Si establece la propiedad RecordSource como el nombre de una consulta existente en la base de datos,
todos los campos devueltos por la consulta serán visibles a los controles enlazados adjuntos al control
Data. El orden de los registros recuperados lo establece la consulta Si en la consulta no se ha
especificado un orden, los datos se devolverán sin ningún orden concreto.
Si establece la propiedad RecordSource como una instrucción SQL que devuelve registros, todos los
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 297
campos devueltos por la consulta a SQL serán visibles a los controles enlazados adjuntos al control
Data. Esta instrucción puede incluir una cláusula ORDER BY para cambiar el orden de los registros
devueltos por el Recordset creado por el control Data o una cláusula WHERE para filtrar los registros.
Después de cambiar el valor de la propiedad RecordSource en tiempo de ejecución, deberá utilizar el
método Refresh para activar el cambio.
Nota. Asegúrese de que cada control enlazado tiene un valor válido para su propiedad DataField. Si
cambia el valor de la propiedad RecordSource de un control Data y, a continuación, utiliza Refresh, el
Recordset identificará el nuevo objeto. Esto puede invalidar los valores de DataField de controles
enlazados y producir un error interceptable.
Las Propiedades Tag, Top, Visible, WhatThisHelpID, Width, igual que el resto de los controles.
METODOS DEL CONTROL DATA
(Se explican aquí los métodos que inciden directamente en el tratamiento de bases de datos. No se
comentan los métodos Drag, Move y ZOrder que son idénticos a los del resto de controles)
Método Refresh
De momento es aplicable al control Data. Veremos que también es aplicable a otros objetos de acceso a
todo Refresh no puede u tilizarse con colecc iones que n o s ean
datos (QueryDef). El mé
persistentes, como Databases, Records ets o Workspaces .
Actualiza los datos del recordset del control data. Imagínese que el control data accede a una base de
datos compartida. Mediante este método actualizamos el contenido del recordset del Data y por lo tanto
los datos presentados a través de los controles enlazados. El método Refresh también se utiliza para
cerrar y volver a generar el objeto Recordset o las estructuras de datos creadas por un control Data.
Sintaxis
NombredelcontrolData.Refresh
Puede utilizar el método Refresh sobre un control Data para abrir o reabrir la base de datos (si han
variado las propiedades DatabaseName, ReadOnly, Exclusive o Connect) y volver a generar el objeto
Recordset indicado por la propiedad Recordset del control.
Método UpdateControls
Actualiza los datos presentes en los controles enlazados a datos vinculados al control Data.
Sintaxis
Nombredelcontroldata.UpdateControls
Utilice este método para restablecer en los controles enlazados sus valores originales, por ejemplo
cuando un usuario modifica los datos y luego decide cancelar los cambios.
Este método produce el mismo efecto que hacer actual de nuevo al registro actual, excepto en que no se
produce ningún evento ni introduce en la Base de Datos los posibles valores que se hubiesen cambiado
en los controles enlazados.
Método UpdateRecord
Guarda en la base de datos los valores actuales de los controles enlazados.
Sintaxis
NombredelcontrolData.UpdateRecord
Puede utilizar este método para guardar el contenido actual de los controles enlazados en la base de
datos. Los cambios introducidos en los controles enlazados a datos se pasan a la base de datos al
cambiar el registro actual, bien mediante código (Data1.Recordset.MoveNext, p.e.) o usando las flechas
del control data, o cambiando el registro actual en un DBGrid. Sin embargo hay circunstancias en las
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 298
que no es apropiado hacer esto. Mediante el método UpdateRecord introducimos los cambios en la BD.
Este método no desencadena el evento Validate.
En algunos casos, la actualización puede no tener lugar, debido a que la operación vulnere las
restricciones de integridad referencial, o que la página que contiene el registro esté bloqueada, o que la
base de datos u objeto Recordset no sean actualizables, o a que el usuario no cuente con el permiso
adecuado para la operación. En cualquiera de estas circunstancias, se producirá un error interceptable.
Estos son los m é
todo s del Co ntrol Data. Este con trol tiene su Records et, y el Record set del
tod os , idé
nti co s a lo s d e un R ecor ds et creado po r códi go .
co ntr ol Data ti ene su s m é
EVENTOS DEL CONTROL DATA
Error
Se produce solamente como resultado de un error de acceso a datos que tiene lugar cuando no está
ejecutando código Visual Basic. Lo explicamos.
El control data carga los datos durante la carga del formulario que lo contiene, abriendo la base indicada
en su propiedad DataBaseName. Imagínese que no existe esa base de datos en el disco. En ese caso
no se producirá ningún interceptable ya que no se ejecuta ningún código escrito. Tampoco se ejecuta
ningún código escrito cuando el usuario hace click en uno de los botones del control data.
El procedimiento Error del control Data se ejecuta cada vez que ocurre un error por una maniobra de
este tipo, y pasa el código de error como parámetro. Analizando el código de error podemos escribir
código en este procedimiento para paliar el error. La ayuda de VB tiene un buen ejemplo del uso de este
procedimiento.
Este ejemplo presenta un cuadro de diálogo Abrir si no se ha podido encontrar la base de datos
especificada en la propiedad DataBaseName del control Data después de haber terminado el evento
Form_Load.
Private Sub Data1_Error (DataError As Integer, Response As Integer)
Select Case DataError
'Si no se ha encontrado el archivo de base de datos se produce el error 3024
Case 3024
'Presentar un cuadro de diálogo Abrir.
CommonDialog1.ShowOpen
End Select
End Sub
Reposition
Se produce después de que un registro se convierte en el registro actual.
Private Sub Objeto_Reposition()
Donde objeto = Nombre del control Data
Cuando se carga un control Data, El primer registro de su objeto Recordset se convierte en el registro
actual, provocando el evento Reposition. Cuando un usuario haga clic en uno de los botones del control
Data, moviéndose de registro en registro o si se usa uno de los métodos Move del objeto Recordset
asociado al control data, como MoveNext, MoveFirst, MovePrevious, los métodos Find, como FindFirst,
FindNext, o cualquier otra propiedad o método que cambie el registro el actual, se produce el evento
Reposition después de que cada registro se convierta en el actual.
Este evento se puede usar para realizar cálculos basándose en los datos del registro actual o para
cambiar el formulario en respuesta a los datos del registro actual.
Validate
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 299
Se produce antes de que un registro diferente se convierta en el registro actual; antes del método
Update (excepto cuando los datos se guardan con el método UpdateRecord); y de los métodos Delete,
Unload o la operación Close.
Private Sub objeto_Validate ([ índice As Integer,] acción As Integer, guardar As Integer)
objeto = Nombre del control Data
ín d ic e = Indice del control Data dentro de una matriz de controles (Si ha lugar)
acción = Un entero que indica la operación que ha producido el evento, como se describe mas
adelante
guardar = una expresión booleana que especifica si los datos asociados han cambiado, como
se describe mas adelante.
Acción puede tomar estos valores :
0
vbDataActionCancel
1
2
3
4
5
6
7
8
9
10
11
vbDataActionMoveFirst
vbDataActionMovePrevious
vbDataActionMoveNext
vbDataActionMoveLast
vbDataActionAddNew
vbDataActionUpdate
vbDataActionDelete
vbDataActionFind
vbDataActionBookmark
vbDataActionClose
vbDataActionUnload
Cancela la operación cuando se sale del
procedimiento Sub.
Método MoveFirst.
Método MovePrevious.
Método MoveNext.
Método MoveLast.
Método AddNew.
Operación Update (no UpdateRecord).
Método Delete.
Método Find.
La propiedad Bookmark no ha sido definida.
Método Close.
El formulario se va a descargar.
Los valores de guardar son:
True
False
Los datos asociados han cambiado.
Los datos asociados no han cambiado.
El evento Validate se usa para realizar las últimas comprobaciones sobre los registros que se van a
escribir en la base de datos.
Vea la ayuda de Visual Basic para mayor detalle de este evento.
CONTROLES ENLAZADOS A DATOS
Los controles enlazados a datos son aquellos que pueden presentar datos de una base de datos, a
través de un control Data. Los controles enlazados a datos permiten crear aplicaciones con acceso a
datos con muy poco código, o incluso ninguno. Para utilizar cualquiera de estos controles enlazados
conectables a datos debe incluir uno o más controles Data en un formulario. El control Data establece un
enlace entre la base de datos y los controles enlazados para la manipulación de los datos. El control
Data que sirve de enlace entre la Base de Datos y los controles enlazados debe estar obligatoriamente
en el mismo formulario que los controles.
Los controles asociados a datos tienen todos la propiedad DataSource, que es la propiedad donde se
debe poner el nombre del control Data asociado a ellos. Existen en Visual Basic trece controles
enlazados a datos, además del control Data :
Data Ya comentado, se utiliza para tener acceso a los datos de las bases a través de controles
enlazados de un formulario. Crea y administra los objetos Database y Recordset para su uso por parte
de los controles enlazados. Requerido para su uso con todos los demás controles enlazados.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 300
DBCombo Se utiliza para obtener una combinación enlazada formada por un cuadro de lista y un
cuadro de texto. La lista puede llenarse automáticamente a partir de un control Data. El usuario puede
elegir un elemento de la lista o introducir un valor en el cuadro de texto. Puede utilizarse para
proporcionar acceso de lectura / escritura a un campo de texto específico seleccionado en la lista.
DBList Se usa para mostrar una lista generada a partir de un control Data en la que el usuario puede
elegir un elemento. La lista puede rellenarse automáticamente desde un control Data, y puede
proporcionar acceso de lectura / escritura a un campo de texto específico seleccionado en ella.
DBGrid Se utiliza para mostrar a la vez todos los registros del recordset del control Data. El DBGrid se
rellena automáticamente con todos los registros, y muestra todos los campos del recordset de control
Data, formando una cuadrícula con filas y columnas. El usuario puede elegir un elemento de la
cuadrícula para variar el valor en ese campo y registro o introducir un nuevo registro. El hecho de
colocarse sobre un determinado registro de la cuadrícula, fuerza a ese registro a convertirse en el
registro actual del control Data al que está asociado.
Label Se usa para el texto que el usuario no debe modificar. Puede utilizarse para ofrecer acceso de
sólo lectura a un campo de texto específico.
TextBox Se utiliza para almacenar texto que el usuario puede introducir o modificar. Puede utilizarse
para proporcionar acceso de lectura / escritura a un campo de texto específico.
CheckBox Se utiliza para crear un cuadro que el usuario puede elegir de forma sencilla para indicar si
algo es verdadero o falso, o para mostrar varias opciones entre las que el usuario pueda elegir más de
una. Puede utilizarse para proporcionar acceso de lectura / escritura a un campo booleano o de bit
específico.
ComboBox Se utiliza para obtener una combinación de un cuadro de lista y un cuadro de texto. La lista
se rellena con el método AddItem. El usuario puede elegir un elemento de la lista o introducir un valor en
el cuadro de texto. Puede utilizarse para proporcionar acceso de lectura / escritura a un campo de texto
seleccionado en la lista. Consulte el control DBCombo
ListBox Se utiliza para mostrar una lista en la cual el usuario puede elegir un elemento. La lista se
rellena con el método AddItem. Puede usarse para proporcionar acceso de lectura / escritura a un
campo de texto específico seleccionado en la lista. Consulte el control DBList
PictureBox Se usa para mostrar una imagen gráfica de un mapa de bits, un icono o un meta-archivo en
un formulario. Puede utilizarse para proporcionar acceso de lectura / escritura a un campo de imagen o
binario específico.
Image Se utiliza para mostrar una imagen gráfica de un mapa de bits, un icono o un meta-archivo en un
formulario. Las imágenes mostradas en un control Image utilizan menos recursos que las de los
controles PictureBox. Puede usarse para proporcionar acceso de lectura / escritura a un campo de
imagen o binario específico.
Es un control enlazado a datos de reciente incorporación. Apareció con la versión 5 de
MSFlexGrid
VB y es un control parecido al DBGrid, pero con algunas ventajas y otros inconveniente. En este caso,
estando asociado a un control Data, el MSFlexGrid solamente permite leer datos, no podemos variar el
contenido de ningún registro. Tampoco se mueve el registro actual del control Data cuando
seleccionamos otra fila del MSFlexGrid.
PROPIEDADES RELACIONADAS CON DATOS COMUNES A ESTOS CONTROLES
Los controles enlazados a datos tienen unas propiedades para el acceso a datos basadas en el enlace
con la base de datos a través del control Data. Las propiedades comunes a todos ellos son :
DataSource Fuente de datos. Es el nombre del control Data que lo enlaza con la B.D. Este control Data
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 301
es el que determina la Tabla donde están los campos con los datos. Esta Tabla se determina mediante
la propiedad RecordSource del control Data.
Es el nombre del campo, dentro de la Tabla de la base de datos, que se va a presentar en
DataField
el control enlazado a datos. Esta propiedad no la tiene el DBGrid ni el MSFlexGrid debido a que
presentan todos los campos de la Tabla de la base de datos seleccionada en el control Data.
Si se le ha forzado al control Data la propiedad Recordset, los campos que se pueden mostrar en los
controles enlazados a datos son justamente, los del ese Recordset al que se le ha forzado.
Vamos a estudiar cada uno de los controles enlazados a datos con un poco mas de detalle.
Control Label
Posiblemente el control Label es el control más sencillo para mostrar el contenido de un campo de una
base de datos. Como todos los controles enlazados a datos, el Label permite presentar los datos e
introducirlos en la base a través del control Data. Lo que ocurre con el Label es que su propiedad
Caption no se puede introducir directamente por teclado, y deberá cambiarse por código. Esto puede ser
una ventaja (no hay posibilidad de introducirlo accidentalmente) y un inconveniente, al tener que escribir
código para hacerlo.
El control Label, al poder ser origen (a través del formulario que lo contiene) y destino de un enlace DDE,
esto nos puede resolver muchos problemas de introdución de distintos datos de otras aplicaciones que
no tengan acceso directo a una base de datos.
El control Label, en lo referente al enlace a datos, solamente tiene las propiedades mencionadas de
DataSource y DataField.
Control TextBox
Todo lo dicho del control Label es aplicable al TextBox, que además presenta la particularidad de que en
este control sí se puede escribir directamente desde el teclado. De esta forma podemos introducir datos
o cambiar los existentes en la base de datos.
Control CheckBox
El control CheckBox permite presentar e introducir datos de tipo Booleano. Tiene las propiedades
DataSource y DataField en lo relativo a acceso a datos.
Controles ListBox y ComboBox
Estos controles tienen una característica especial respecto a su comportamiento con el enlace a la base
de datos. La lista no se puede cargar directamente desde la base de datos, sino a través de un control
intermedio, por ejemplo un Label, donde presentaremos un campo de la base de datos. El texto de la
propiedad Caption de este Label se introduce en el ListBox o ComboBox mediante el método AddItem.
Una vez introducidos todos los elementos de ese campo que nos interesen, cada vez que la base de
datos se sitúa sobre el registro correspondiente a uno de los elementos que está en el ListBox o
ComboBox, éste cambia su ListIndex para seleccionar el elemento correspondiente al registro actual del
control Data.
El ListBox puede contener elementos correspondientes a la base de datos y otros ajenos. Puede
emplearse esta característica del ListBox para seleccionar un elemento entre varios elementos tomados
de la BD y otros introducidos por otro procedimiento, con la particularidad de que el ListIndex de este
ListBox irá a posicionarse sobre el elemento de la BD correspondiente al registro actual del Control Data.
Tienen las propiedades DataSource y DataField en lo relativo a acceso a datos.
Controles DBList y DBCombo
Para agregar estos controles debe insertar el OCX Microsoft Data Bound List Controls 6.0
Estos controles tienen dos enlaces a controles data. Uno para rellenar la lista, que se lo debemos indicar
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 302
en la propiedad RowSource, acompañado del nombre del campo con el que la va a rellenar, que
introduciremos en la propiedad ListField, y otro enlace a otro control Data, que se lo debemos indicar en
la propiedad DataSource. El campo de este segundo control Data se lo indicaremos en la propiedad
DataField. El comportamiento de estos dos controles es el siguiente: Mediante el enlace a través de la
propiedad RowSource se rellena la lista, utilizando los datos del campo elegido en la propiedad
ListField. Imaginemos que la tabla a la que nos conectamos con estas propiedades es la Tabla A. La
tabla a la que enlazamos el DBList mediante la propiedad DataSource, le llamamos Tabla B. Con este
invento vamos a pasar un dato desde la tabla A a la tabla B. El dato que vamos a pasar está en la tabla
A en el campo señalado en la propiedad BoundColumn del DBList. El registro de la tabla A de donde
cogemos el dato será el seleccionado en el DBList. El registro de la tabla B donde vamos a meter el dato
será el registro actual de ese control data, control actual que habremos seleccionado mediante cualquier
método. El campo de esa tabla B que vamos a variar será el campo indicado en la propiedad DataField.
(Esto se vuelve a explicar mas abajo, pero para entenderlo no hay mas remedio que realizar una
práctica)
Control PictureBox y Control Image
Pueden mostrar una imagen almacenada en una Base de Datos. Mediante el control Data, se puede
introducir la imagen presente en uno de estos controles en la Base de Datos.
El campo que contenga una imagen en una BD debe ser tipo Objeto OLE (Binario Largo en versiones
anteriores de Access), y el tipo de imágenes que se pueden introducir son los mapas de bits (Archivos
con extensión .BMP), los archivos de icono, (Extensión .ICO) y los metaarchivos. (Metafiles, extensión
.WMF)
Para introducir un gráfico en una BD es mas práctico introducirlo mediante un control Data y un control
Picture o Image que creando por código un Recordset. En realidad deberíamos decir que es el único
método práctico de introducir / sacar imágenes de una Base de Datos
Control DBGrid
Es posiblemente el control que más se use para presentar y modificar datos de una B.D. El control
DBGrid presenta todos los registros y todos los campos de la Base de Datos. Por eso, necesita
obligatoriamente un control Data para poder presentar datos. Otros controles (Label, TextBox, Picture,
etc.) que solamente presentan un dato (un campo de un registro) pueden trabajar sin necesidad de un
control data, creando un Recordset mediante código. (Lo veremos un poco mas adelante). Sin embargo
el control DBGrid, al presentar todos los datos de la base de datos necesita un control Data. Veamos
porqué.
Cuando creamos un objeto Recordset mediante la instrucción : (se verá mas adelante)
Set Mirecordset = MiDataBase.Openrecordset (“Select campo1, campo2 from Mitabla”)
lo que estamos haciendo es seleccionar, de todos los campos que pueda tener la tabla llamada Mitabla,
los denominados campo1 y campo2. Cada vez que seleccionemos un registro, es ese registro solamente
el que se mantiene en la memoria del ordenador, (el registro actual) y de ese registro, solamente
metemos los datos del campo1 y campo2.
Cuando creamos un Recordset mediante un control Data, se meten en la memoria TODOS los registros
de la tabla especificada en el control data. Por lo tanto, al permanecer todos los registros de esa tabla en
memoria, podremos presentar sus valores en el control DBGrid. No lo podremos hacer con un
Recordset creado mediante código, que solamente mantiene un registro en memoria.
Deberemos explicar qué ocurre cuando se crea un Recordset mediante código, y posteriormente se
fuerza a que el Recordset del control data sea igual a ese Recordset creado.
Con el Recordset creado con la instrucción anterior, podemos forzar a un control Data que su Recordset
sea igual al ya creado mediante la instrucción :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 303
Set Data1.Recordset = MiRecordset
En este caso, el control Data1 tomará todos los registros con los campos campo1 y campo2 de la base
de datos y los meterá en la memoria RAM. Así ya podemos rellenar las cuadrículas del control DBGrid.
Observe que una aplicación de acceso a datos ocupará mucha mas memoria RAM si establecemos el
enlace con la base de datos mediante un control Data que si lo hacemos creando Recordsets a medida.
Pero si necesitamos presentar los datos en un DBGrid, no quedará mas remedio que usar un control
Data. Si nuestra aplicación no tiene que presentar en el DBGrid todos los campos de la tabla de la B.D.
podemos crear previamente un Recordset mediante código y a continuación forzar que el Recordset del
control Data sea igual al Recordset creado, utilizando la expresión anterior.
El control DBGrid tendrá tantas columnas como campos tenga el Recordset. El número de filas será
igual al número de registros que tiene la tabla. Si se sobrepasa el espacio físico del DBGrid para poder
presentarlos, aparecerán automáticamente flechas de deslizamiento vertical. El ancho de las columnas
puede cambiarse mediante la propiedad Width del objeto Columns del DBGrid.
DBGrid1.Columns(n).Width = Valor
Donde n es el número de la columna (la primera es la 0) y el valor debe expresarse según las unidades
de medida (ScaleWidth) del Formulario que lo contiene.
Del control DBGrid podemos destacar estas propiedades :
AllowAddNew
Devuelve o establece un valor que indica si el usuario puede agregar nuevos registros al objeto
Recordset subyacente a un control DBGrid.
La última fila que se muestra en el control DBGrid se deja en blanco para permitir a los usuarios
introducir nuevos registros. Si la propiedad AllowAddNew es False, los usuarios no pueden establecer
el foco en dicha fila.
El Recordset subyacente puede, por otras razones, no permitir inserciones incluso en el caso de que la
propiedad AllowAddNew sea True. En este caso, se producirá un error si el usuario intenta agregar un
registro.
AllowDelete
Devuelve o establece un valor que indica si el usuario puede eliminar registros del objeto Recordset
subyacente a un control DBGrid.
Utilice la propiedad AllowDelete para impedir que los usuarios eliminen registros del conjunto de
registros a través de la interacción con el control DBGrid.
El objeto Recordset subyacente puede, por otras razones, no permitir eliminaciones incluso en el caso de
que la propiedad AllowDelete sea True. En este caso, se producirá un error si el usuario intenta eliminar
un registro.
AllowRowSizing
Devuelve o establece un valor que indica si un usuario puede modificar el tamaño de las filas del control
DBGrid.
Sintaxis
nombre.AllowRowSizing = [True / False]
Si la propiedad AllowSizing es True, el puntero del mouse se convierte en una flecha de doble cabeza
(Size N S) cuando se sitúa sobre el divisor de filas entre selectores de registro, y el usuario puede
modificar el tamaño de las filas mediante arrastre. Cualquier cambio de tamaño de columna provoca un
evento RowResize.
AllowUpdate
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 304
Devuelve o establece un valor que indica si un usuario puede modificar datos del control DBGrid.
Sintaxis
nombre.AllowUpdate = [True / False]
Cuando la propiedad AllowUpdate es False, el usuario puede aún desplazarse a través del control
DBGrid y seleccionar datos, pero no puede modificar ninguno de los valores; cualquier intento de hacerlo
se ignora.
Puede también hacer uso de las propiedades del objeto Columns para hacer que columnas individuales
del control DBGrid sean de sólo lectura, pero los valores de la propiedad AllowUpdate tienen prioridad
sobre los valores establecidos para las columnas (sin modificar éstos).
Nota El objeto Recordset puede no permitir actualizaciones incluso si AllowUpdate es True para el
control DBGrid; en este caso se produce un error interceptable cuando el usuario intenta cambiar el
registro.
ColumnHeaders
Devuelve o establece un valor que indica si los encabezados de columna se muestran en el control
DBGrid.
Sintaxis
objeto.ColumnHeaders = [True / False]
Si es True se muestran los encabezados de columna del control DBGrid, y si es False no se muestran.
DataMode
Establece un valor que especifica si el control DBGrid funciona en modo enlazado o no enlazado. Esta
propiedad no está disponible en tiempo de ejecución.
Los valores que puede tomar la propiedad DataMode son:
0-Bound. El control DBGrid está enlazado con el control Data.
1-Unbound. El control DBGrid no está enlazado directamente al control Data.
Un DBGrid está enlazado cuando se le asigna un control Data en su propiedad DataSource. En este
caso, presenta sin mas los datos del Recordset de ese control Data. Si le especificamos en la propiedad
DataMode que no esté enlazado, utilizaremos código en los procedimientos del control Data para pasarle
los datos cuando nos interese.
DefColWidth
Devuelve o establece un valor que indica el ancho de columna predeterminado para todas las columnas
del control DBGrid.
Sintaxis
objeto.DefColWidth [= valor]
donde valor es un entero basado en el modo de escala del control.
Si se da a la propiedad DefColWidth el valor 0, el control establece automáticamente el tamaño de todas
las columnas en base al ancho del encabezado de columna o al valor de la propiedad Size del campo
subyacente, seleccionando el más largo de los dos.
RecordSelectors
Los selectores de registros aparecen a la izquierda de las filas en el control DBGrid. Cuando el usuario
elige el selector, el registro completo (fila del control DBGrid) se selecciona.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 305
La propiedad RecordSelectors devuelve o establece un valor que indica si se muestran los selectores
de registro en el control DBGrid.
Sintaxis
objeto.RecordSelectors = [True / False]
El Objeto Columns aplicado al control DBGrid.
El objeto Columns es un objeto no privativo del control DBGrid, que contiene todas las columnas y las
propiedades de las columnas de un control. Podemos cambiar las propiedades de cada una de las
columnas de un DBGrid mediante las propiedades del objetos Columns asociado a él. Por ejemplo, el
encabezamiento de una columna en un DBGrid es, por defecto, el nombre del campo que se va a
presentar en esa columna. Si queremos poner otro encabezamiento a una columna, ejecutaremos la
expresión :
DBGrid1.Columns(0).Caption = "Cabecera"
donde el 0 entre paréntesis significa que estamos afectando a la columna número 0 (la primera por la
izquierda).
Si queremos cambiar su anchura :
DBGrid1.Columns(3).Width = 1000
En este caso estamos fijando la anchura de la columna cuarta por la izquierda a 1000 unidades de
medida de las del Formulario que contiene al DBGrid.
CONTROLES DBList y DBCombo
Los dos controles DBList y DBCombo se implementan de la misma manera. Las dos únicas diferencias
estriban en la forma en que se presenta la información al usuario y la presencia de la porción del control
DBCombo en el cuadro de texto, que se emplea para introducir valores.
Los controles DBList y DBCombo tienen dos modos que pueden utilizarse individualmente o al mismo
tiempo:
Autollenado : Llena automáticamente la lista con un campo seleccionado de entre todos los registros
administrados por el control Data especificado por la propiedad RowSource del control DBList o
DBCombo.
Ac tualizaci ón aut om ática : Enlaza el registro seleccionado en el control a un campo específico del
objeto Recordset administrado por el control Data especificado por la propiedad DataSource .
Esto explicado en otras palabras significa lo siguiente :
En control DBList o DBCombo puede trabajar sobre dos controles Data. Uno para rellenar la lista. El
control Data y el campo que rellena la lista son los especificados en las propiedades R o w S o u r c e y
ListField del control DBList o DBCombo. Respecto a este control Data estos controles funcionan
solamente como receptores de datos : No pueden cambiar el contenido de los registros con los que
rellenan su lista. (Llamemos a esta base de datos Base A en esta explicación)
El otro control Data es el que estos controles usan para introducir datos en su BD asociada. El control
Data y el campo de la BD asociados a estos controles DBList y DBCombo, son los especificados en las
propiedades DataSource y DataField . Es sobre esta base de datos y el campo correspondiente sobre
los que estos controles DBList y DBCombo actúan cambiando o introduciendo datos. (Llamemos a esta
otra base de datos Base B)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 306
Basta con seleccionar un elemento de la lista (que pertenece a la base A) y un campo (X) del registro de
la base A al que pertenece ese elemento se colocará en el campo correspondiente (el indicado en la
propiedad DataField del control DBList o DBCombo) de la base B. En el caso del DBCombo, podemos
escribir directamente el dato en su caja de texto en vez de seleccionarlo de la lista.
Ese campo (X) cuyo dato pasamos de la base A a la base B no tiene porqué ser el elemento que vemos
en la lista. Puede ser otro campo de la base A. Será el que introduzcamos en la propiedad
B o u n d C o l u m n del DBList o DBCombo. Es la propiedad que viene a continuación. Léasela con la
atención que se merece.
Propiedad BoundColumn
Devuelve o establece el nombre del campo de origen de un objeto Recordset que se utiliza para
suministrar un valor de datos a otro Recordset.
Resumamos. En un DBList o DBCombo presentamos en su lista un determinado campo de una BD. Esa
BD tendrá mas campos. Un poco mas arriba decíamos que ese elemento de la lista podíamos pasarlo a
otra BD (La especificada en la propiedad DataSource , y en su campo DataField ). ¿Podríamos pasar a
esa BD, en vez del elemento de la lista, otro campo de esa BD origen ?. Podríamos, por ejemplo,
presentar en la lista el nombre de una persona, nombre que hemos tomado de un listín telefónico, y en
vez de pasar el nombre que es el que figura en la lista, pasar su número de teléfono, que es otro campo
de la misma BD. La respuesta es SI. Para ello, pongamos en la propiedad B o u n d C o l u m n del DBList o
DBCombo que estamos usando, el nombre del campo que contiene el número de teléfono. Observe que
por defecto, esa propiedad se rellena con el mismo campo que el especificado en la propiedad ListField .
Eso no quiere decir que no se pueda cambiar. Para cambiarlo, haga click en la flecha vertical que
aparece en la casilla de propiedades, y donde verá que aparecen todos los campos de la base de datos
seleccionada en el control Data asociado a este control. También puede cambiarlo en tiempo de
ejecución con la siguiente sintaxis :
nombredelDBList.BoundColumn = nombredelcampo
Con estas ideas expresadas aquí, puede comenzar a leer el texto de ayuda de esta propiedad. No se
desespere si no entiende algo de lo allí expresado.
BoundText
Devuelve o establece el valor de la propiedad BoundColumn de un control DBCombo o DBList pasado
desde o hacia la propiedad DataField después de realizar una selección. Es decir, es el contenido del
campo especificado en la propiedad B o u n d C o l u m n comentada anteriormente.
Esta propiedad está disponible solamente en tiempo de ejecución.
Esta propiedad es de lectura y escritura. Es sencilla de usar para conocer el contenido del campo
especificado en B o u n d C o l u m n . (lectura del valor)
Cuando la queramos utilizar para forzar el valor de esta propiedad a un valor determinado, debemos
utilizar la siguiente sintaxis :
objeto.BoundText [= valor]
En este caso, el DBList o DBCombo intenta buscar un elemento coincidente en el campo especificado en
la propiedad B o u n d C o l u m n de todos los registros de la BD asociada. Si encuentra uno igual , se
establece el valor de la propiedad BoundText basándose en el campo especificado por la propiedad
B o u n d C o l u m n . Si no se encuentra dicha coincidencia, la propiedad BoundText se establece en el valor
Null.
Es decir, si hay coincidencia con algún valor de ese campo, BoundText seguirá con el valor especificado.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 307
Si no la hay, BoundText se pone a Nulo.
MatchWithList
Propiedad solo de lectura. Devuelve True si el contenido actual de la propiedad BoundText coincide con
uno de los registros de la parte de lista del control.
Sintaxis
Variable = objeto.MatchWithList
Si Variable = True el contenido de la propiedad BoundText coincide con uno de los registros de la lista. Si
es False, el contenido de la propiedad BoundText no coincide con ninguno de los registros de la lista.
Cuando introduce un valor en la parte de texto del control DBCombo, la propiedad MatchWithList se
establece como True si el valor introducido es uno de los elementos que aparecen en la lista. Usando
esta propiedad, el código puede interceptar entradas que no están la lista, o proporcionar código para
agregar la nueva entrada a la tabla de origen.
DataChanged
Devuelve o establece un valor que indica que han cambiado los datos del control enlazado por algún
proceso distinto de la recuperación de datos del registro actual. No está disponible en tiempo de diseño.
Sintaxis
objeto.DataChanged [=Variable]
Variable = objeto.DataChanged
‘establece la pr opiedad
‘lee el valor actual de esta propiedad
Variable puede ser True, indicando que los datos que hay actualmente en el control no son iguales que
los del registro actual, y False (Predeterminado) que indica que los datos que hay actualmente en el
control (si los hay) son iguales que los del registro actual.
Comentarios
Cuando un control Data se mueve de un registro a otro, pasa datos desde los campos del registro actual
a controles enlazados al campo específico o el registro completo. Cuando se muestran datos en los
controles enlazados, la propiedad DataChanged se establece como False. Si el usuario o alguna
operación cambia el valor del control enlazado, la propiedad DataChanged se establece como True. Si
pasa a otro registro la propiedad DataChanged no se ve afectada.
Cuando el control Data comienza a mover a otro registro, se produce el evento Validate. Si DataChanged
es True para algún control enlazado, el control Data invoca automáticamente los métodos Edit y Update
para enviar los cambios a la base de datos.
Si no desea guardar los c ambio s de un c ontro l enlazado en la base de datos, puede establecer la
prop iedad DataChanged c om o False en el evento Validate .
MatchEntry
Devuelve o establece un valor que indica cómo el control DBCombo o DBList realiza búsquedas
basándose en la entrada del usuario.
Sintaxis
objeto.MatchEntry = valor
Donde valor es una constante o un valor que define el comportamiento de un control cuando tiene el
enfoque y el usuario introduce uno o más caracteres.
0
vbMatchEntrySimple Coincidencia básica: (Predeterminado) El control busca la siguiente
coincidencia del carácter introducido usando la primera letra de entradas de la lista. Al escribir
repetidamente la misma letra se recorren todas las entradas de la lista que comienzan por esa letra.
1
vbMatchEntryExtended Coincidencia ampliada: El control busca una entrada que coincida con
todos los caracteres introducidos. La búsqueda se realiza a medida que se escriben los caracteres,
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 308
refinando progresivamente la búsqueda.
Cuando la propiedad MatchEntry se establece como vbMatchEntryExtended y el usuario presiona la tecla
de retroceso o espera varios segundos, la cadena de coincidencias de restablece.
SelectedItem (Solo DBCombo)
Devuelve un valor que contiene un marcador para el registro seleccionado en un control DBCombo.
Sintaxis
DBCombo1.SelectedItem
Cuando selecciona un elemento de la parte de lista del control DBCombo, la propiedad SelectedItem
contiene un marcador que puede utilizar para reposicionar el registro seleccionado en el Recordset como
especifica la propiedad RowSource.
SelText
SelText devuelve o establece una cadena con el texto actualmente seleccionado, o es una cadena de
longitud cero () si no hay caracteres seleccionados.
VisibleCount
Devuelve un valor que indica el número de elementos visibles del control DBCombo o DBList.
Sintaxis
objeto.VisibleCount
La propiedad VisibleCount devuelve un entero desde 0 al número de elementos visibles del control. Un
elemento se considera visible únicamente si una parte del texto es visible.
VisibleItems
Devuelve una matriz marcadores, uno para cada elemento visible de la lista del control DBCombo o
DBList.
Sintaxis
objeto.VisibleItems
Estos marcadores pueden emplearse para obtener registros individuales del conjunto de registros
empleado para rellenar la lista.
Y aquí se terminan las propiedades de DBList y DBCombo. ¡La lata que dan y lo poco que se
usan!
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 309
Controles Picture e Image para acceso a datos a través del control Data.
Merece la pena hablar del almacenamiento de imágenes en una base de datos. Es posible introducir
imágenes en una base de datos Access. El campo debe ser del tipo Objeto OLE y puede manejarse de
dos formas, una de forma sencilla, mediante un control Data, y otra de forma un poco complicada,
mediante los métodos AppendChunk y GetChunk. Estos dos métodos los veremos un próximo
capítulo. Pero adelanto que es complicado usarlos.
Es muy sencillo sin embargo introducir y presentar imágenes residentes en una base de datos mediante
los controles Picture e Image. Estos controles son enlazados a datos y pueden guardar una imagen o
presentarla. Basta para ello poner los valores adecuados en las propiedades DataSource y DataField
para elegir un campo tipo Objeto OLE de la base de datos y está el problema resuelto. Sobre todo para
presentar la imagen, que lo hace automáticamente. No es lo mismo para introducir los datos, pero
también es muy sencillo.
Basta para ello disponer de un CommonDialog, por ejemplo, para buscar una imagen dentro del disco. El
fichero puede ser un BMP, JPG o WMF. Abrimos el CommonDialog (CD1) y buscamos la imagen
deseada. A continuación la cargamos en el Control Picture o Image que está enlazado a datos mediante
el método LoadPicture. Para introducir la imagen en la base de datos basta con cambiar de registro, o
utilizar el método UpdateRecord del control Data.
Para presentar una imagen es preferible usar el control Image con la propiedad Stretch = False a usar el
control Picture. Con el Image y esa propiedad puesta a False, siempre veremos la imagen con el tamaño
diseñado en el formulario. Hacerlo con el control Picture se puede, pero es algo mas complicado.
Pese a que, como se ha visto, se pueden meter imágenes en la base de datos Access, no es
aconsejable hacerlo debido al volumen tan grande de datos que genera. Es preferible guardar la imagen
en el fichero con la imagen, y meter en la base de datos la dirección completa del fichero. Para abrirlo no
hay mas que leer la dirección del fichero, y presentarlo en el Picture o Image mediante el método
LoadPicture.
Control MSFlexGrid
El control MSFlexGrid es un control similar al DBGrid, pero pensado fundamentalmente para enlazarlo a
datos a través del control Adodc1 (El control similar al Data en ADO). Sin embargo también funciona con
el control Data, aunque con prestaciones reducidas. Estando enlazado al control Data, muestra los datos
solo para lectura. Tampoco permite cambiar el registro actual del control Data haciendo click sobre una
de las líneas del MSFlexGrid. Estas dos condiciones le hacen el control ideal para presentar todos los
datos del control Data para aquellos casos en los que no se permite cambiarlos al usuario.
Nota final al control Data
Puede ver en la información d e Microsoft palabras como “los antiguos controles Data y Control de datos
remotos (RDC)”.
No se desanime. El control Data y DAO tienen mucho que decir todavía en la
programación en Visual Basic. Efectivamente hay controles más modernos creados mediante la
tecnología ActiveX que aportan unas prestaciones mayores que estos dos controles. Y formas de acceso
a datos mucho más modernas y abiertas que el motor Jet. Pero tienen también su contrapartidas.
Estudie bien el control Data y el acceso a través de DAO. Llevará mucho camino recorrido para estudiar
posteriormente ADO.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 310
Visual Basic Guía del estudiante Cap. 12
Objetos DAO
ACCESO A BASES DE DATOS SIN UTILIZAR EL CONTROL DATA
En el capítulo anterior hemos visto los controles capaces de acceder a un Base de Datos, enlazados
mediante un control Data. Se comenzó a exponer que no es necesario usar un control Data para acceder
a leer datos, añadir registros o cambiar su contenido. Y es más. Comenzaremos ahora a ver que el
control Data pese a que puede evitarnos gran cantidad de líneas de código, nos hace perder el control
respecto al programa. Es normal. El control Data se ha desarrollado para realizar un trabajo muy
estándar. Si nuestra aplicación se separa un poco de lo normal, lo mas probable es que necesitemos
realizar las operaciones mediante código. Esto no quiere decir que el Data haya que dejarlo en desuso.
Será necesario en aquellas aplicaciones en las que se va a usar un control DBGrid, pues como se
recordará, mediante el uso de un control Data metemos en memoria RAM todo el contenido de la base
de datos relativo al Recordset que hemos creado. El co ntr ol Data s erá neces ario en aquell as
aplicaciones donde utilicemos un DB Grid, un DBList o un DBCom bo. Veremos mas adelante que
también será necesario cuando queramos gu ard ar im ágen es en una Base de Datos.
El control Data también permite consultas más rápidas a la BD. El hecho de guardar el contenido
completo del Recordset en la memoria hace que cualquier consulta sea más rápida. Eso sí, estamos
empleando mucha más memoria RAM.
Pero en este capítulo vamos a ver como se pueden manejar bases de datos utilizando otros objetos de
acceso a datos. Concretamente los objetos DAO.- (Data Access Objet).
Los objetos DAO utilizan el Motor de Bases de Datos Jet de Microsoft y trabajan directamente sobre
el fichero que contiene la base de datos. Existen otros objetos de acceso a datos, como ha podido ver en
el capítulo anterior, que no trabajan directamente sobre el fichero, sino sobre una conexión ODBC que
enlaza con la base de datos. Son los objetos RDO y ADO, cuyo estudio se realizará en capítulos
posteriores. Estos últimos tipos son mas modernos, pero no tienen algunas prestaciones que tienen los
DAO, debido precisamente a que no trabajan directamente sobre el fichero. Centrémonos sobre los
objetos DAO
Estos objetos, pese a que no tienen representación en la interface gráfica, son objetos Visual Basic
como los demás, y nos podremos referir a ellos por su nombre como hacíamos con todos los controles.
Eso sí, debemos declararlos como se declaran las variables, y siguen siendo válidos los criterios de
declaración de variables en cuanto al ámbito de aplicación. Si declaramos un DAO en un procedimiento,
no nos podremos referir a él fuera de ese procedimiento. Si queremos que sea válido en toda la
aplicación deberemos declararlo en la sección de declaraciones de un módulo, o en la sección de
declaraciones de un formulario si fuese suficiente ese ámbito para nuestra aplicación.
La primera sorpresa suele ocurrir a la hora de declarar un objeto. Por ejemplo, para declarar un objeto
tipo DataBase debemos hacerlo con la siguiente declaración:
Dim MiBaseDatos As DataBase
Y al ejecutar el programa puede ocurrirle el siguiente error: Error de compilación. No se ha definido el
tipo definido por el usuario.
Lo que le está ocurriendo es que su programa no conoce el tipo de variable DataBase. Para que la
conozca, debe agregarle una referencia. Vaya a Proyecto | Referencias … de la barra de menú y
seleccione Microsoft DAO 3.51 Objet Library
Haga click en Aceptar y ya tiene agregada esa
referencia a su programa. Agregar una referencia significa que le ha dicho a su programa que puede
hacer uso de una colección de DLLs donde podrá encontrar la definición del objeto o la variable que no
encuentra. Ahora ya no le dará el error anterior, pues en esa DLL que acaba de agregarle a su programa
está la explicación al secreto de lo que es un objeto DataBase.
Verá que hay mas referencias parecidas a Microsoft DAO 3.51. (Las versiones 2.0, 2.1, 2.5/3.5, y si ha
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 311
instalado Access2000 tendrá la 3.6) Existen tantas versiones distintas como versiones de Access. En
realidad esta DLL no es mas que un componente de Access que podemos usar, al igual que lo hace
Access, para gestionar una base de datos. Debe elegir la versión mas alta, pero con cuidado. La versión
3.5 corresponde a la versión de Access 97. Cuando cree con su programa una base de datos con esta
versión, no podrá abrirla con Access 2.0 No se olvide de la teoría de la compatibilidad de Microsoft, que
dice que cualquier versión que Microsoft considere obsoleta no debe reconocer los datos guardados por
versiones más modernas del mismo programa. Piense si es posible que alguien que vaya a abrir una
base de datos guardada con su aplicación dispone de una versión anterior de Access. Por ejemplo,
cuando se está escribiendo este libro, está recién aparecido Access 2000. ¿Cree que es oportuno en
estos momentos, en los que todavía se está introduciendo en muchos usuarios Access 97 usar una DLL
que nos cree bases de datos que solamente puedan ser abiertas por Access 2000?.
La versión Microsoft DAO 3.6 corresponde a Access 2000. Si ha instalado este programa le aparecerá
esa referencia en la lista de referencias. No se sorprenda si antes de instalar Access 2000 no tenía esa
referencia y después de la instalación sí. Si crea una BD con la versión 3.6 no podrá abrirla con Access
97 ¡Esta es la compatibilidad hacia delante de Microsoft!
Objetos DAO de acceso a datos
Son muchos y tienen estructura jerárquica. Es importante resaltar lo de su estructura jerárquica, ya que
como verá, un objeto DAO crea los objetos DAO inmediatamente inferiores en jerarquía.
Hay que señalar que las colecciones de estos objetos DAO son a su vez objetos de acceso a datos. Esto
hay que explicarlo un poco mejor. Por ejemplo, un objeto Database es un objeto DAO que representa
una base de datos abierta. Al objeto que agrupa a todas las bases de datos abiertas en ese momento le
llamamos Objeto Databases. Si tenemos dos bases de datos abiertas en un determinado momento, el
objeto Databases contendrá dos elementos.
Todos los objetos DAO excepto el dbEngine tienen colecciones. Es lógico. El dbEngine, como verá mas
adelante, es precisamente el Motor de Bases de Datos Jet y solamente existe uno. Comenzaremos
precisamente por él la explicación de los objetos DAO.
El dbEngine es el motor Jet. Y como vimos en el capítulo anterior, la versión 3.5 puede trabajar
directamente sobre el fichero de la base de datos o a través de una conexión ODBC. En el primer caso
decimos que está trabajando en el espacio de trabajo Microsoft Jet Si le hacemos trabajar a través de
ODBC decimos que estamos trabajando en el espacio de trabajo ODBCDirect
Los objetos que emplea en cada uno de los espacios de trabajo pueden verse en las figuras 20.1 y 20.2.
Puede observarse que tiene muchos mas objetos en el espacio de trabajo Microsoft Jet que en el de
ODBCDirect. Es lógico. Con el primero nos permite CREAR bases de datos, y por lo tanto necesita
tener objetos tales como el Tabledef, Index o Relation. Lo verá un poco mas adelante.
El objeto dbEngine tiene los siguientes métodos, propiedades y colecciones
Métodos CreateWorkspace, CompactDatabase, RepairDatabase, Idle, RegisterDatabase
Propiedades DefaultPassword, DefaultUser, IniPath, LoginTimeout, Version
Colecciones Errors, Properties, Workspaces
Veremos estos métodos y propiedades según vayamos avanzando en el capítulo
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 312
Fig. 20.1 Objetos DAO para el espacio de trabajo Microsoft Jet
En esta figura pueden verse los objetos y sus colecciones. Las colecciones llevan el nombre en plural.
Parece un poco complicado, y posiblemente lo será. Lo cierto es que para el trabajo que se hace
normalmente con bases de datos este diagrama queda bastante reducido. No se extrañe tampoco de ver
que objetos como el Fields y el Field existen en varios niveles. Lo verá mucho mejor mas adelante.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 313
Fig. 20.2 Objetos DAO para el espacio de trabajo ODBCDirect
Este modelo parece un poco mas asequible. La razón es que no hace todo lo que hace el espacio de
trabajo Microsoft Jet.
Objeto Workspace
Un objeto Workspace define una sesión de trabajo para un usuario específico. Una sesión de trabajo es
precisamente eso, una sesión de trabajo en el más puro estilo informático. Pueden existir varias
sesiones de trabajo, pero en la mayoría de los casos eso no es lo normal. Será necesario crear varias
sesiones cuando necesitemos imponer restricciones de acceso a una base de datos, cuando tengamos
que usar Transacciones (*) en un sistema multiusuario, y en algún caso más. Las sesiones de trabajo
tienen dueño (Usuario) y una palabra clave para acceder a ellas.
Pero lo normal es tener solamente una sesión abierta. Y visual Basic nos facilita este caso abriendo una
sesión de trabajo automáticamente. Cuando se inicia Visual Basic, se crea un Workspace con palabra
clave y nombre de usuario Admin. Este Workspace es precisamente el que ocupa el número cero de la
colección de Workspaces. Es decir, es el Workspaces(0).
No se preocupe de que ahora mismo no lo entienda. Ya lo entenderá. Pero hay que exponerlo ahora. El
objeto Workspace contiene:
Para el espacio de trabajo Microsoft Jet:
Grupos de trabajo , que es un grupo de usuarios de un entorno multiusuario que comparten
datos y el mismo sistema de base de datos.
Grupos de usuarios , que es una colección de cuentas de usuario. Estos objetos, que no son
objetos de acceso a datos, sino de explotación de los recursos del sistema, están enfocados a la
seguridad respecto al acceso a las bases de datos que se trabajan conjuntamente. No tendría
sentido hablar aquí de ellos si no fuese porque encontrará referencias a estos objetos
continuamente en la ayuda de Visual Basic.
Bases de Datos (Databases). Este el objeto que ahora nos interesa del objeto Workspace. Un
objeto Database es una base de datos abierta.
Para el espacio de trabajo ODBCDirect:
Conexión , que representa una conexión con una base de datos a través de ODBC
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 314
Bases de Datos (Databases).
Ya podemos comenzar a comprender una diferencia entre ambos espacios de trabajo. En el Microsoft
J et tenemos Usuarios y Grupos de Usuarios. En el espacio ODBCDirect no los tenemos, ya que el
permiso o denegación de acceso de uno u otro usuario a una base de datos se establece cuando se
crea (en Windows) la conexión ODBC. En el espacio ODBCDirect tenemos un objeto llamado
Connection, objeto que no tenemos en el Microsoft Jet ya que con este sistema accedemos
directamente al fichero de la base de datos. No necesitamos ninguna conexión establecida previamente.
Al objeto Workspace se le puede dar un nombre definido por el usuario. Ese nombre habrá que
declararlo como nombre de una variable objeto Workspace :
Dim Misesion as Workspace
La declaración de la variable Objeto tiene las mismas características que cualquier variable en cuanto al
ámbito en el que se puede usar. Para que pueda usarse en toda la aplicación deberemos declararla en
un Módulo con la sentencia Public
Public Misesion as Workspace
Esta advertencia es válida para la declaración de todos los objetos DAO.
Una vez declarado el nombre del objeto Workspace, hay que crearlo. En realidad, y tal como citábamos
mas atrás, cada vez que se inicia una sesión de Visual Basic, se crea automáticamente un Workspace.
El número 0 A este Workspace no podemos ponerle ningún tipo de palabra de acceso, ya que se la ha
puesto VB : Admin. Utilicemos este Workspace, el número 0 de la colección Workspaces, para
comenzar a trabajar. Tiempo tendremos mas adelante de ver como se crea un Workspace. Para hacer
que Misesion sea ese Workspace que crea automáticamente VB basta con ejecutar la siguiente línea de
código
Set Misesion = Workspaces(0)
Pero si no queremos aprovechar este Workspace creado automáticamente por Visual Basic, y queremos
usar otro, usemos el método CreateWorkspace. Se verá al final del capítulo.
Creación de Objetos DAO
Para crear un objeto DAO (Cualquiera que sea) debemos usar una forma que se va a repetir a lo largo
de toda su vida profesional, mientras trabaje con Visual Basic y Bases de Datos:
Set ObjetoDAOInferior = ObjetoDAOSuperior.Método ( Aquí .... alguna cosa )
Logicamente el término Aq uí.... algu na cos a va a depender de cada método y de lo que Vd. quiera
hacer, pero la estructura Set DAOInferior = DAOSuperior.Método ( - - - - - - - - - - ) se mantendrá en
todas las operaciones de creación y manipulación de objetos DAO. Esta sintaxis es tan simple que un
profesor de Visual Basic decía que es como un “ ju eg o d e n iñ
o s ” No lo olvide y se le quitará el miedo al
manejo de bases de datos mediante código. Posiblemente hasta ahora le haya parecido muy difícil y
haya optado por usar el control Data para todas sus aplicaciones. Si recuerda este Ju eg o de n iños verá
que es más sencillo crear objetos DAO que poner un control Data en un formulario.
Comenzaremos a explicar la operación de bases de datos mediante DAO explicando como se crean
bases de datos Access mediante Visual Basic. ¿Para que se van a crear bases de datos mediante un
programa si puedo hacerlo directamente con Access? . Esta pregunta me la han hecho los alumnos
durante todos mis años de docencia. La única respuesta para ello es que deseo que Vd. sea
programador, no usuario de ofimática.
Objeto Database
Un objeto Database representa una base de datos abierta . Una colección Databases contiene todos
los objetos Database abiertos en un objeto Workspace del motor de bases de datos Microsoft Jet.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 315
Un objeto Database puede crearse, bien porque hemos creado una base de datos mediante el
procedimiento CreateDataBase, o porque hemos abierto una base de datos existente mediante el
procedimiento OpenDatabase. En cualquiera de los dos casos, el objeto Database existe hasta que lo
cerremos (mediante el método Close) o hasta que cerremos la aplicación.
Al objeto Database se le debe dar un nombre definido por el usuario. Eso sí, hay que declararlo como
una variable objeto Database
Dim MiDataBase As Database
El nombre que le demos al objeto DataBase no tiene nada que ver con el nombre del fichero que alberga
esa base de datos. El objeto DataBase es la base de datos que creamos en la memoria RAM del
ordenador.
Colección Databases
Es el conjunto de Objetos Database existentes. La colección Databases
pertenece al Workspace.
Crear una Base de Datos ACCESS. Método CreateDatabase
Para crear una base de datos deberemos utilizar el método CreateDatabase. Previamente debemos
declarar el nombre que queremos dar al objeto DataBase que se va a crear como un objeto Database :
Dim MiBaseDatos as Database
Si tenemos declarado un Workspace llamado Misesion mediante la declaración :
Dim Misesion as Workspace
Y hacemos que Misesion sea el Workspace creado automáticamente por VB
Set Misesion = Workspaces (0)
podremos usar el método del Workspace CreateDatabase para crear ese objeto Database. Recuerde
que el objeto Database NO es el fichero que va a contener la base de datos sino que es una estructura
de base de datos que está de momento en la memoria RAM del ordenador. El fichero se creará
posteriormente cuando cerremos el objeto Database. El nombre del objeto Database tampoco tiene
porque coincidir con el nombre del fichero que se va a crear. En el ejemplo que veremos mas adelante,
el nombre del objeto Database es MiBaseDatos y el nombre del fichero es MiBase.Mdb.
La sintaxis del método CreateDataBase es el “juego de niños” citado antes:
Set ObjetoDAOInferior = ObjetoDAOSuperior.Método ( Parámetros )
En nuestro caso el Objeto DAO superior es el Workspace Misesion, y los parámetros que hay que pasar
en este caso son:
Nombre (y Path) del fichero de la base de datos
Idioma, para permitir la ordenación alfabética de los datos. Para los idiomas español, inglés y francés
debe usar dbLangGeneral.
Opciones, que le permite elegir la versión de la base de datos a crear (Equivalente a la versión de
Access) y si deseamos crear una base de datos cifrada. Si no pone nada en este parámetro le crea una
base de datos sin cifrar, y de la última versión que le permite la referencia elegida para el motor de bases
de datos (Microsoft DAO 3,51, por ejemplo)
Vayamos al ejemplo:
Set MiBaseDatos = Misesion.CreateDatabase (“C:\MiCarpeta\MiBase.MDB”, dbLangGeneral)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 316
Si ahora cierra el programa le creará la Base en el disco. Ejecute Access y abra la BD
C:\MiCarpeta\MiBase.MDB. ¡Ya Existe! Pero observará que está completamente vacía. Es normal. Una
Base de Datos ACCESS tiene tablas. Y de momento no hemos escrito ningún código para crear esas
tablas. Vamos a seguir creando esta base de datos, al tiempo que explicamos el resto de los
procedimientos que hay que usar para ello.
El Método CreateDataBase Crea un nuevo objeto Database, guarda la base de datos en disco y
devuelve un objeto Database abierto.
Vaya a la ayuda de VB. Verá que la sintaxis de este método es:
Set MiBaseDatos = Misesion.CreateDatabase (nombre_base, escenario, opciones)
MiBaseDatos es el nombre del objeto Database por el cual nos referiremos a esa base de datos, NO el
nombre del archivo con el que quedará guardada en el disco.
Misesion es el nombre del objeto Workspace existente que contendrá la base de datos. Si se omite este
argumento, se utilizará el objeto Workspace predeterminado - Workspaces(0) – e incluso, si no se pone
nada, usará ese Workspace predeterminado.
nombre_base es el nombre del archivo de base de datos que se va a crear. Es decir, el nombre del
archivo en el disco. Puede ser una ruta completa y un nombre de archivo, como por ejemplo
"C:\MiCarpeta\MiBase.MDB". Si no se indica una extensión, se agregará .MDB. Si la red lo admite,
también puede especificar una ruta de red, como por ejemplo "\\MISERVID\MICOMP\MIDIR\MIBD". Con
este método sólo pueden crearse archivos de base de datos .MDB. (ACCESS)
escenario es una expresión de cadena utilizada para especificar dos cosas: el orden alfabético que se
va a usar en esta base de datos, (Obligatorio) que denominaremos inf_local y el Password o palabra
clave que quiere usar para restringir su uso. Este Password es opcional. Debe especificar el
argumento inf_local o se producirá un error. Consulte la tabla de constantes para inf_local incluida
más adelante en este tema.
En el argumento Opciones puede combinar varias opciones, según se especifica a mas adelante.
Puede combinar varias opciones sumando las constantes correspondientes.
Valores de los parámetros
En el argumento inf_local se suministra información de la lengua empleada para especificar la
propiedad CollatingOrder del texto para las comparaciones entre cadenas. Es un argumento
obligatorio. Para los idiomas Inglés, alemán, francés, portugués, italiano y español moderno se usa la
siguiente constante :
dbLangGeneral
No use dbLangSpanish. pues no hace nada especial respecto a dbLangGeneral
Este parámetro es obligatorio. Piense que una vez creada la Base de Datos, alguna vez le pedirá que le
obtenga un Recordset con los datos ordenados alfabéticamente ( acuérdese de la sentencia SQL
ORDER BY Nombredelcampo )
Si desea introducir una palabra clave para restringir el acceso a la base de datos, debe indicarlo a
continuación. Deberá concatenarlo con la inf_local mediante el signo & y separarlo mediante
punto y coma. Hay que poner pwd antes de la contraseña
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 317
dbLangGeneral & ";pwd=NuevaContraseña"
Para el último parámetro, Opciones se pueden usar las siguientes constantes :
Constante
Descripción
dbEncrypt
dbVersion10
Crea una base de datos codificada.
Crea una base de datos que utiliza la versión 1.0 del motor
Microsoft Jet.
Crea una base de datos que utiliza la versión 1.1 del motor
Microsoft Jet.
Crea una base de datos que utiliza la versión 2.5 del motor
Microsoft Jet.
Crea una base de datos que utiliza la versión 3.0 del motor
Microsoft Jet. Esta Versión es compatible con la 3.5
dbVersion11
dbVersion25
dbVersion30
de base de datos
de base de datos
de base de datos
de base de datos
Si se omite la constante de codificación, se creará una base de datos no codificada.
El método CreateDataBase abre esta nueva base de datos y devuelve un objeto Database, cuya
estructura y contenido deberá completar utilizando objetos de acceso a datos adicionales. Es decir, crea
una Base de Datos sin nada que deberá rellenarla posteriormente con tablas.
(Advertencia sobre las bases de datos cod ificadas . No piense que al codificar la base de datos va a
mantener sus datos confidenciales en secreto. Access se los guardará codificados, pero se los va a
presentar de forma clara. Utilice para ello el Password, ya que no podrá abrir la base si no se conoce ese
Password. Pero tampoco se fíe mucho. Existen infinidad de craqueadores de contraseñas de Access. El
Password vale para proteger la BD de usuarios no “piratas”. No emplee este p rocedimiento en
aplicaciones en las que necesite verdadera confidencialidad.
Objetos DAO para introducir en una base de datos
Estos objetos que se pueden añadir son : Objetos TableDef, TableDefs, Field, Fields, QueryDef,
QueryDefs. Para hacer las cosas poco a poco nos fijaremos solamente en las tablas y los campos.
(Objetos Tabledef y Field)
El Objeto TableDef es una tabla de una base de datos ACCESS. El Objeto TableDefs es la colección
que contiene todas las tablas de la base de datos
Un objeto Field representa un campo dentro de una tabla Access. La colección Fields contiene todos los
campos de una tabla. Verá mas adelante que también hay objetos Field en otros objetos DAO (Index,
QueryDef, Recordset, Relation), pero de momento vamos a fijarnos solamente en las tablas.
Crear una Tabla. Método CreateTableDef.
Crea un objeto Tabledef, que no es ni más ni menos que la estructura de una tabla Access, pero que de
momento está en la memoria RAM del ordenador. Cuando esa estructura se pase al fichero de la base
de datos en el disco, será una Tabla que podemos ver cuando abramos la BD con Access.
El objeto Tabledef debe crearlo un objeto DataBase. Puede ser perfectamente el objeto Database
creado anteriormente. Pero seguramente lo ha cerrado (cerrando el programa, simplemente) para poder
ver con Access la base de datos que acaba de crear. Puede volver a crear el objeto DataBase abriendo
la base de datos. Aunque se le explicará mas tarde, le adelanto el método para abrir una base de datos
existente en el disco:
Set MiBaseDatos = Misesion.OpenDatabase (“C:\MiCarpeta\MiBase.MDB”)
Declaremos ahora el nombre que quiere ponerle al objeto Tabledef que va a crear: (MiTabla1)
Dim Mitabla1 As Tabledef
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 318
Si queremos introducir varias tablas en la BD deberemos declarar tantos objetos Tabledef como tablas
necesitemos:
Dim MiTabla2 as Tabledef, MiTabla3 as Tabledef, ……
y crearemos las tablas necesarias mediante el método CreateTableDef
Si acude a la información de VB para ver los parámetros que hay que pasar en el método
CreateTableDef verá que son muchos: ([nombre[, atributos[, origen[, conexión]]]]) Se explicará para que
sirven todos ellos, pero de momento nos quedamos únicamente con el primero: Nombre, que es el
nombre que podrá ver en Access como nombre de la tabla que va a crear.
Set Mitabla1 = MiBaseDatos.CreateTableDef (Nombre)
Ejemplo:
Set Mitabla1 = MiBaseDatos.CreateTableDef (“Alumnos”)
Si queremos crear más Tabladefs:
Set Mitabla2 = MiBaseDatos.CreateTableDef (“Profesores”)
Set Mitabla3 = MiBaseDatos.CreateTableDef (“Asignaturas”)
De momento solamente hemos creado uno o varios objetos Tabledef. Pero como siempre, vacíos. Una
tabla tiene campos. Un objeto Tabledef tiene Fields. Debemos crear objetos Field (Campos) para poder
meterlos en los objetos Tabledef que acabamos de crear.
Crear campos. Método CreateField
Crea un objeto Field, que es la estructura de lo que mas tarde será un Campo de una tabla de la BD. El
objeto Field solamente está en la memoria RAM del ordenador. Cuando pase a formar parte de una tabla
será un campo de esa tabla.
El objeto Field debe crearlo el objeto DAO superior a él: el Tabledef. Previamente declararemos los
nombres de los Objetos Field a introducir.
Dim MiCampo11 as Field, MiCampo121 as Field, MiCampo21 as Field
(El Campo11 es el primer campo que meteremos en el Tabledef Tabla1. El Campo12 el segundo, el
Campo21 será el primer campo del Tabledef Tabla2, etc.
Los parámetros que vamos a pasar en este método son:
Nombre
Tipo
Tamaño
Será el nombre de ese campo. P.e. NombreAlumno, Apellidos, etc
Tipo de dato, String, numérico, Date, etc
Sólo para los campos String. Indicará el número de caracteres de ese campo.
Creamos el objeto Field con la siguiente sintaxis
Set MiCampo11 = Mitabla1.CreateField ([nombre[, tipo [, tamaño]]])
(Vea el Anexo 1 Propiedades de los campos al final de este capítulo)
Ejemplos
Set MiCampo11 = Mitabla1.CreateField (“ID_Alumno”, dbText, 8)
Set MiCampo12 = Mitabla1.CreateField (“NombreAlumno”, dbText, 20)
Set MiCampo13 = Mitabla1.CreateField (“Apellidos”, dbText, 25)
Set MiCampo14 = Mitabla1.CreateField (“Edad”, dbInteger)
Set MiCampo15 = Mitabla1.CreateField (“Fecha_Ingreso”, dbDate)
Set MiCampo21 = Mitabla2.CreateField (“NombreProfesor”, dbText, 20)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 319
Se crean todos los campos que se quieren introducir en las tablas. Observe que cada objeto Field debe
ser creado por el objeto Tabledef que lo va a contener. (MiTabla1 crea todos sus campos, MiTabla2 los
suyos, etc)
Ya están todos los campos creados, pero todavía no están metidos en las tablas. Tenemos que
añadirlos a la colección de campos de la tabla que los creó. Esa colección de campos es el Objeto Fields
de la tabla. Se añade mediante el método Append.
MiTabla1.Fields.Append Micampo11
MiTabla1.Fields.Append Micampo12
MiTabla1.Fields.Append Micampo13
MiTabla1.Fields.Append Micampo14
MiTabla1.Fields.Append Micampo15
MiTabla2.Fields.Append Micampo21
Ya tenemos campos formando parte de la colección Fields de las tablas. Ahora debemos añadir las
tablas a la colección de tablas de la base de datos. Esa colección de tablas es el objeto Tabledefs de la
base de datos, es decir, del objeto DataBase. Lo haremos también mediante el método Append
MiBaseDatos.TableDefs.Append Mitabla1
MiBaseDatos.Tabledefs.Append Mitabla2
Si ahora cerramos la base de datos mediante el método Close:
MiBaseDatos.Close
Ya tenemos la base de datos creada en el disco de la misma forma que lo hubiera hecho Access.
Pero puede que le falte algo respecto a una base creada directamente con Access: los Indices y
las Relaciones.
Un índice es una marca que le podemos poner a cada uno de los registros en un campo. Esa marca
puede servir por ejemplo, para ordenar los registros de la BD por ese campo. Puede servir también para
evitar que dos registros tengan el mismo valor para un determinado campo. En el ejemplo que estamos
preparando, el Campo11 (ID_Alumno) queremos que sea un índice, y además que no se pueda repetir el
mismo valor para dos registros distintos, de forma que no puedan existir dos registros con el mismo valor
en ese campo.
Una Relación es una correspondencia entre un campo de una tabla y otro campo de características
similares en otra tabla. Esto nos lleva al concepto de Base de Datos Relacional que seguramente ya
sabe de que se trata. En Access se puede establecer una relación de una forma muy sencilla. En Visual
Basic también. Pero antes de seguir reflexionemos y recordemos lo que hemos hecho hasta ahora.
Observe que, cada vez que creamos un objetos (DataBase, Tabledef, Field) usamos el mencionado
“juego de niños”. El método correspondiente para crear un objeto DAO pertenece al objeto DAO
inmediatamente superior en jerarquía, es decir, CreateDatabase es un método del objeto Workspace,
CreateTableDef es un método del objeto Database, CreateField es un método del objetos TableDef.
Las colecciones pertenecen también al objeto inmediatamente superior en jerarquía al tipo de objetos
que forman la colección. La colección Fields (Objeto Fields) pertenece a un objeto TableDef, la
colección TableDefs (objeto TableDefs) pertenece a un objeto Database, y la colección Databases
(Objeto Databases) pertenece a un objeto Workspace. La colección Workspaces pertenece al
DBEngine, y el DBEngine ya no podemos asignarlo a ningún objeto DAO. Tendremos que decir que
pertenece al sistema.
Recordemos ese “juego de niños” :
Set DAOInferior = DAOSuperior.Método ( - - - - - -)
Hemos visto que después de crear un objeto, debemos añadirlo a la colección a la que debe pertenecer
con el método Append. El procedimiento es siempre el mismo :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 320
Objeto superior.Colección.Append Objeto a añadir
Sigamos ahora perfeccionando la base de datos. Vamos a ver como se crea un Indice.
Crear Indices para los campos. Método CreateIndex
Para crear un índice debe estar creado el campo al que se le va a aplicar el índice. Puede que le parezca
un poco extraño alguno de los métodos que vamos a usar para crear un índice, como por ejemplo volver
a usar el procedimiento CreateField para crear un campo que ya existe. Son las incongruencias que
tiene a veces Visual Basic. Le recomiendo que si no se acuerda bien de cómo se hace, recurra a la
ayuda de VB, que en este caso es exacta y concisa. O si lo prefiere, al ejemplo que ilustra esta Guía del
Estudiante como colofón a este capítulo.
Primer debemos crear el Objeto Index. Se hace mediante el método del objeto Tabledef, CreateIndex.
El índice debe crearlo el Tabledef al que pertenece el campo que queremos que sea índice. La sintaxis
de CreateIndex es:
Set NombreIndice = NombreTabledef.CreateIndex([Nombre])
Donde NombreIndice es el nombre de una variable declarada como tipo de dato objeto Index.
NombreTabledef es el nombre de variable del objeto TableDef que se desea usar para crear el nuevo
objeto Index.
Nombre es una variable de tipo String que da un nombre único al nuevo objeto Index. Este nombre lo
puede ver si abre la base de datos con Access y en la vista de Diseño de la tabla, abre la función Ver |
Indices de la barra de menú.
En nuestro ejemplo:
Declaramos el objeto Index
Dim MiIndice as Index
Creamos el índice
Set MiIndice = MiTabla1.CreateIndex (“Indice1”)
Ya tenemos creado el Objeto Index. Ahora, (y aquí empieza la incongruencia citada) este objeto Index
debe crear el campo que queremos que sea índice. Pero ese campo ya debe existir en el objeto
Tabledef con el que hemos creado el índice (en este caso, en MiTabla1)
Set MiCampo11 = MiIndice.CreateField (“ID_Alumno”, dbText, 8)
El nombre del campo, tipo y tamaño deben coincidir con los datos que sirvieron para crear el
campo en el objeto Tabledef.
Pero un índice puede tener varios campos. Por ejemplo, piense en el código de un objeto en un
inventario. El código es el número que identifica de forma unívoca a un objeto. Un objeto inventariable
(por ejemplo una mesa) tiene un código de grupo (por ejemplo, el 123) Hay muchas mesas dentro de un
inventario, pero todas ellas tienen un número distinto (una tiene el 001, otra el 002, etc) La combinación
de código de grupo más el número del objeto dentro de ese grupo queremos que sea un índice. Ese
índice estará formado entonces por dos campos. En este caso deberemos crear los dos campos:
Set MiCampo11 = MiIndice.CreateField (“C_Grupo”, dbText, 3)
Set MiCampo12 = MiIndice.CreateField (“Numero”, dbText, 3)
Ya tenemos el campo o los campos creados por el índice. Ahora debemos añadirlo (o añadirlos) a la
colección Fields del objeto Index recién creado. Lo hacemos mediante el método Append
MiIndice.Fields.Append MiCampo11
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 321
Si fuesen dos los campos
MiIndice.Fields.Append MiCampo11
MiIndice.Fields.Append MiCampo12
No crea que ya hemos terminado. Un objeto Index tiene propiedades. Una de ellas ya la hemos visto sin
querer, la propiedad Name (nombre del índice, en nuestro ejemplo, Indice1). Otras propiedades son:
Primary - El objeto Index representa la clave primaria de la tabla.
Unique - No permite repetición de valores en ese campo
Required - Indica que todos los campos del objeto Index deben rellenarse.
IgnoreNulls - Indica si permite valores Nulos en los campos del índice.
(Existen además las propiedades Clustered, Foreign, DistinctCount que no se explican para no
complicar mas el tema. Cuando los necesite no tendrá inconveniente en estudiarlos partiendo de la
ayuda de VB)
Para introducir el valor de una de estas propiedades se procede con la siguiente sintaxis:
MiIndice.Uniuqe = True
MiIndice.Primary = True
Ya está creado el índice y tiene ya metido uno o mas campos y todas sus propiedades. Ahora debemos
añadir ese índice a la colección Indexes del Objeto Tabledef.
MiTabla1.Indexes.Append MiIndice
Lo confieso. Cada vez que hago esto en la vida real tengo que volver a leer este procedimiento en la
Guía del Estudiante. Es complicado, pero alguna vez se terminará aprendiendo .
Ya tenemos la base de datos completamente creada. Sin embargo alguien dirá que le falta algo:
Relacionar dos tablas
Relaciones entre tablas Método CreateRelation
Una Relación es una asociación establecida entre dos campos del mismo tipo ubicados en dos tablas
distintas. Se pueden establecer relaciones uno a uno ó uno a varios. Para relacionar un campo con
otros, ese campo debe ser clave primaria. A la tabla que contiene a este campo se le llama Tabla
Principal. A la tabla que contiene el campo (o los campos) relacionados se le llama Tabla Relacionada.
Para crear una relación, usaremos un nuevo objeto DAO : El objeto Relation. Este objeto forma parte de
una colección, que es a su ves otro objeto DAO : el objeto Relations.
Para crear una relación usaremos el Método CreateRelation, que es un método del objeto Database.
(Lógico, una relación se establece entre dos tablas. Por lo tanto, la relación debe pertenecer al objeto
DAO superior jerárquicamente a las tablas: el Objeto Database. Como para cualquier otro objeto DAO,
es necesario declararlo :
Dim MiRelacion as Relation
Para crear la relación deberemos usar el método CreateRelation
Set MiRelacion = MiBaseDatos.CreateRelation ("RelacionUno")
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 322
Una relación se hace entre dos campos. Una relación debe tener campos. Por lo tanto, deberemos hacer
una cosa similar a la que hacíamos para el método CreateIndex, crear los campos mediante el Objeto
Relation que acabamos de crear. Pero esos campos ya deben estar creados en las tablas que se van a
relacionar.
Supongamos que queremos crear una relación en la base de datos creada en el ejemplo anterior, y
queremos relacionar el campo Campo11 que está en MiTabla1 y que lo habíamos hecho clave primaria,
con el campo Campo21 de MiTabla2. MiTabla1 y MiTabla2 son los nombres reales de las tablas, NO
los nombres de los objetos Tabledef.
El ejemplo que trae la ayuda de VB puede ser muy aclaratorio, pero le advertimos lo mismo que para los
índices, paciencia. Una vez creada la relación, podrá comprobarlo visualizándola con el visor de
relaciones del Access
Suponemos que la base de datos está abierta. Si no lo está, la abrimos.
Set MiBaseDatos = Workspaces(0).OpenDatabase("MIBD.MDB")
Creamos el objeto Relation, que tendrá por nombre RelacionUno, pero este nombre NO debe
confundirse con el nombre del objeto DAO Relation, que es MiRelacion
Set MiRelacion = MiBaseDatos.CreateRelation ("RelacionUno")
Una vez creada, le decimos a MiRelacion cual es la Tabla principal
MiRelación.Table = "MiTabla1"
'Nombre de la tabla principal.
Le decimos cual es el nombre de la tabla relacionada
MiRelación.ForeignTable = "MiTabla2"
‘Nombre de la tabla relacionada
Le ponemos los atributos a la relación. En este caso dbRelationUpdateCascade, para que, si hacemos
un cambio en el valor del campo de la tabla principal, ese cambio se refleje en el campo o los campos
relacionados con el.
MiRelación.Attributes = dbRelationUpdateCascade
Le decimos cual es el nombre del campo de la tabla principal que vamos a relacionar, mediante el
método CreateField. Deberemos declarar el nombre del objeto Field que vamos a crear para la relación
Dim MiCampo as Field
Set MiCampo = MiRelación.CreateField("Campo11")
Le recordamos lo de antes. Campo11 debe estar ya creado en la tabla Tabla1. Parece un poco ilógico
usar el método CreateField para un campo que ya está creado.
Le decimos ahora cual es el nombre del campo en la tabla relacionada
MiCampo.ForeignName = "Campo21"
Añadimos el campo creado a la colección Fields del objeto Relation
MiRelación.Fields.Append MiCampo
Y ahora añadimos el objeto Relation recién creado a la colección Relations del objeto Database
MiBaseDatos.Relations.Append MiRelación
Solamente nos falta ver que valores puede tener la propiedad Attributes del objeto Relation
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 323
dbRelationUnique
dbRelationDontEnforce
dbRelationInherited
dbRelationUpdateCascade
dbRelationDeleteCascade
La relación es uno a uno.
La relación no es impuesta (no hay integridad referencial).
La relación existe en una base de datos no activa que contiene
las dos tablas vinculadas.
Las actualizaciones se realizarán en cascada.
Las eliminaciones se realizarán en cascada.
Ahora ya casi podemos decir que tenemos la base de datos creada. Puede que sea así o que le falte
alguna cosa. Puede faltarle una o varias consultas. Las consultas también se pueden crear mediante
objetos DAO. Precisamente con un objeto QueryDef
Consultas. El Objeto QueryDef
Pero habrá observado que una base de datos ACCESS puede contener, además de tablas,
CONSULTAS. Las consultas no contienen datos. Contienen una referencia a los registros de las tablas
que los contienen. Una consulta podríamos decir que son conjuntos de registros tomados de una o
varias tablas (en este último caso, esas tablas deben estar relacionadas) que cumplen unas
determinadas condiciones. Pero aunque podemos ver esos registros como tales, con sus datos
exactamente igual que si se tratase de los registros de una tabla, las consultas no contienen el dato, sino
el número del registro dentro de la tabla que lo contiene. A la hora de presentar los datos de una
consulta, lo que estamos presentando son los datos almacenados en la tabla o las tablas que componen
esa consulta.
Crear una consulta. Método CreateQueryDef
Un objeto QueryDef representa una consulta de la base de datos. El objeto QueryDefs es la colección
de objetos QueryDef. La diferencia entre una consulta (Un QueryDef) y una tabla (Un TableDef) es que
la Tabla tiene dentro de sí los datos. La consulta tiene dentro una referencia al lugar de las tablas donde
se encuentran los datos.
Antes de utilizar el método CreateQueryDef debe declarar el nombre de los objetos a crear,
declarándolos como Variables Objeto tipo QueryDef . El ámbito es igual que para cualquier variable:
Public MiConsulta1 as QueryDef
Public MiConsulta2 as QueryDef
Ahora podemos utilizar el método CreateQueryDef para crear el nuevo objeto QueryDef en la base de
datos.
Sintaxis Con la fórmula de siempre :
Set MiConsulta1 = MiBaseDatos.CreateQueryDef ([Nombre][, Texto_sql])
Donde
MiConsulta1 es una variable del tipo QueryDef que previamente se ha declarado como tal. Será el
nombre por el que llamemos al Objeto QueryDef en el código de nuestra aplicación.
MiBaseDatos es el nombre del objeto Database abierto en el que vamos a introducir el nuevo objeto
QueryDef.
N o m b r e es una expresión de cadena que representa el nombre de la nueva consulta que vamos a crear.
Este nombre será el que veamos al abrir la base de datos con Access en la pestaña Consultas. Puede
omitirlo a la hora de crear la consulta, pero deberá añadirselo posteriormente.
Texto_sql es una expresión de cadena (instrucción SQL válida) que define el objeto QueryDef.
Lógicamente una consulta nos debe suministrar una serie de datos de una o mas tablas. Esos datos no
tienen porqué ser todos los datos de las tablas. Texto_sql es precisamente el filtro de esos datos
(expresado mediante una cláusula SQL).
Una vez creado el objeto QueryDef, no es necesario añadirlo a la colección QueryDefs de la Base de
Datos, excepto que hayamos creado el objeto QueryDef sin nombre. (Sin haber puesto el parámetro
N o m b r e , según se comentó mas atrás). Para añadirlo a la colección QueryDefs :
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 324
MiBaseDatos.QueryDefs.Append MiConsulta1
Como caso práctico de creación de una consulta, podemos tener
Set MiConsulta1 = MiBaseDatos.CreateQueryDef (“Fernandez”, “Select Nombre, Apellido1,
Apellido2 From Alumnos Where Apellido1 = ‘Fernandez’ )
Ahora ya tenemos la base de datos creada con todas las posibilidades. Ha llegado el momento de crear
una base real para comprobar todo lo expuesto.
Ejemplo práctico de creación de una base de datos. El famoso ejercicio del Videoclub
Vayamos a un ejemplo típico en cualquier curso de Visual Basic: el famoso Videoclub. Un videoclub tiene
una base de datos en la que tenemos una tabla, de nombre Clientes donde figuran los nombres y
dirección de los clientes, así como el número de su cuenta bancaria. Tiene un campo (ID_Cliente) que
es el que define al cliente. Será un campo tipo texto, que albergará un número que se incrementará en 1
cada vez que se hace un nuevo cliente. Cada cliente tiene un ID_Cliente y ese ID_Cliente es único para
él. (Este campo podría ser un autonumérico, pero personalmente no me gusta usar autonuméricos. Un
autonumérico es un Long –numérico- y quiero ser coherente con lo expuesto en el capítulo 1 donde se
decía que solamente se usarían campos numéricos en aquellos datos con los que se hagan operaciones
matemáticas) El campo ID_Cliente será clave primaria, ya que no pueden existir dos clientes con el
mismo ID_Cliente.
Otra tabla necesaria será la tabla Peliculas, donde introduciremos todos los datos relativos a las
películas (existentes o no en el videoclub), tal como título, director, artistas, resumen, calificación, precio,
etc. Tendrá un campo, ID_Pelicula que identificará a esa película. Pero puede haber versiones en varios
idiomas, por lo tanto, existirá otro campo Idioma de tipo texto, para introducir ese dato. Por lo tanto, una
película deberemos definirla por el conjunto formado por su ID_Pelicula y por su Idioma. El conjunto de
esos dos campos será la clave primaria. (Si cree que hay campos que no tienen sentido en esta tabla
(Idioma), piense que esto es un ejemplo para poder explicar de la forma más didáctica todas las posibles
variaciones de una instrucción)
Existe otra tabla denominada Cintas, donde figurarán todas las cintas existentes en el videoclub.
Para poder relacionarla con la tabla Peliculas, le ponemos un campo llamado ID_Pelicula que en
esta tabla no será clave primaria. También le pondremos el campo Idioma, sobre el que no
haremos ningún tipo de relación. Tendrá un campo ID_Cinta que será la combinación de varios
datos, uno que nos indique la película que tiene grabada esa cinta (Será la combinación de los
campos ID_Pelicula e Idioma) y de un número secuencial que indicará el número de la copia. Si le
pone imaginación y este conjunto de datos puede meterse en un código de barras, le facilitará la
operación de alquiler y devolución. En este ejercicio haremos que sea así, dándole a este campo
un tamaño de 13 dígitos para poder meterlo en un código EAN-13. Podemos añadirle mas
campos a nivel administrativo, como fecha de alta, fecha de baja, precio de esta copia, etc.
Existirá una tercera tabla, Alquileres, que relacionará al cliente con la cinta que ha alquilado.
Tendrá un campo llamado ID_Cliente y otro ID_Cinta. Aparte tendrá otros dos campos, fecha de
alquiler y fecha de devolución.
La base de datos deberá tener dos relaciones, una, entre el campo ID_Cliente de la tabla Clientes
y el campo ID_Clientes de la tabla alquileres (Será uno a infinito) y otra relación, entre el campo
ID_Cinta de la tabla Cintas y el campo ID_Cinta de la tabla Alquileres (Relación 1 a 1 ya que
solamente existe una cinta con esa ID_Cinta). Para darle más alegría al ejercicio le pondremos
una relación entre los campos ID_Pelicula e Idioma de las tablas Peliculas y Cintas.
(Se ha puesto el nombre de Pelicula al campo relacionado con ID_Pelicula para que se vea que
dos campos relacionados no tienen porqué tener el mismo nombre. Eso sí, deben tener las
mismas características)
Como colofón a todo esto, crearemos una consulta en la que utilizaremos todas las relaciones.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 325
Para llevar a cabo este ejercicio se ha partido de una interface gráfica en la que pueden verse tres
botones (Borrar la base de datos, crearla y salir) y un TextBox donde se ha puesto el nombre del
fichero de la base de datos en su propiedad Text. Veamos el código de cada uno de los botones
(por orden inverso de complejidad del código)
Fig. 20.3 Interface gráfica de la parte de crear bases de datos para la aplicación del Videoclub
CODIGO
Private Sub BSalir_Click()
Unload Me
End Sub
Private Sub BBorrar_Click()
On Error GoTo RutErr
Dim HayDir As String
HayDir = Dir(TBNombreBase)
If HayDir <> "" Then
Kill TBNombreBase
End If
RutErr:
If Err = 75 Then
MsgBox "Tiene la Base de Datos abierta por otro programa"
End If
End Sub
Creación de la base de datos
Private Sub BCrear_Click()
On Error GoTo RutErr
Dim HayDir As String ‘Se comprueba que existe la BD y se invita a borrarla
HayDir = Dir(TBNombreBase)
If HayDir <> "" Then
MsgBox "Ya existe el fichero con la base de datos. Debe borrarlo previamente"
Exit Sub
End If
‘ Se declaran todas las variables tipo objeto
Dim MiBaseDatos As Database
Dim MiTabla1 As TableDef, MiTabla2 As TableDef, MiTabla3 As TableDef
Dim MiTabla4 As TableDef
Dim MiCampo11 As Field, MiCampo12 As Field, MiCampo13 As Field
Dim MiCampo14 As Field, MiCampo15 As Field, MiCampo21 As Field
Dim MiCampo22 As Field, MiCampo23 As Field, MiCampo24 As Field
Dim MiCampo25 As Field, MiCampo31 As Field, MiCampo32 As Field
Dim MiCampo33 As Field, MiCampo34 As Field, MiCampo35 As Field
Dim MiCampo36 As Field, MiCampo41 As Field, MiCampo42 As Field
Dim MiCampo43 As Field, MiCampo44 As Field
‘Se crea el Objeto DataBase (Se toma el nombre del fichero del TextBox TBNombreBase
Set MiBaseDatos = Workspaces(0).CreateDatabase(TBNombreBase, dbLangGeneral)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 326
‘Se crean los Objetos Tabledef
Set MiTabla1 = MiBaseDatos.CreateTableDef("Clientes")
Set MiTabla2 = MiBaseDatos.CreateTableDef("Peliculas")
Set MiTabla3 = MiBaseDatos.CreateTableDef("Cintas")
Set MiTabla4 = MiBaseDatos.CreateTableDef("Alquileres")
‘Cada Tabledef crea sus propios Objetos Field
Set MiCampo11 = MiTabla1.CreateField("ID_Cliente", dbText, 8)
Set MiCampo12 = MiTabla1.CreateField("Nombre", dbText, 20)
Set MiCampo13 = MiTabla1.CreateField("Apellidos", dbText, 50)
Set MiCampo14 = MiTabla1.CreateField("Direccion", dbText, 50)
Set MiCampo15 = MiTabla1.CreateField("Telefono", dbText, 15)
Set MiCampo21 = MiTabla2.CreateField("ID_Pelicula", dbText, 8)
Set MiCampo22 = MiTabla2.CreateField("Titulo", dbText, 20)
Set MiCampo23 = MiTabla2.CreateField("Idioma", dbText, 1)
Set MiCampo24 = MiTabla2.CreateField("Director", dbText, 25)
Set MiCampo25 = MiTabla2.CreateField("Resumen", dbText, 255)
Set MiCampo31 = MiTabla3.CreateField("ID_Cinta", dbText, 13)
Set MiCampo32 = MiTabla3.CreateField("Pelicula", dbText, 20)
Set MiCampo33 = MiTabla3.CreateField("Idioma", dbText, 1)
Set MiCampo34 = MiTabla3.CreateField("Precio", dbSingle)
Set MiCampo35 = MiTabla3.CreateField("Fecha_Alta", dbDate)
Set MiCampo36 = MiTabla3.CreateField("Fecha_Baja", dbDate)
Set MiCampo41 = MiTabla4.CreateField("ID_Cliente", dbText, 8)
Set MiCampo42 = MiTabla4.CreateField("ID_Cinta", dbText, 13)
Set MiCampo43 = MiTabla4.CreateField("Fecha_Alq", dbDate)
Set MiCampo44 = MiTabla4.CreateField("Fecha_Dev", dbDate)
‘Una vez creados los campos se les ponen las peopiedades que se estime oportuno
‘En este caso, se ha puesto la propiedad AllowZeroLength (Permitir valores nulos en ese ‘campo)
a lo que interesa en cada uno de los campos. Nota Tenga presente que por defecto le ‘va a dejar
el campo que NO permite valores nulos, circunstancia que le va a crear problemas.
MiCampo12.AllowZeroLength = True
MiCampo13.AllowZeroLength = False
MiCampo14.AllowZeroLength = True
MiCampo15.AllowZeroLength = True
‘Se añaden los campos a la colección Fields de las tablas
MiTabla1.Fields.Append MiCampo11
MiTabla1.Fields.Append MiCampo12
MiTabla1.Fields.Append MiCampo13
MiTabla1.Fields.Append MiCampo14
MiTabla1.Fields.Append MiCampo15
MiTabla2.Fields.Append MiCampo21
MiTabla2.Fields.Append MiCampo22
MiTabla2.Fields.Append MiCampo23
MiTabla2.Fields.Append MiCampo24
MiTabla2.Fields.Append MiCampo25
MiTabla3.Fields.Append MiCampo31
MiTabla3.Fields.Append MiCampo32
MiTabla3.Fields.Append MiCampo33
MiTabla3.Fields.Append MiCampo34
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 327
MiTabla3.Fields.Append MiCampo35
MiTabla3.Fields.Append MiCampo36
MiTabla4.Fields.Append MiCampo41
MiTabla4.Fields.Append MiCampo42
MiTabla4.Fields.Append MiCampo43
MiTabla4.Fields.Append MiCampo44
‘Se añaden las tablas a la colección Tabledefs del objeto Database
MiBaseDatos.TableDefs.Append
MiBaseDatos.TableDefs.Append
MiBaseDatos.TableDefs.Append
MiBaseDatos.TableDefs.Append
MiTabla1
MiTabla2
MiTabla3
MiTabla4
‘Se declaran las variables tipo objeto Index y tipo objeto Field para crear los índices
Dim MiIndice1 As Index, MiIndice2 As Index, MiIndice3 As Index
Dim CampoIndiceA As Field
Dim CampoIndiceB As Field
‘Se crea el primer objeto Index
Set MiIndice1 = MiTabla1.CreateIndex("IndiceCliente")
‘Este objeto Index crea el campo que va a ser índice, con los mismos datos que el
‘campo MiCampo11
Set CampoIndiceA = MiIndice1.CreateField("ID_Cliente", dbText, 8)
‘Se añade el campo a la colección Fields del In dex
MiIndice1.Fields.Append CampoIndiceA
‘Se le dice que es un índice primario (Clave primaria)
MiIndice1.Primary = True
‘Se añade el objeto Index recién creado a la colección Index del objeto tabledef
MiTabla1.Indexes.Append MiIndice1
‘Se procede de igual forma con el segundo objeto Index
Set MiIndice2 = MiTabla2.CreateIndex("IndicePeliculas")
‘Aquí se meten dos campos en el mismo índice
Set CampoIndiceA = MiIndice2.CreateField("ID_Pelicula", dbText, 10)
Set CampoIndiceB = MiIndice2.CreateField("Idioma", dbText, 1)
MiIndice2.Fields.Append CampoIndiceA
MiIndice2.Fields.Append CampoIndiceB
MiIndice2.Primary = True
MiTabla2.Indexes.Append MiIndice2
Set MiIndice3 = MiTabla3.CreateIndex("IndiceCintas")
Set CampoIndiceA = MiIndice3.CreateField("ID_Cinta", dbText, 13)
MiIndice3.Fields.Append CampoIndiceA
MiIndice3.Primary = True
MiTabla3.Indexes.Append MiIndice3
‘Se declaran los objetos Relation y un par de objetos Field para crear las relaciones. Por
‘claridad se han declarado objetos Field distintos para la creación de los índices y de las ‘relaciones, pero
podrían haber sido los mismos
Dim MiRelacion1 As Relation, MiRelacion2 As Relation, MiRelacion3 As Relation
Dim CampoRelacionA As Field
Dim CampoRelacionB As Field
‘Se crea la primera relación entre el campo ID_Clientes de la tabla Clientes (Tabla ‘primaria) y el campo
ID_Cliente de la tabla Alquileres (Tabla relacionada)
Set MiRelacion1 = MiBaseDatos.CreateRelation("RelClientes", "Clientes", "Alquileres")
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 328
Set CampoRelacionA = MiRelacion1.CreateField("ID_Cliente", dbText, 8)
CampoRelacionA.ForeignName = "ID_Cliente"
MiRelacion1.Fields.Append CampoRelacionA
MiBaseDatos.Relations.Append MiRelacion1
‘Se crea la segunda relación
Set MiRelacion2 = MiBaseDatos.CreateRelation("RelCintas", "Cintas", "Alquileres")
MiRelacion2.Attributes = dbRelationUnique
Set CampoRelacionA = MiRelacion1.CreateField("ID_Cinta", dbText, 13)
CampoRelacionA.ForeignName = "ID_Cinta"
MiRelacion2.Fields.Append CampoRelacionA
MiBaseDatos.Relations.Append MiRelacion2
‘La tercera relación “relaciona” dos campos, Película e Idioma
Set MiRelacion3 = MiBaseDatos.CreateRelation("RelCintasPelis", "Peliculas", "Cintas")
Set CampoRelacionA = MiRelacion1.CreateField("ID_Pelicula", dbText, 8)
Set CampoRelacionB = MiRelacion1.CreateField("Idioma", dbText, 8)
CampoRelacionA.ForeignName = "Pelicula"
CampoRelacionB.ForeignName = "Idioma"
MiRelacion3.Fields.Append CampoRelacionA
MiRelacion3.Fields.Append CampoRelacionB
MiBaseDatos.Relations.Append MiRelacion3
‘Se comienza a crear una consulta (La sentencia SQL está cortada dado que no cabe en ‘una línea. El
signo  indica que esa línea continúa en la siguiente
Dim MiConsulta1 As QueryDef
Set MiConsulta1 = MiBaseDatos.CreateQueryDef("Pelis", "SELECT Clientes.Nombre,
Clientes.Apellidos, Clientes.Telefono, Peliculas.Titulo, Alquileres.ID_Cinta " & _
" FROM Peliculas INNER JOIN (Clientes INNER JOIN (Cintas INNER JOIN Alquileres ON
Cintas.ID_Cinta = Alquileres.ID_Cinta) " & _
" ON Clientes.ID_Cliente = Alquileres.ID_Cliente) ON (Peliculas.Idioma = Cintas.Idioma) AND
(Peliculas.ID_Pelicula = Cintas.Pelicula)" & _
" WHERE (((Alquileres.ID_Cinta)='0000000000001'));")
‘Se cierra la el objeto database. En este momento es cuando se crea el fichero.
MiBaseDatos.Close
‘se comunica al usuario la buena nueva de que la base ha sido creada.
MsgBox "La base de datos se ha creado con éxito"
‘Aquí comienza la rutina de error
Exit Sub
RutErr:
MsgBox "Ha ocurrido el error " & Err & ". " & Err.Description
End Sub
Nota acerca de la sentencia SQL para crear la consulta.
Se puede ser muy experto en SQL y tener miedo a crear una consulta SQL debido a la
complejidad que puede tener. No crea que el autor ha escrito la sentencia SQL que ha visto. Ha
utilizado el truco de crear primero la consulta con Access, de la forma gráfica que seguro que Vd.
conoce, ha comprobado que era eso lo que quería, pasó a Vista SQL y la copió. Es muy bueno
hacer prácticas con SQL, para que no se olvide. Pero en algunos casos es preferible acudir a los
trucos que nos proporcionan nuestras herramientas.
El resultado de todo esto podemos verlo si abrimos la base de datos con Access
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 329
Fig. 20.4 Tablas de la BD de Videoclub creada con el código descrito
Fig. 20.5 Y la consulta
Fig. 20.6 Clave Primaria formada con los dos campos de la tabla Películas
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 330
Fig. 20.7 Propiedades de esa clave primaria
Fig. 20.8 Las relaciones creadas
Crear bases de datos con contraseña
Imagínese que quiere que su base de datos no se pueda abrir mediante Access. Lo que debe
hacer es crearla con una contraseña (Password) de forma que cuando la quiera abrir, le pida el
Password. Si no lo sabe, no se puede abrir. Si crea una base de datos con estas características, y
no comunica el Password a nadie, solamente la podrá abrir mediante el programa. (Eso sí, el
programa para abrirla, deberá introducir en su instrucción de apertura el Password con el que se
creó.)
Si volvemos a la línea donde creabamos la base de datos del videoclub:
Set MiBaseDatos = Workspaces(0).CreateDatabase(TBNombreBase, dbLangGeneral)
Basta con añadirle ";pwd=PaswordElegido" concatenándolo tras el parámetro que especifica la
lengua. En el ejemplo siguiente hemos usado como Password las iniciales LSB
Set MiBaseDatos =
= Workspaces(0).CreateDatabase(TBNombreBase, dbLangGeneral & ";pwd=LSB")
Cuando lleguemos a la parte de abrir bases de datos, explicaremos cómo se abre una base de
datos con contraseña. Y no crea que ha conseguido la confidencialidad total de sus datos.
Existen programas que puede bajarse de Internet que le leen la contraseña con la que ha
protegido su base. No es una protección total, pero sí suficiente para que un usuario “normal” no
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 331
se la pueda abrir.
Crear bases de datos encriptada
Puede encriptar el fichero de su base de datos. Solamente le será útil para que no puedan ver el
contenido del fichero .MDB, ya que si se abre con Access, le presentará los datos de forma
correcta. Para encriptar una base de datos basta con añadir la palabra dbEncrypt en la instrucción
donde ha creado la BD
Set MiBaseDatos = Workspaces(0).CreateDatabase(TBNombreBase,dbLangGeneral & ";pwd=LSB", dbEncrypt)
Ha merecido la pena el trabajo. Hemos creado la base de datos haciendo click en un botón de la
aplicación. No ha sido necesario venderle al cliente Access, ni enviar una base de datos vacía
con los discos de distribución. Además hemos controlado todos los parámetros de los campos
de nuestra BD. Merece la pena crearse las bases de datos por programa.
Anexo1
Propiedades de los campos
Ha visto mas atrás que puede ser necesario cambiar las propiedades de los campos una vez
creados (Por ejemplo, MiCampo13.AllowZeroL ength = False ) Alargaríamos demasiado este ya
largo capítulo si se explican todos los las propiedades que puede tener un campo. Añada un
poco de esfuerzo a su estudio y vea las propiedades de los objetos Field en la ayuda. Le reseño
aquí las que he considerado mas importantes
AllowZeroLength Si/NO Si es Si permite que ese campo tenga valores nulos
DataUpdatable Si/No Si es Si permite modificar el dato de ese campo. No tiene aplicación a la hora de
crear un campo. Sí puede cambiar el valor de esta propiedad por ejemplo, cuando crea un recordset.
DefaultValue Es el valor que le pone a ese campo si no introduce ninguno. Puede indicar un valor a la
hora de crear el campo:
Campo14.DefaultValue = “Madrid”
Required Si/No Indica si el dato es requerido. En caso de que tom e el valor SI (True) es
necesario introducir un dato en ese campo
Value Es justamente el dato que almacena en ese campo. Es la propiedad por defecto del objeto Field.
Propiedades Type, Attributes y Size referidas a los campos
En el método CreateField debe introducir el tipo del campo que desea crear. (Como puede ver
mas atrás, con esta sintaxis p.e.: CreateField("Fecha_Alq" , dbDate ) Ese tipo coincide con la
propiedad Type aplicada a los campos. La propiedad Size solamente tendrá que aplicarla cuando
vaya a crear un campo tipo Texto.
Puede ver la ayuda de VB para mas detalles. Le enumero los mas usuales
Propiedad Type
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 332
Constante
Descripción
Constante
dbBoolean
dbCurrency
dbDouble
dbLong
dbLongBinary
dbSingle
Campo SI/NO
dbByte
Tipo moneda
dbDate
Numérico Doble
dbInteger
Entero Long
dbMemo
Binario largo (Objeto OLE)
Numérico Single
dbText
Descripción
Campo tipo Byte
Tipo Date/Time
Numérico Integer
Campo Memo
CampoTexto
Propiedad Attributes
Constante
Descripción
dbFixedField
dbVariableField
dbAutoIncrField
El tamaño del campo es fijo (predeterminado en campos numéricos).
El tamaño del campo es variable (Sólo campos de texto).
El valor del campo en los registros nuevos es incrementado
automáticamente a un valor Long integer único que no puede ser modificado.
Sólo aceptado en tablas bases de datos Jet.
El valor del campo no puede ser modificado.
El campo está ordenado de forma descendente (Z-A o 100-0) (sólo se
aplica a objetos Field de una colección Fields de un objeto Index). Si se omite
esta constante, el campo se ordena ascendentemente (A-Z o 0-100)
(predeterminado).
dbUpdatableField
dbDescending
dbAutoIncrField es la constante a utilizar cuando queremos crear un campo que se vaya
incrementando cada vez que se introduce un nuevo registro (Campo Contador). Por ejemplo, si hemos
creado un campo denominado ID que será el contador de una serie de registros, y queremos que se
incremente en 1 cada vez que añadamos un registro, debemos usar la propiedad Attributes ANTES de
añadir ese campo al objeto TableDef correspondiente, de la siguiente forma :
Set micampo1N = mitabla01.CreateField("ID", 4) ‘ Creamos el campo ID
micampo1N.Required = True
‘ La propiedad Required la veremos
micampo1N.Attributes = dbAutoIncrField
‘ Le damos atributo de contador
‘ Añadimos el campo a la tabla
mitabla01.Fields.Append micampo11
Propiedad Size
Devuelve o establece un valor que indica el tamaño máximo, en bytes, de un objeto Field que contiene
texto o el tamaño fijo de un objeto Field que contiene texto o valores numéricos
Esta propiedad se le debe suministrar en la sintaxis de CreateField solamente cuando creamos
un campo tipo texto - CreateField("ID_Cinta", dbText, 13). El tamaño de un campo texto puede
ser desde 1 a 255 caracteres. Para el resto de los tipos de datos, el tamaño va implícito en el tipo
de dato. Puede consultar el tamaño ocupado por cualquier campo, leyendo la propiedad Size de
un campo:
Variable = Micampo11.Size
Abrir una Base de Datos ya existente mediante DAO.
Método OpenDatabase
Hasta ahora hemos visto como crear una base de datos. No es lo más usual. Lo normal es tener la base
de datos creada y abrirla cuando queremos extraer datos o introducir datos. Vamos a ver como se abre
una base de datos mediante DAO, usando el espacio de trabajo Microsoft JET. Veremos luego como se
puede crear un Recordset, que es en realidad sobre el que se leen y escriben datos, como se pueden
añadir registros, borrarlos etc.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 333
Para abrir una base de datos existente deberemos usar el método OpenDatabase. Pero previamente
deberemos declarar el nombre que se le va a dar a ese objeto Database mediante la instrucción Dim si
queremos que el ámbito de ese Database sea un formulario, o Global o Public, (en la sección de
declaraciones de un Módulo o Formulario) si queremos que el ámbito sea toda la aplicación.
Por ejemplo, si queremos abrir una base de datos y poder referirnos a ella en toda la aplicación,
debemos declararla de esta forma en la sección de declaraciones de un módulo :
Public MiBaseDatos as Database
Método OpenDatabase
Abre la base de datos existente. La base de datos abierta se agrega automáticamente a la colección
Databases.
Sintaxis Recuerde la expresión general: Set DAOInferior = DAOSuperior.Método ( - - - - - -)
Set MiBaseDatos = Misesion.OpenDatabase(nombre_bd[, exclusivo[, sólo-lectura[, origen]]])
La sintaxis del método OpenDatabase consta de las siguientes partes:
MiBaseDatos
Misesion
nombre_bd
Variable de tipo de dato objeto Database que representa el objeto DAO
Database que se va a abrir.
Variable de tipo de dato objeto Workspace que representa el objeto
Workspace existente que va a contener a la base de datos.
Expresión de cadena con el nombre de un archivo (y su Path) de una base de
datos existente. Si el nombre de archivo tiene extensión, es necesario especificarla. Si la
red lo admite, también puede especificar una ruta de red, como por ejemplo
"\\MISERVID\MICOMP\MIDIR\MIBD.MDB". nombre_bd también puede ser un origen de
datos OBDC. Lo veremos en otro capítulo.
Al especificar nombre_bd hay que tener en cuenta algunas consideraciones:
Si se refiere a una base de datos ya abierta por otro usuario con acceso
exclusivo, se producirá un error.
Si no se refiere a una base de datos existente o a un origen de datos ODBC
válido, se producirá un error.
Si es una cadena de longitud cero ("") y origen es "ODBC;", aparecerá un cuadro de
diálogo con todos los nombres de orígenes de datos ODBC registrados, en el que el
usuario podrá elegir una base de datos.
exclusivo
sólo_lectura
origen
p.e.
Valor de tipo Boolean que es True si la base de datos se va a abrir con acceso
exclusivo (no compartido) o False si se va a abrir con acceso compartido. Si se omite
este argumento, la base se abrirá con acceso compartido.
Valor de tipo Boolean que es True si la base de datos se va a abrir con acceso
de sólo lectura o False si se va a abrir con acceso de lectura/escritura. Si se omite este
argumento, la base se abrirá para lectura/escritura.
Expresión de cadena utilizada para abrir la base de datos. Esta cadena
constituye los argumentos de conexión ODBC. Para especificar una cadena de origen
deberá especificar también los argumentos exclusivo y sólo_lectura. Consulte la sintaxis
en la propiedad Connect.
Set MiBaseDatos = Misesion.OpenDatabase (“C:\Guia_Est\Videoclub.MDB”)
abre la base de datos cuyo fichero está en C :\Guia_Est y se llama Videoclub.MDB. Al no expresarle mas
parámetros la abre de modo no exclusivo, y de lectura y escritura. Al no especificar nada en el parámetro
origen entiende que la base es ACCESS
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 334
Nota para t od o este c apítulo . No es necesario cambiar el nombre del Workspace. Si Misesion =
Workspaces (0), la sentencia anterior podemos ponerla también :
Set MiBaseDatos = Workspaces(0). OpenDatabase (“C:\Guia_Est\Videoclub.MDB”)
El hecho de poner siempre un nombre al Workspace es solamente a efectos didácticos
Ya tenemos la base de datos abierta. Pero no crea que nuestro programa ha hecho trabajo. Se ha
limitado a ver si existía el fichero indicado y a “apuntar” el nombre y path de ese fichero que contiene la
base de datos. El trabajo comienza cuando cree el recordset.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 335
EL OBJETO RECORDSET
(O la mitad de lo que Vd. necesita saber de Bases de Datos)
Un objeto Recordset contiene los registros de una tabla o de una consulta. Puede ser que no los
contenga todos, si al crear ese recordset le hemos impuesto que los registros cumplan una determinada
condición. En resumen, un recordset es un objeto de acceso a datos que contiene una colección de
registros tomados, bien de una tabla, bien de un conjunto de tablas (a través de una consulta)
También hay una colección Recordsets. La colección Recordsets contiene todos los objetos Recordset
abiertos de un objeto Database.
Al utilizar objetos de acceso a datos, casi toda la interacción con los datos se produce a través de
objetos Recordset. Todos los objetos Recordset están formados por registros (filas) y campos
(columnas). Existen tres tipos de objetos Recordset:
Records et de tipo tabla : Representación en código de una tabla base de datos que puede utilizarse
para agregar, modificar o eliminar registros de una sola tabla de base de datos. Un Recordset tipo Tabla
contiene todos los campos de una tabla y no puede contener campos que no pertenezcan a esa tabla.
Records et de tipo hoja d e respuestas d inámic a : Resultado de una consulta que puede tener registros
actualizables. Un Recordset de tipo hoja de respuestas dinámica es un conjunto dinámico de registros
que puede utilizarse para agregar, modificar o eliminar registros de una o más tablas de una base de
datos subyacente. Este tipo de objeto Recordset puede contener campos de una o más tablas de una
base de datos.
Reco rds et de tipo ins tantánea : Copia estática de un conjunto de registros que puede utilizarse para
buscar datos o generar informes. Los objetos Recordset de tipo instantánea pueden contener campos de
una o más tablas de una base de datos, pero no pueden actualizarse. Un recordset de tipo instantánea
(Snapshot) es una fotografía que se hace a la tabla o tablas que lo componen. Los datos que tiene el
recordset son los que existían cuando se realizó la fotografía. Cualquier actualización posterior no se
puede ver.
Resumiendo, un Recordset es un conjunto de registros. Recuerde cuando explicábamos en control Data
se decía que este control creaba un Recordset a partir de sus propiedades DatabaseName y
RecordSource. De esta forma, el conjunto de registros que tiene ese control Data es la totalidad de los
registros de la tabla (o consulta) que poníamos en la propiedad RecordSource. Pero siempre podemos
asignar a la propiedad Recordset de ese control Data un Recordset ya creado mediante código. Y en ese
caso, solamente contendrá los campos que a nosotros nos interese, incluso campos de distintas tablas,
cosa que viene muy bien algunas veces.
Un Recordset lo crearemos con el método OpenRecordset que estamos estudiando. El objeto
Recordset se abre desde un objeto DataBase (que es lo normal). Pero si acude a la información de VB
verá que también se puede abrir desde un TableDef, un QueryDef y desde otro Recordset. No se
complique la vida. Abra directamente los Recordsets desde la base de datos. A lo mejor, tenemos
oportunidad de ver que también se puede abrir desde otro recordset, pero que en este caso solamente
podemos abrirlo para cambiar alguna de sus propiedades.
Como cualquier objeto DAO, debemos declararlo como variable tipo objeto.
Public Mirecordset As Recordset
Una vez declarado, para abrirlo basta con ejecutar la sentencia :
Set Mirecordset = base_datos.OpenRecordset (origen[, tipo[, opciones]])
Al crear un nuevo objeto Recordset se agrega automáticamente a la colección Recordsets.
base_datos es el nombre del objeto Database que va a crear el recordset. (La base de datos que acaba
de abrir)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 336
Origen en la primera expresión es una variable de tipo String que especifica el origen de los registros del
nuevo objeto Recordset. El origen puede ser un nombre de tabla, un nombre de consulta o una
instrucción SQL que devuelva registros. En el caso de los objetos Recordset de tipo tabla, el origen sólo
puede ser un nombre de tabla.
Tipo es el tipo de Recordset que se quiere crear. Si no se especifica un tipo, OpenRecordset creará un
objeto Recordset de tipo tabla cuando sea posible. (Cuando especifica como Origen el nombre de una
Tabla) Si se especifica una consulta o una tabla adjunta, OpenRecordset creará un objeto Recordset de
tipo hoja de respuestas dinámica. El tipo del nuevo objeto Recordset se define mediante una de las
siguientes constantes :
dbOpenTable para abrir un objeto Recordset de tipo tabla.
dbOpenDynaset para abrir un objeto Recordset de tipo hoja de respuestas dinámica.
dbOpenSnapshot para abrir un objeto Recordset de tipo instantánea.
El parámetro opciones permite especificar las características del nuevo objeto Recordset tales como las
restricciones de edición y consulta para otros usuarios. Vea la Ayuda de VB para mayor detalle.
Los objetos Recordset se eliminan automáticamente de la colección Recordsets al cerrarlos con el
método Close. También se eliminan automáticamente cuando creamos otro recordset con el mismo
nombre.
Ejemplo de creación de un Objeto Recordset
Decíamos que se puede crear un Recordset con la sentencia :
Recuerde la Fórmula general Set DAOinf = DAOsup.Método ( - - - - - - - )
Set Mirecordset = base_datos.OpenRecordset (origen[, tipo[, opciones]])
Si tenemos abierta una base de datos llamada MiBaseDatos, podemos crear el objeto MiRecordset
eligiendo de la tabla MiTabla de esa base de datos los campos Campo1, Campo2 y Campo3, y que sea
del tipo de hoja de respuestas dinámica, de la siguiente forma :
Set Mirecordset = MiBaseDatos.OpenRecordset (“SELECT Campo1, Campo2, Campo3 _ FROM
MiTabla”, dbOpenDynaset)
Si deseamos que el Recordset contenga todos los campos de esa misma tabla :
Set Mirecordset=MiBaseDatos.OpenRecordset (“SELECT * FROM MiTabla”, dbOpenDynaset)
o simplemente sin utilizar la sentencia SQL :
Set Mirecordset = MiBaseDatos.OpenRecordset (“MiTabla”, dbOpenDynaset)
En los ejemplos anteriores no se ha establecido ningún parámetro en Opciones.
Veamos lo que decíamos antes. Crear un Recordset desde otro recordset. Se puede usar solamente
para variar sus propiedades. Si desde el Recordset anterior, queremos crear un nuevo Recordset
denominado MiRecordset1, que tenga la condición de que sea solo lectura, usaremos la sentencia :
Set Mirecordset1 = Mirecordset.OpenRecordset (dbReadOnly)
Este nuevo Recordset contendrá los mismos campos que el Recordset origen, pero no podremos
cambiar datos en él.
Pueden crearse tantos Recordsets como se necesiten. Estos Recordsets pueden tener campos
comunes. Es más, podríamos crear dos Recordsets exactamente iguales.
Pero en la mayoría de los casos, necesitaremos crear un Recordset donde se elijan varios campos de
una o varias tablas, seleccionando de esos campos unos determinados valores. Por ejemplo, en una
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 337
base con las direcciones de los clientes, a lo mejor queremos seleccionar todas aquellas direcciones en
las cuales el código postal sea el 28700 (San Sebastián de los Reyes). Imaginemos que hemos abierto
la base de datos con el nombre CLIENTES (Recuerde que este es el nombre del objeto DAO usado para
abrir la B.D., no el nombre que pueda tener esa B.D. en el disco), y esta base de datos tiene una tabla
llamada DIRECCIONES (Este sí es el nombre real de la tabla dentro de la B.D.) Vamos a abrir un
Recordset con todos los clientes de San Sebastián de los Reyes :
Set Mirecordset2 = CLIENTES.OpenRecordset (“SELECT * FROM DIRECCIONES WHERE
COD_POSTAL = 28700“, dbOpenDynaset)
El Recordset Mirecordset2 contiene todos los campos de todos los registros de la tabla DIRECCIONES
que cumplan la condición de que el código postal (campo COD_POSTAL en el ejemplo) sea igual a
28700.
Observe en esta y anteriores expresiones, que la sentencia SQL está entre doble comilla.
Podemos introducir cualquier sentencia SQL para determinar qué registros introducimos en el
Recordset. Por ejemplo, si queremos seleccionar todos los clientes de Madrid (su código postal
comenzará necesariamente por 28 y le seguirán tres cifras) :
Set Mirecordset2 = CLIENTES.OpenRecordset (“SELECT * FROM DIRECCIONES WHERE
COD_POSTAL LIKE 28???“, dbOpenDynaset)
Tipo de recordset más práctico ¿Dynaset, Table?
A la hora de crear un recordset podemos pensar que tipo es el más adecuado. Todo dependerá de lo
que necesitemos de nuestro recordset y de cómo nos queramos mover por él. Cuando decimos
movernos por él queremos decir cambiar de un registro a otro, buscar registros, etc.
Vamos a prescindir del recordset tipo Snapshot si lo que queremos es leer y escribir datos. Un recordset
Snapshot solamente sirve para realizar informes (leer) de los datos en un instante determinado. Veamos
la elección entre Dynaset y Table
Si queremos seleccionar parte de los registros de una tabla, o ver registros de varias tablas al mismo
tiempo (lo que podemos ver en Access en una consulta), debemos elegir directamente el tipo Dynaset,
ya que el tipo Table debe contener TODOS los registros de una UNICA TABLA.
Si estamos en ese caso es el único en el que tendremos dudas respecto al tipo elegido.
Si creamos un recordset tipo Table se nos puede complicar un poco el código a la hora de movernos a lo
largo del recordset, ya que no podemos usar ciertos métodos como los Find (FindFirst, FindLast, etc.)
debiendo utilizar para realizar la misma función los métodos Move (MoveFirst, MoveLast, MovePrevious,
MoveNext), o el método Seek, un poco más complicado y que exige un índice. (Lo que ganamos con la
complicación del Seek es velocidad). Los desplazamientos a lo largo de un recordset tipo tabla son
mucho más rápidos que sobre un recordset tipo Dynaset. Esa rapidez se nota fundamentalmente cuando
va a manejar miles de registros, en cuyo caso es indispensable usar recordsets tipo tabla y moverse
sobre un índice. Si no va a manejar miles de registros, no apreciará mucha diferencia entre uno y otro. Y
si usa Dynaset dispone de más recursos, sobre todo de búsqueda. Veremos casos de uno y otro tipo.
Métodos y Propiedades del recordset que va a necesitar inmediatamente
Propiedad RecordCount
Devuelve el número de registros accedidos en un objeto Recordset. El valor de esta propiedad es de
sólo lectura
Sintaxis
NombredeMiRecordset.RecordCount
Donde NombredeMiRecordset es un objeto Recordset . El valor devuelto por la propiedad RecordCount
es un dato numérico Long
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 338
(NombredeMiRecordset puede ser del tipo Dynaset , Snapshot Table. Pero en el caso de que sea
Dynaset se va a encontrar con una sorpresa. Si le pide ese dato a un recordset tipo Dynaset recién
creado, le devolverá el valor 1. ¡Parece que solamente tiene un registro! No es así. Un recordset tipo
Dynaset tiene la ventaja (y el inconveniente) de que solamente guarda en memoria un registro. Por lo
tanto no sabe cuantos registros tiene realmente hasta que no los recorre todos. Para que el método
RecordCount le devuelva el número de registros existentes, tiene que acceder previamente al primero
y al último. Para ello basta con ejecutar estas dos líneas de código:
NombredeMiRecordset.MoveLast
NombredeMiRecordset.MoveFirst
A partir de ese momento, ya le indicará el número correcto de registros existentes.
Método AddNew
Crea un nuevo registro en un objeto Recordset de tipo Table o Dynaset.
Sintaxis
MiRecordset.AddNew
El método AddNew crea un nuevo registro donde puede introducir nuevos datos, y posteriormente
agregarlo al conjunto de registros del objeto Recordset. Este método establece en los campos el valor
Null (predeterminado para los objetos Recordset de tipo tabla) o los valores predeterminados, si existen.
El registro creado queda en la memoria, y ahí se puede modificar simplemente asignando a cada campo
el valor deseado. Para asignar un valor a un campo simplemente tenemos que poner la expresión :
MiRecordset ! MiCampo1 = “Dato tipo string”
MiRecordset ! MiCampo2 = Dato tipo numérico
Una vez que se hayan introducido los datos en el nuevo registro, debe utilizar el método Update para
guardar los cambios y agregarlo al conjunto de registros. No se modificará la base de datos hasta que se
utilice el método Update.
La posición del nuevo registro depende del tipo de objeto Recordset:
En un objeto Recordset de tipo hoja de respuestas dinámica, (Dynaset) los registros se insertan al final
del conjunto, independientemente de las reglas de ordenación que pueda haber en vigor al abrir el
conjunto de registros. En un objeto Recordset de tipo tabla cuya propiedad Index esté definida, los
registros se agregan en el lugar correspondiente al orden. Si no se ha establecido la propiedad Index, los
nuevos registros se agregan al final del conjunto.
El registro que era actual antes de utilizar el método AddNew continúa siéndolo después. Esto puede
comprobarlo asignando a un Label el contenido de un campo, añadir un registro con un valor para ese
campo distinto al que está presente en el Label y comprobar que el contenido del Label no se ve
afectado por haber introducido un registro nuevo. Si desea hacer que el nuevo registro sea el actual,
puede establecer en la propiedad Bookmark el marcador identificado por el valor de la propiedad
LastModified. En la práctica anterior observará tras este proceso que se cambia el contenido del Label
al nuevo valor.
Vea la propiedad LastModified un poco mas adelante.
Método Edit
Copia el registro actual de un objeto Recordset de tipo hoja de respuestas dinámica o tabla en el búfer
de copia para su edición.
Sintaxis
LSB
MiRecordset.Edit
Visual Basic – Guía del Estudiante
Capítulo 1
Página 339
Donde MiRecordset representa el nombre de un objeto Recordset abierto y actualizable que contiene el
registro a editar.
Una vez invocado el método Edit, los cambios efectuados en los campos del registro actual se copian en
el búfer de copia. Al terminar de realizar los cambios deseados, utilice el método Update para
guardarlos. Como en el caso del método AddNew este registro modificado está en la memoria y es
necesario introducirlo en la BD.
El registro actual después de utilizar Edit es precisamente el registro que acabamos de editar. Para
poder usar Edit debe existir un registro actual. Si no es así o si MiRecordset no se refiere a un objeto
Recordset de tipo tabla u hoja de respuestas dinámica, a un objeto Table o a un objeto Dynaset abierto,
se producirá un error.
El uso de Edit producirá un error en las condiciones siguientes:
No hay registro actual.
La base de datos o el conjunto de registros es de sólo lectura.
Ningún campo del registro es actualizable.
Otro usuario ha abierto la base de datos o el conjunto de registros para uso exclusivo.
Otro usuario ha bloqueado la página que contiene el registro.
Una vez añadido el registro, o cambiados los datos de un registro, debemos utilizar el Método Update
para guardar los datos en la BD.
Método Update
Guarda el contenido del búfer de copia en un objeto Recordset de tipo hoja de respuestas dinámica o
tabla especificado.
Es decir, mete en la Base de Datos el contenido del registro que estaba en la memoria, bien por haber
utilizado el método Update, bien por haber utilizado el método Edit.
Sintaxis
MiRecordset.Update
Donde MiRecordset representa el nombre de un objeto Recordset de tipo hoja de respuestas dinámica o
tabla, abierto y actualizable.
Los cambios en el registro actual se perderán en las siguientes situaciones:
Uso del método Edit o AddNew y desplazamiento a otro registro sin utilizar antes Update.
Uso de Edit o AddNew y utilización de nuevo de Edit o AddNew sin especificar antes Update.
Establecimiento de otro registro en la propiedad Bookmark.
Cierre del conjunto de registros indicado en MiRecordset sin utilizar antes Update.
Cada vez que se crea o edita un registro se cambia el valor de la propiedad LastModified, que tomará el
marcador de ese registro creado o editado.
Método CancelUpdate
Cancela todas las actualizaciones pendientes del objeto Recordset.
Sintaxis
recordset.CancelUpdateTipo
Tipo puede tomar los siguientes valores
dbUpdateRegular
dbUpdateBatch
Comentarios
LSB
Cancela los cambios pendientes que no están en la memoria caché.
Cancela los cambios pendientes en la memoria cache actualizada.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 340
El método CancelUpdate cancela todas las actualizaciones pendientes a causa de una operación Edit o
AddNew. La utilización del método CancelUpdate tiene el mismo efecto que moverse a otro registro sin
utilizar el método Update, salvo que el registro activo no cambia y algunas propiedades, como BOF y
EOF, no se actualizan.
Método Delete
Este método elimina el registro actual de un objeto Recordset de tipo hoja de respuestas dinámica o
tabla. Para eliminar un registro, debe haber un registro actual en el Recordset antes de utilizar Delete,
pues de lo contrario se producirá un error interceptable. Una vez eliminado, este registro sigue siendo el
registro actual. Puede observar, que si a continuación de Delete utiliza AbsolutePosition para conocer en
que registro está, la respuesta será -1, prueba de que está sobre un registro inexistente.
Propiedad Bookmark
Devuelve o establece un marcador que identifica de forma única el registro actual de un objeto
Recordset o define el registro actual de un Recordset como marcador válido.
Esto merece una pequeña aclaración. Bookmark en inglés significa ese papel que introducimos en un
libro para saber en qué página hemos dejado la lectura. En Visual Basic, significa el registro en el que
estamos actualmente (registro actual) Podemos conocer en que registro estamos mediante la siguiente
expresión:
Variable = MiRecordset.Bookmark
Pero tenemos que tener en cuenta que Variable es una variable tipo String (Sí, string, aunque parezca
que para conocer la posición de un registro debería ser un numérico, pero es así). Por lo tanto
deberíamos haber declarado la variable previamente como una variable tipo String
Dim Variable As String
Pero esta propiedad sirve para colocarnos en el registro que deseemos. Eso sí, previamente deberíamos
haber obtenido el Bookmark de ese registro. Imagínese que se está moviendo a lo largo del recordset y
hemos visto un registro donde tenemos un dato importante (por ejemplo, un máximo del valor de un
campo) No sabemos si habrá otro registro que tenga un valor mayor que este. Deberemos seguir
buscando, pero antes anotamos el Bookmark de ese registro
Variable = MiRecordset.Bookmark
Seguimos buscando moviéndonos por todo el recordset, y comprobamos que no hay otro registro con un
valor mayor. Queremos volver a aquel registro. Para ello forzamos a que el registro cuyo Bookmark sea
igual a Variable se convierta en registro actual:
MiRecordset.BookMark = Variable
Y se colocará en el registro deseado.
Solamente se puede ver la propiedad Bookmark en aquellos recordsets que tengan la propiedad
Bookmarkable a True. En un Recordset basado completamente en tablas del motor de base de datos
Microsoft Jet, el valor de la propiedad Bookmarkable es True y pueden usarse marcadores. Sin
embargo, otros productos de bases de datos pueden no aceptar los marcadores. Por ejemplo, no se
pueden usar marcadores en un Recordset basado en una tabla anexa Paradox que no tiene clave
principal.
La propiedad Bookmark se almacena internamente como matriz de Byte. Por esta razón, si se intenta
usar la propiedad Bookmark en una operación de comparación, se producirá un error interceptable.
Antes de tener acceso a la propiedad Bookmark, copie los valores de los marcadores a variables cadena
y efectúe las comparaciones usando dichas variables cadena. Por ejemplo, el siguiente código compara
marcadores en dos objetos Recordset:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 341
Dim Marca1 as String, Marca2 as String
Dim Rs1 as Recordset, Rs2 as Recordset
Set Rs1 = Db.OpenRecordset("Títulos")
Set Rs2 = Rs1.Clone()
Marca1 = Rs1.Bookmark
Marca2 = Rs2.Bookmark
If Marca1 = Marca2 Then Print "Esta comparación es válida "
No intente realizar la siguiente co mp aración, aunque a prim era vista parezca igual :
If Rs1.Bookmark = Rs2.Bookmark Then ..... Porque dará error.
No hay límite en el número de marcadores que pueden establecerse. Para crear un marcador para otro
registro distinto del registro actual, muévase al registro deseado y asigne el valor de la propiedad
Bookmark a una variable String que identificará el registro.
Para asegurarse de que el Recordset acepta marcadores, inspeccione el valor de su propiedad
Bookmarkable antes de usar la propiedad Bookmark. Si Bookmarkable es False, el Recordset no acepta
marcadores, y el uso de la propiedad Bookmark produce un error interceptable.
Si la propiedad Bookmark se establece a un valor que corresponda a un registro eliminado, se produce
un error interceptable.
Propiedad LastModified
Devuelve un marcador que indica el registro más recientemente agregado o modificado.
Sintaxis
NombreRecordset.LastModified
El valor devuelto por esta propiedad es un tipo de datos Variant o String. (Similar al devuelto por
Bookmark) LastModified se puede usar para colocarse en el registro más recientemente agregado o
actualizado.
Esta propiedad puede usarse para volver al último registro que ha sido modificado. Basta para ello
igualar la propiedad Bookmark a la propiedad LastModified :
NombreRecordset.Bookmark = NombreRecordset.LastModified
Métodos MoveFirst, MoveLast, MoveNext, MovePrevious
Estos métodos son aplicables a todos los tipos de recordset.
Se sitúan en el primer, el último, el siguiente o el anterior registro del objeto Recordset especificado y lo
convierten en el registro actual.
Sintaxis
MiRecordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}
Puede utilizar los métodos Move para desplazarse de un registro a otro sin aplicar una condición.
Al abrir el conjunto de registros indicado en Recordset, el primer registro pasa a ser el registro actual y
en la propiedad BOF se establece False. Si el conjunto no contiene ningún registro, se establecerá en
BOF el valor True y no habrá registro actual.
Si el primer o el último registro ya es el actual al utilizar MoveFirst o MoveLast, el registro actual no
varía.
Si utiliza MovePrevious cuando el registro actual sea el primero, en la propiedad BOF se establecerá
True y no habrá registro actual. Si utiliza de nuevo MovePrevious, se producirá un error y BOF continuará
con el valor True.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 342
Si utiliza MoveNext cuando el registro actual sea el último, en la propiedad EOF se establecerá True y
no habrá registro actual. Si utiliza de nuevo MoveNext, se producirá un error y EOF continuará con el
valor True.
Si Recordset hace referencia a un objeto Recordset de tipo tabla o a un objeto Table, el movimiento se
hará según el índice actual de la tabla. Para establecer el índice actual puede usar la propiedad Index. Si
no establece un índice actual, el orden de los registros devueltos no estará definido.
Si utiliza MoveLast en un objeto Recordset basado en una consulta SQL o QueryDef, se forzará la
terminación de la consulta, poblando completamente el objeto Recordset.
No es posible utilizar los métodos MoveFirst ni MovePrevious en los Recordset tipo snapshot de
desplazamiento hacia delante.
Para desplazar la posición del registro actual en un objeto Recordset un número de registros
determinado hacia adelante o hacia atrás, utilice el método Move.
Método Move
Desplaza la posición del registro actual en un objeto Recordset.
Sintaxis
MiRecordset.Move filas[, inicio]
Donde :
filas es un valor de tipo Long con signo que especifica el número de filas (de registros) que se desplaza
la posición. Si filas es mayor que 0, la posición se desplaza hacia adelante (hacia el final del archivo). Si
es menor que 0, la posición se desplaza hacia atrás (hacia el principio del archivo).
Inicio (opcional) es un valor de tipo String que identifica un marcador. Si se especifica inicio, el
desplazamiento será relativo al marcador indicado. Si se omite, Move comenzará por el registro actual.
El marcador que debe utilizarse para definir el registro Inicio debe ser un Bookmark o similar
(LastModified, por ejemplo)
Si se especifica una posición anterior al primer registro, la posición del registro actual se situará al
principio del archivo (BOF). Si se especifica una posición posterior al último registro, la posición del
registro actual se situará al final del archivo (EOF).
Si el objeto Recordset no contiene registros y el valor de su propiedad BOF es True, el uso de este
método para desplazarse hacia atrás producirá un error interceptable en tiempo de ejecución. Lo mismo
ocurrirá si el valor de la propiedad EOF es True y pretende desplazarse hacia adelante. Si las
propiedades BOF o EOF tienen el valor True y se intenta usar el método Move sin un marcador válido,
se generará un error interceptable.
Si el objeto Recordset está basado en una consulta, la operación forzará la ejecución de la consulta en el
número de filas especificado..
Métodos FindFirst, FindLast, FindNext, FindPrevious
Estos métodos no se pueden aplicar a un recordset tipo Tabla
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 343
Buscan el primer, el último, el siguiente o el anterior registro de un objeto Recordset de tipo instantánea u
hoja de respuestas dinámica, que satisfaga el criterio especificado y lo convierte en el registro actual.
MiRecordset.{FindFirst | FindLast | FindNext | FindPrevious} criterio
Sintaxis
MiRecordset es el nombre de un objeto Recordset.
Criterio es una expresión de cadena (como la cláusula WHERE de una instrucción SQL, sin la palabra
WHERE) que se utiliza para buscar un registro.
Si no se encuentra ningún registro que satisfaga el criterio, el puntero de registro actual se situará en el
primer registro del objeto Recordset y se establecerá en la propiedad NoMatch el valor True. Si
Recordset contiene más de un registro que satisfaga el criterio, FindFirst hallará el primero de ellos,
FindNext el siguiente y así sucesivamente. La propiedad NoMatch tomará en este caso el valor False.
Compruebe siempre el valor de la propiedad NoMatch para determinar si la operación de búsqueda ha
tenido éxito. Si la búsqueda ha tenido éxito, NoMatch se establece a False. Si ha fracasado, NoMatch
se establece a True y el registro actual pasa a ser el primero del objeto Recordset. Por ejemplo:
Dim Estabaaqui as String
Estabaaqui = Recordset.Bookmark
Recordset.FindFirst "Nombre = 'Luis' "
If Recordset.NoMatch = True Then
Recordset.Bookmark = Estabaaqui
' Busca un nombre. Recuerde siempre las
comillas dobles para la expresión de búsqueda y las
comillas simples si se trata de un dato string.
'Si no se ha encontrado
' Si no se ha encontrado, vuelve al que era el
‘registro actual.
Else
.
.
' Sí se ha encontrado.
Aquí las instrucciones adecuadas
End If
No es posible utilizar estos métodos en un objeto Recordset de tipo snapshot de desplazamiento hacia
delante.
Al buscar campos que contengan fechas, deberá utilizar el formato de fecha de los Estados Unidos
(mes-día-año), incluso cuando no utilice la versión para este país del motor de base de datos Jet, pues
de lo contrario es posible que no se encuentren los datos buscados. Puede utilizar la función Format
para convertir la fecha. Por ejemplo:
Mirecordset.FindFirst "fecha > #" & Format(mifecha, "mm/dd/yyyy" ) & "#"
Observe que las fechas, aparte de ponerlas en americano, hay que presentarlas entre almohadillas (#).
Observe lo dicho mas atrás para las comillas dobles en la expresión de búsqueda.
Método Seek
Este método solo se puede usar con recordsets tipo Tabla
Si no podemos usar los métodos Find en un recordset tipo Tabla, ¿Qué podemos hacer para buscar un
dato en un recordset de este tipo? Usar el método Seek
El método Seek busca el primer registro de un objeto Recordset indexado de tipo Table que cumple el
criterio especificado para el índice activo y lo convierte en el registro activo. Sólo funciona en espacios de
trabajo Microsoft Jet.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 344
Sintaxis
MiRecordset.Seek comparación, clave1, clave2...clave13
Donde MiRecordset es un recordset de tipo Table que tiene definido un índice en el campo por el que
se va a realizar la búsqueda. Como podemos tener varios índices en una tabla, deberemos indicarle cual
es el índice de búsqueda. Una vez que se lo indiquemos, ese índice será el Indice activo.
comparación Es una de esta expresiones de cadena: <, <=, =, >=, >.
clave1, clave2...clave13 Son uno o más valores que corresponden a los campos en el índice activo del
objeto Recordset. Puede utilizar un argumento de hasta 13 claves.
Antes de usar Seek se debe establecer el índice activo. Todo índice tiene un nombre. Habíamos visto
cuando creábamos un índice que debía tener un nombre. Recuerde el ejemplo:
Set MiIndice2 = MiTabla2.CreateIndex("IndicePeliculas")
Puede ver el nombre de ese índice en la Fig. 20.7 En este caso habíamos creado el índice mediante
código y hemos podido controlar su nombre. Si lo hubiésemos creado directamente en Access, el
nombre que le pone por defecto es el mismo que el nombre del campo.
Ese nombre del índice es el que debemos usar para crear el índice activo. Por ejemplo, si quisiéramos
que el índice activo fuese el IndicePeliculas lo haríamos índice activo mediante la siguiente instrucción:
MiRecordset.Index = "IndicePelículas"
A partir de ahora, el campo (o campos) de ese índice será sobre el que realizaremos la búsqueda
mediante Seek. Para encontrar el registro que tenga por valor 00000012 usaremos la expresión
MiRecordset.Seek "=", "00000012"
Ese registro será ahora el registro actual. Si hubiese mas de un registro con ese valor, el registro actual
será el primero que cumpla esa condición
En el ejemplo hemos utilizado el comparador = para buscar un registro cuyo valor en el campo indicado
por el índice activo sea igual al indicado en el siguiente parámetro (00000012). Si quisiésemos encontrar
un registro cuyo valor sea superior a 00000012 usaríamos la expresión
MiRecordset.Seek ">", "00000012"
Pero observe ahora que el 0000012 no es un número, es una cadena de caracteres. No se preocupe.
Seek puede comparar el contenido de un campo numérico, de un campo texto, de un campo
Fecha/Hora, etc. Eso sí, debe compararlo con un valor del mismo tipo, es decir, si el contenido del
campo es numérico, en el parámetro Clave1 deberemos pasarle un campo numérico, si el campo es
texto, deberemos pasarle un dato tipo texto, etc.
El método Seek busca en los campos clave especificados y localiza el primer registro que cumpla el
criterio especificado por comparación y clave1. Cuando lo encuentra, convierte ese registro en activo y la
propiedad NoMatch se establece en False. Si el método Seek no consigue localizar ninguna
coincidencia, la propiedad NoMatch se establece en True y el registro activo es indefinido.
Si comparación es igual (=),mayor o igual (>=) o mayor que (>), Seek empezará al principio del índice y
buscará hacia adelante.
Si comparación es menor que (<) o mayor o igual que (<=), Seek empezará al final del índice y buscará
hacia atrás, a menos que haya entradas de índice duplicadas al final. En tal caso, Seek empezará en
una entrada cualquiera entre las entradas duplicadas existentes al final del índice.
Debe especificar valores para todos los campos definidos en el índice. Si utiliza Seek con un índice de
múltiples columnas y no especifica un valor de comparación para cada campo del índice, no podrá usar
el operador de igual (=) en la comparación. Esto se debe a que algunos de los campos de criterio(clave2,
clave3, etc) estarán predeterminados en Null, lo que posiblemente no concordará. Por tanto, el operador
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 345
de igual sólo funcionará correctamente si tiene un registro que sea Null en su totalidad, excepto la clave
que está buscando. Es aconsejable usar el operador mayor que o igual en su lugar.
En el ejemplo siguiente se toman los nombres de las calles y otros datos de una tabla llamada
Calles_Nombre, cuyo campo NombreVia esta indexado. El índice tiene el mismo nombre que el campo
porque se creó directamente con Access. El procedimiento BBuscaCalle_Click busca la primera calle
cuyo nombre coincida con las letras tecleadas en el TextBox TBBuscaCalle
Set BaseDatos = OpenDatabase("C:\Callejero\Calles.mdb")
Set RsCalles = BaseDatos.OpenRecordset("Calles_Nombre", dbOpenTable)
Private Sub BBuscaCalle_Click()
RsCalles.Index = "NombreVia"
RsCalles.Seek ">=", TBBuscaCalle
If RsCalles.NoMatch = False Then
TBNombreCalle = RsCalles!nombrevia
Else
TBNombreCalle = "No se encontró la calle"
End If
End Sub
Método Clone
En muchas ocasiones es necesario crear un Recordset que sea copia exacta de otro. Las ocasiones en
las que es necesario hacer esto pueden ser variadas, pero vamos a destacar una : crear un Recordset
idéntico al Recordset de un control Data, para trabajarlo con código durante una parte de la ejecución del
programa. Otras aplicaciones pueden ser copiar el Recordset de otra máquina a través de la Red de
Area Local, ... y donde podamos llegar con nuestra imaginación.
La sintaxis de Clone es la siguiente :
Sintaxis
Set Duplicado = Original.Clone
Donde Duplicado es una variable tipo Recordset, y Original es el Recordset que se va a duplicar.
Con el método Clone puede crear múltiples Recordsets. Cada uno de ellos puede tener su propio
registro actual. El uso de Clone no modifica los datos de los registros. Puede modificar un registro desde
cualquier Recordset, bien desde el que sirvió de original, bien desde cualquiera de sus copias, pero debe
hacerlo invocando los métodos Edit - Update. Puede compartir marcadores entre dos o más Recordsets
creados de esta forma.
Puede utilizar el método Clone cuando desee realizar en un conjunto de registros una operación que
requiera varios registros actuales. Este método es más rápido y eficiente que crear un nuevo Recordset.
Inicialmente, un Recordset creado con Clone carece de registro actual. Para hacer que un registro sea el
actual antes de utilizar el Recordset copia, puede utilizar cualquiera de los métodos Move, Find o Seek
(solo para Recordsets tipo Tabla), o establecer su propiedad Bookmark
El hecho de cerrar el Recordset original no afecta al duplicado y viceversa.
Nota No es posib le utilizar este mé
todo c on sn apsho ts de desplazamiento hacia delante (objetos
Records et de tipo instantánea con la opción d bForw ardOnly activ ada).
Método Requery
El método Requery actualiza los datos de un objeto Recordset, volviendo a ejecutar la consulta con la
que se ha creado ese Recordset. Este método debe usarse cada vez que se sospeche que los datos de
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 346
la Base de datos han cambiado, y se quieran presentar los datos actualizados. Es un método típico de
una BD que se está usando desde varios puestos a través de una Red de Area Local.
Sintaxis
NombreRecordset.Requery [NuevoQueryDef]
Donde NombreRecordset es el nombre del Recordset, y NuevoQueryDef (opcional) es una consulta
almacenada
No es posible utilizar el método Requery en objetos Recordset tipo Snapshot o en los Dynaset que
tengan la propiedad Restartable a False, ni tampoco en los objetos Recordset de tipo Tabla.
Si los valores de las propiedades BOF y EOF del objeto Recordset son ambos True después de utilizar
el método Requery, la consulta no habrá devuelto ningún registro y el objeto Recordset no contendrá
datos.
Transacciones
Métodos BeginTrans, CommitTrans y Rollback
Est os m é
to do s so n m é
to do s del Ob jeto W or ks pac e
Veamos estos tres métodos que, dadas sus funciones, deben estudiarse conjuntamente.
Supongamos un Banco. Debe hacer una transferencia entre dos cuentas corrientes que están en la
misma base de datos. La operación es sencilla : Busca la cuenta origen y crea un nuevo registro. Apunta
en el campo OPERACIÓN una T de Transferencia, en el campo IMPORTE apunta el valor del dinero a
transferir, y en el campo SALDO pone la diferencia entre lo que había en ese campo en la última
operación, menos el importe del dinero transferido.
A continuación hace un proceso similar con la cuenta destino, pero en este caso, sumándole el importe
de la transferencia. No hay problemas. Pero que pasa si, una vez sacado el dinero de la cuenta origen,
no se puede ingresar en la cuenta destino, por la razón que sea (cuenta bloqueada, no existe esa
cuenta, fallo de la red de área local) Obviamente la operación no se ha completado, y hay que devolver
el dinero a la cuenta origen. Podría hacerse un apunte, metiendo la misma cantidad de dinero que se ha
extraído anteriormente, y su saldo no se verá afectado. Pero no sé lo que pensaría el cliente cuando vea
un estadillo de su cuenta, en la que le han sacado una cantidad de dinero, aunque en el siguiente apunte
se lo hayan vuelto a introducir.
Para evitar estas situaciones usamos lo que se denomina una Transacción, que es una combinación de
estos tres métodos. Con el método BeginTrans iniciamos la Transacción. Con CommitTrans
terminamos la transacción y se guardan los cambios realizados (En ambas cuentas a la vez, en el caso
del ejemplo). Con Rollback se termina la transacción sin llegar a guardar los cambios, quedando el
Objeto Workspace afectado por las operaciones internas a esa transacción tal y como estaba antes de
comenzar dicha operación.
Dado que una transacción pertenece a un Workspace, deberemos aplicar estos métodos al Workspace
que ese usuario tenga abierto. Es decir, en un sistema con varios usuarios que están trabajando
simultáneamente sobre una Base de Datos, un determinado usuario deberá entrar con un Workspace
propio (una sesión de trabajo solo para él). En estas condiciones podemos crear una transacción. Y aquí
comenzamos a ver la necesidad de crear Workspaces distintos para distintos usuarios. Veremos un
poco más adelante como se crean los Workspaces.
Sintaxis
MiSesión.BeginTrans
MiSesión.CommitTrans
MiSesión.Rollback
Dentro de un objeto Workspace, las transacciones son siempre globales y no se limitan sólo a la base de
datos o al conjunto de registros. Si realiza operaciones en más de una base de datos o conjunto de
registros durante una transacción en un objeto Workspace, el método Rollback deshará todas las
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 347
operaciones en todos ellos. Quiere esto decir que una transacción debe iniciarse al comenzar una
determinada operación, realizar esa operación sin realizar ninguna otra durante ese tiempo, terminar la
operación y finalizar la transacción, bien con CommitTrans o con Rollback.
Si desea tener transacciones simultáneas, lo mas indicado es crear varios objetos Workspace para usar
uno con cada transacción.
Puede anidar transacciones. Es posible tener hasta cinco niveles de transacciones abiertos a un tiempo
en un mismo objeto Workspace utilizando múltiples combinaciones anidadas de BeginTrans y
CommitTrans o Rollback. En este caso, el orden de finalización de una transacción debe ser siempre de
menor a mayor nivel jerárquico, es decir, se deberá cerrar primero la transacción que esté mas interior
dentro del anidamiento, y así sucesivamente. Si cierra una transacción anidada mediante CommitTrans,
y posteriormente cierra una transacción que abarque a esta última con Rollback, los cambios de la
primera transacción NO quedarán guardados.
(Cuando se utilizan bases de datos SQL ODB C externas no es pos ible anidar las transacciones).
Si cierra un objeto Workspace sin guardar o deshacer las transacciones pendientes, éstas se desharán
automáticamente.
Algunas bases de datos pueden no admitir las transacciones. En este caso la propiedad Transactions
del objeto Database o Recordset tendrá el valor False. Lea detenidamente la Ayuda de estos métodos
antes de trabajar con ellos.
El hecho de usar transacciones, aparte de lo que significa para asegurar la integridad de los datos,
ahorra accesos al disco (Importantísimo en algunas redes LAN y WAN), ya que los cambios a introducir
se van almacenando en un búfer en la memoria, y se vuelcan al disco solamente en el momento de
terminar la transacción de modo afirmativo con CommitTrans.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 348
La protección de accesos a una base de datos Access. Usuarios, Workspaces, Grupos de Trabajo,
Grupos de Usuarios. La base de datos de sistema.
Acabamos de ver que es necesario poder crear Workspaces para cada usuario. Hasta ahora, y para no
complicar el estudio de las bases de datos, habíamos usado solamente el Workspaces(0) que VB crea
automáticamente. Vamos a entrar ahora en la creación de Usuarios (Users) y Workspaces. El método
para crear Workspaces es el CreateWorkspace, método del dbEngine. Comencemos con una mirada a
este objeto desde el punto de vista de DAO. No olvide que el dbEngine es el motor de bases de datos
Jet.
El dbEngine. Visión desde DAO
El objeto dbEngine es el objeto de nivel más alto en el modelo de objeto DAO. Es el encargado de
contener y controlar todos los objetos DAO. Hay un solo objeto dbEngine, inherente a la aplicación, y no
se pueden crear más.
Tiene como cualquier objeto DAO sus propiedades y métodos. Vamos a ver alguna propiedad, en orden
ascendente de importancia práctica.
Propiedad Version
Devuelve la versión actual de DAO en uso. El tipo de datos es String (p.e., "3.5" )
Propiedad DefaultType
Establece o devuelve un valor que indica qué tipo de espacio de trabajo (Microsoft Jet u ODBCDirect)
utilizará el próximo objeto Workspace que se cree. Puede tomar los valores:
dbUseJet
dbUseODBC
Crea objetos Workspace conectados al motor de base de datos Microsoft Jet.
Crea objetos Workspace conectados a un origen de datos ODBC.
Propiedad DefaultUser. Establece el nombre de usuario utilizado para crear el Workspace
predeterminado cuando se inicializa.
Propiedad DefaultPassword. Establece la contraseña utilizada para crear el Workspace
predeterminado cuando se inicializa.
El DefaultUser es un tipo de datos String, que puede tener entre 1 y 20 caracteres de longitud en
espacios de trabajo Microsoft Jet y cualquier longitud en espacios de trabajo ODBCDirect.
El DefaultPassword es un tipo de datos String que puede tener hasta 14 caracteres de longitud en bases
de datos Microsoft Jet y cualquier longitud en conexiones ODBCDirect. Puede contener cualquier
carácter excepto 0 ASCII.
De modo predeterminado, la propiedad DefaultUser se establece a "administrador" y la propiedad
DefaultPassword se establece a una cadena de longitud cero ("").
Para que estas propiedades tenga efecto, debe establecerla antes de llamar a cualquier método DAO.
Propiedad LoginTimeout. Establece o devuelve el número de segundos que se esperará antes de que
se genere un error cuando se intenta conectar a una base de datos de ODBC. Tiene como valor
predeterminado, 20 segundos.
Propiedad IniPath. Devuelve la ubicación de la información de Registro de Windows de Microsoft Jet. El
método SetOption le permite sobrescribir los valores del Registro de Windows para el motor de base de
datos Microsoft Jet. (Recuerde que cualquier operación indebida sobre el registro de Windows puede
hacerle perder toda la información de su PC)
Propiedad SystemDB
LSB
(Muy importante)
Visual Basic – Guía del Estudiante
Capítulo 1
Página 349
Establece o devuelve la ruta de acceso del archivo de información del grupo de trabajo (sólo espacios de
trabajo Microsoft Jet). Este archivo es una base de datos Access, que normalmente se llama
System.Mdw (Observe que la extensión es distinta a la .Mdb a la que nos tiene acostumbrados Access)
Access usa este fichero y lo guarda generalmente en C:\Windows\System. Pero puede copiar esta base
con otro nombre, y colocarla en el directorio que quiera. Lo único que tendrá que hacer es indicarle al
dbEngine su nombre y ubicación mediante esta propiedad SystemDB En esa base de datos se guarda
la información de los usuarios. Se guarda su nombre y su contraseña. Lógicamente no se puede leer con
Access, aunque la abre como si se tratase de una base de datos ordinaria, pero cuando pretende abrir
una tabla, no la visualiza.
(NOTA. - La ayuda dice que el nombre predeterminado es System.Mda. Ese era el nombre para
versiones antiguas del Motor Jet. En mi PC, con W98 y VB6, y con Access98 solamente encuentro
System.Mdw)
Creación de nuevos usuarios Método CreateUser
(Sólo espacios de trabajo Microsoft Jet). Crea un nuevo Usuario, e introduce sus datos en el archivo de
información del grupo de trabajo (Base de Datos System.Mdw o la especificada en la propiedad
SystemDB) El método CreateUser corresponde al Workspace o al Objeto Group.
Para crear un nuevo usuario deberemos suministrar la siguiente información:
Nombre del usuario, PID y contraseña. La sintaxis de CreateUser es:
Set User = Objeto.CreateUser (Nombre, PID, contraseña)
Donde User es la variable tipo objeto User que desea crear. Debe declararse como User)
Objeto El nombre del Workspace (o del objeto objeto Group) que quiere utilizar para crear el nuevo
objeto User.
Nombre Nombre del nuevo usuario
PID. Identificador de Usuario. Debe contener de 4 a 20 caracteres alfanuméricos
Contraseñal. Contraseña para el nuevo usuario. La contraseña puede tener hasta 14 caracteres de
longitud y puede incluir cualquier carácter excepto el carácter ASCII 0
Esto merece algún comentario. El nuevo usuario debe crearlo un Workspace (o un Group, pero de eso
no nos vamos a ocupar por ahora) Lo normal es crear el nuevo usuario con el Workspaces(0) que como
sabe, lo crea automáticamente Visual Basic.
Recuerde que antes de crear un nuevo usuario, debe indicar donde está la base de datos con la
información del systema, mediante la propiedad SystemDB
DBEngine.SystemDB = "C:\Windows\System\System.Mdw")
Con las siguientes instrucciones se crea un nuevo usuario
Dim NuevoUser As User
Set NuevoUser = Workspaces(0).CreateUser("Luis", "EsteesmiPID", "MiContraseña")
Workspaces(0).Users.Append NuevoUser
Podemos saber cuantos usuarios tiene el Workspaces(0) y su nombre. Con las siguientes
instrucciones vamos a introducir los nombres de los usuarios en la lista ListUsers
ListUsers.Clear
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
Creación de nuevos Workspaces. Método CreateWorkspace
Podemos crear cuantos Workspaces necesitemos. Recuerde que un Workspace es una sesión de
trabajo. Y una sesión de trabajo se abre para que trabaje un usuario. Por eso, a la hora de crear
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 350
un Workspace debemos indicarle para que usuario, y la contraseña de ese usuario. Como el
objeto Workspace pertenece al dbEngine, es este objeto el que debe crearlo.
La sintaxis es la siguiente:
Set NuevoWorkSpace = DBEngine.CreateWorkspace (Nombre, Usuario, Contraseña, Tipo)
NuevoWorkSpace es el Workspace que queremos crear, que habremos declarado como variable tipo
objeto Workspace.
Nombre es el nombre del Workspace (P.e., MiSesion)
Usuario Nombre de un usuario registrado en la base de datos del sistema (Que lo habremos creado
con CreateUser) que será el propietario del nuevo objeto Workspace.
Contraseña La contraseña del Usuario propietario del Workspace.
Tipo (Opcional). Indica el tipo de espacio de trabajo. Puede tomar los valores dbUseJet para crear un
espacio de trabajo Microsoft Jet, o dbUseODBC para crear un espacio de trabajo ODBCDirect. Si omite
tipo, la propiedad DefaultType del objeto DBEngine determinará a qué tipo de origen de datos está
conectado el Workspace
No es necesario añadir el nuevo Workspace a la colección Workspaces
Veamos un ejemplo de cómo crear un Workspace para el usuario Luis creado anteriormente:
Dim NewWS as Workspace
Set NewWS = DBEngine.CreateWorkspace("SesiondeLuis", "Luis", "MiContraseña")
DBEngine.Workspaces.Append NewWS
Podemos ver todos los Workspaces existentes. En las siguientes instrucciones podemos ver el código
para listarlos en ListWS
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
Debe tenerse en cuenta que el objeto Workspace es un objeto que solamente existe mientras está
ejecutándose la aplicación. Cuando salimos de la aplicación, ese Workspace desaparece. No
ocurre lo mismo con el Usuario, que queda en la base de datos del sistema, es decir, es un objeto
persistente.
Las partes de código expuestas se han sacado de un ejemplo creado para ver el número y nombre de
los usuarios existentes, Workspaces y DataBases. Es un ejemplo para explicar estos conceptos. No
tiene otra finalidad.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 351
Fig. 20.9 Aspecto de la interface gráfica del ejercicio para crear Users y Workspaces
Código de este ejercicio
General/Declaraciones
Option Explicit
Dim VarDrag As String
Dim NuevoWS() As Workspace
Private Sub BAnadirUser_Click()
On Error GoTo RutErr
Dim NomUsuario As String, I As Integer
If BAnadirUser.Caption = "Añadir" Then
TBNuevoUserName.Visible = True
TBNuvoUsePID.Visible = True
TBNuevoUserPw.Visible = True
LNUserName.Visible = True
LNuevoUserPID.Visible = True
LNuevoUserPw.Visible = True
BAnularUser.Left = 3480
BAnularUser.Visible = True
BBorrarUser.Visible = False
BAnadirUser.Caption = "O.K."
Exit Sub
End If
If BAnadirUser.Caption = "O.K." Then
Dim NuevoUser As User
Set NuevoUser = Workspaces(0).CreateUser(TBNuevoUserName, TBNuvoUsePID, TBNuevoUserPw)
Workspaces(0).Users.Append NuevoUser
TBNuevoUserName.Visible = False
TBNuvoUsePID.Visible = False
TBNuevoUserPw.Visible = False
LNUserName.Visible = False
LNuevoUserPID.Visible = False
LNuevoUserPw.Visible = False
BAnularUser.Visible = False
BBorrarUser.Visible = True
BAnadirUser.Caption = "Añadir"
ListUsers.Clear
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 352
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
BAnularUser.Visible = False
BAnadirUser.Visible = True
End If
RutErr:
If Err = 3304 Then
MsgBox "Debe introducir el PID (Mínimo 5 caracteres, máximo 20 caracteres)"
Exit Sub
Else
If Err > 0 Then MsgBox "Ha ocurrido el error " & Err & "."
End If
End Sub
Private Sub BAnadirWs_Click()
On Error GoTo RutErr
If BAnadirWs.Caption = "Añadir" Then
TBNuevoWorkspace.Visible = True
TBNombreUser.Visible = True
TBNuevoWSPw.Visible = True
LNWSName.Visible = True
LNombreUsuario.Visible = True
LUserPw.Visible = True
BAnularWS.Left = 5520
BAnularWS.Visible = True
BEliminarWs.Visible = False
BAnadirWs.Caption = "O.K."
Exit Sub
End If
If BAnadirWs.Caption = "O.K." Then
Dim NumWS As Integer
NumWS = Workspaces.Count
ReDim Preserve NuevoWS(NumWS)
Dim I As Integer, NomWS As String
Set NuevoWS(NumWS) = DBEngine.CreateWorkspace(TBNuevoWorkspace,
TBNuevoWSPw)
DBEngine.Workspaces.Append NuevoWS(NumWS)
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
BAnadirWs.Caption = "Añadir"
TBNuevoWorkspace = ""
TBNombreUser = ""
TBNuevoWSPw = ""
TBNuevoWorkspace.Visible = False
TBNombreUser.Visible = False
TBNuevoWSPw.Visible = False
LNWSName.Visible = False
LNombreUsuario.Visible = False
LUserPw.Visible = False
BAnularWS.Visible = False
BEliminarWs.Visible = True
End If
RutErr:
If Err = 3029 Then
MsgBox "El Password usado no coincide con el de ese Usuario (User)"
Exit Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
TBNombreUser,
Página 353
End If
End Sub
Private Sub BAnularUser_Click()
If BAnadirUser.Caption = "O.K." Then
TBNuevoUserName.Visible = False
TBNuvoUsePID.Visible = False
TBNuevoUserPw.Visible = False
LNUserName.Visible = False
LNuevoUserPID.Visible = False
LNuevoUserPw.Visible = False
BAnularUser.Visible = False
BBorrarUser.Visible = True
BAnadirUser.Caption = "Añadir"
End If
If BBorrarUser.Enabled = True Then
BBorrarUser.Enabled = False
BAnadirUser.Visible = True
BAnularUser.Visible = False
ListUsers.ListIndex = -1
End If
End Sub
Private Sub BAnularWS_Click()
If BAnadirWs.Caption = "O.K." Then
BAnadirWs.Caption = "Añadir"
TBNuevoWorkspace = ""
TBNombreUser = ""
TBNuevoWSPw = ""
TBNuevoWorkspace.Visible = False
TBNombreUser.Visible = False
TBNuevoWSPw.Visible = False
LNWSName.Visible = False
LNombreUsuario.Visible = False
LUserPw.Visible = False
BAnularWS.Visible = False
BEliminarWs.Visible = True
End If
If BEliminarWs.Enabled = True Then
BEliminarWs.Enabled = False
BAnadirWs.Visible = True
BAnularWS.Visible = False
End If
End Sub
Private Sub BBorrarUser_Click()
Dim NomUsuario As String, I As Integer
Workspaces(0).Users.Delete ListUsers.Text
ListUsers.Clear
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
BAnularUser.Visible = False
BAnadirUser.Visible = True
End Sub
Private Sub BEliminarWs_Click()
Dim I As Integer, NomWS As String, NumWS As Integer
For I = 0 To DBEngine.Workspaces.Count - 1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 354
NomWS = DBEngine.Workspaces(I).Name
If NomWS = ListWS.Text Then NumWS = I
Next I
Workspaces(NumWS).Close
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
BEliminarWs.Enabled = False
BAnularWS.Visible = False
BAnadirWs.Visible = True
End Sub
Private Sub BSalir_Click()
End
End Sub
Private Sub BVerIni_Click()
Shell "Notepad.exe " & App.Path & "\Cap20Usr.INI", vbNormalFocus
End Sub
Private Sub Form_Activate()
On Error GoTo RutErr
Dim LineaEntr As String
Dim LineaEntr8 As String
Dim I As Integer, NomUsuario As String
Dim PathFichero As String
Open App.Path & "\Cap20Usr.INI" For Input As #1
Do Until EOF(1)
Line Input #1, LineaEntr
LineaEntr8 = ""
LineaEntr8 = Left(LineaEntr, 8)
If UCase(LineaEntr8) = "PROYCAPT" Then Me.Caption = Right(LineaEntr, Len(LineaEntr) - 9)
If UCase(LineaEntr8) = "DBENGINI" Then PathFichero = Trim(Right(LineaEntr, Len(LineaEntr) - 9))
Loop
Close #1
LBDSys = PathFichero
TBTextINI = PathFichero
DBEngine.SystemDB = PathFichero
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
For I = 0 To DBEngine.Workspaces.Count - 1
NomUsuario = Workspaces(I).Name
ListWS.AddItem NomUsuario
Next I
RutErr:
If Err = 3028 Then
MsgBox "No se puede abrir la base de datos del sistema. Compruebe que su Path y nombre son
correctos. Vealo en Ver Ini"
End If
End Sub
Private Sub ListUsers_Click()
BAnadirUser.Visible = False
BBorrarUser.Enabled = True
BAnularUser.Left = 4560
BAnularUser.Visible = True
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 355
Private Sub ListWS_Click()
BEliminarWs.Enabled = True
BAnadirWs.Visible = False
BAnularWS.Left = 6600
BAnularWS.Visible = True
End Sub
Private Sub Text1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Shift = 1 And Button = 1 Then
VarDrag = Text1.Text
Text1.Drag
End If
End Sub
El fichero Cap20Usr.INI que debe estar necesariamente en la misma carpeta que el programa, en el
caso del PC del autor tiene esta forma
REM Visual Basic - Guía del Estudiante. Cap. 20. Creación de Usuarios y WorkSpaces
DBEngINI=C:\WinNT\System32\System.mdw
(Deberá cambiar el Path del fichero System.Mdw de acuerdo a como lo tenga en su ordenador.)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 356
Mantenimiento y Copia de Bases de Datos.
Vamos a ver dos métodos del Objeto DBEngine para el mantenimiento y copia de Bases de Datos
ACCESS.
En una Base de Datos ACCESS, cuando borramos un dato en realidad no lo estamos borrando, sino
marcándolo como borrado. (No intente recuperar un dato marcado y no borrado porque no se puede.)
Por lo tanto, verá que tras sucesivas operaciones de escritura / borrado en una BD, esta va aumentando
su tamaño. Se necesita un método que limpie todos los datos inservibles de la BD para disminuir su
tamaño. Este método también deberá reorganizar los índices y marcadores internos a esa BD. El objeto
DAO que debe hacer estas cosas es el Motor de Bases de Datos. Es decir, el Objeto DBEngine. Los
métodos son CompactDatabase, que hace una copia de la base de datos (no borra la BD original) sin
copiar los datos inútiles, y RepairDatabase, que intenta (no siempre lo consigue) reparar los datos
internos de una BD que presente datos corruptos (Se generan con bastante facilidad cuando apagamos
el ordenador con la base abierta)
Método CompactDatabase
Copia, compacta y da la opción de modificar la versión, el orden de intercalado y la codificación de una
base de datos cerrada.
Sintaxis
DBEngine.CompactDatabase BaseDatosAnt, BaseDatosNva [, inf_local [, opciones]]
BaseDatosAnt es el nombre del fichero de la base de datos a compactar. Debe expresar el Path
completo y el nombre del fichero (C :\MiCarpeta\MiBase.MDB) Si el nombre de archivo tiene extensión,
deberá especificarla. Si la red lo admite, también puede especificar una ruta de red, como por ejemplo
"\\MISERVID\MIDIR\MiBase.MDB".
BaseDatosNva es el nombre del fichero (con su Path completo) de la base de datos nueva, creada al
copiar la BaseDatosAnt, ya compactada. No es posible especificar en el argumento BaseDatosNva el
mismo archivo de base de datos que en BaseDatosAnt.
inf_local es una expresión de cadena utilizada para especificar el alfabeto usado a la hora de ordenar
datos de esa Base de Datos. El parámetro a introducir es el mismo que para el argumento similar usado
en la creación de la Base de Datos (dbLangGeneral para el caso de España). Este argumento es
opcional. Si se omite, la información local de BaseDatosNva será la misma que la de BaseDatosAnt.
Opciones nos permite cambiar alguna característica de la Base de Datos. Puede elegirse entre cifrarla o
no cifrarla y cambiar la versión del motor de bases de datos que va a usar la nueva Base de Datos.
dbEncrypt
dbDecrypt
dbVersion10
dbVersion11
dbVersion25
dbVersion30
Codifica la base de datos durante la compactación.
Descodifica la base de datos durante la compactación.
Crea una base de datos que utiliza la versión 1.0 del motor
Crea una base de datos que utiliza la versión 1.1 del motor
Crea una base de datos que utiliza la versión 2.5 del motor
Crea una base de datos que utiliza la versión 3.0 del motor
Jet
Jet
Jet
Jet
Se puede usar una constante (solamente) de encriptación y una (solamente) de Versión. Sólo se puede
compactar BaseDatosNva con una versión igual o posterior a la de BaseDatosAnt.
Lea detenidamente la ayuda en línea de este Método.
Método RepairDatabase
Intenta reparar una base de datos dañada que accede al motor de base de datos Microsoft Jet.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 357
Sintaxis
DBEngine.RepairDatabase NombreBase
Donde NombreBase es el nombre (Y path) del fichero que contiene la Base de Datos a reparar. Puede
especificar una ruta de red. P.e. : "\\MISERVID\ MIDIR\NombreBase.MDB".
Para poder reparar la base debe estar Cerrada. Recuerde, si está en un entorno multiusuario, que los
demás usuarios tampoco pueden tenerla abierta mientras la repara.
El método RepairDatabase también intenta validar todas las tablas del sistema y todos los índices. Los
datos que no puedan repararse se pierden. Si la base de datos no puede repararse, se producirá un
error interceptable.
Sugerencia Después de reparar una base de datos, es aconsejable compactarla con el método
CompactDatabase para desfragmentar el archivo y recuperar espacio en disco.
METODOS DEL OBJETO DataBase
Método Execute
Este Método es para el Objeto DataBase y para el Objeto QueryDef.
Ejecuta una consulta de acciones o una instrucción SQL en el objeto Database especificado.
Sintaxis
Para un objeto DataBase
NombreBD.Execute origen[, opciones]
Donde NombreBD es el nombre del objeto DataBase
Origen es una instrucción SQL
Opciones es un entero o constante que determina las características de integridad de
datos de la consulta, según se especifica mas adelante.
Para un objeto QueryDef
NombreQuerydef.Execute [opciones]
Donde NombreQuerydef es el nombre del objeto QueryDef cuya propiedad SQL especifica la
instrucción SQL a ejecutar.
Opciones igual que para el Objeto Database.
En opciones puede utilizar las siguientes constantes:
dbDenyWrite
dbInconsistent
dbConsistent
dbSQLPassThrough
dbFailOnError
dbSeeChanges
Deniega el permiso de escritura a los demás usuarios.
(Predeterminado) Actualizaciones inconsistentes.
Actualizaciones consistentes.
Paso a través de SQL. Hace que se pase la instrucción SQL a una
base de datos ODBC para su procesamiento.
Deshace las actualizaciones en caso de error.
Genera un error en tiempo de ejecución si otro usuario modifica los
datos que se están editando.
El método Execute sólo es válido para las consultas de acciones. Si utiliza Execute con otro tipo de
consultas, se producirá un error. Debido a que las consultas de acciones no devuelven registros,
Execute no devuelve un conjunto de registros.
Ejemplo. En el siguiente ejemplo, usamos EXECUTE para cambiar el campo Nombre en una tabla
llamada CLIENTES de una Base de Datos abierta, cuyo Objeto DataBase se llama BaseDatos. Para
poder “jugar” con el nombre a cambiar y el nombre cambiado, se introduce el nombre que queremos
cambiar en TBNombre2 y el nuevo nombre en TBNombre1
Dim RegistrosCambiados As Long
Dim MiSQL As String
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 358
MiSQL = "UPDATE CLIENTES SET NOMBRE = '" & TBNombre2 & "' WHERE NOMBRE= '" &
TBNombre1 & "'"
BaseDatos.Execute MiSQL, dbFailOnError
RegistrosCambiados = BaseDatos.RecordsAffected
MsgBox RegistrosCambiados
Dada una instrucción SQL sintácticamente correcta y teniendo los permisos adecuados, el método
Execute no fallará, aún cuando no pueda modificarse ni eliminarse una línea. Por lo tanto, debe
especificar siempre la opción dbFailOnError cuando utilice el método Execute para ejecutar una
consulta de actualización o eliminación. Esta opción generará un error interceptable y deshará todos los
cambios realizados con éxito cuando alguno de los registros afectados se encuentre bloqueado y no
pueda actualizarse o eliminarse.
Propiedad RecordsAffected
Para determinar el número de registros afectado por el último método Execute, puede utilizar la
propiedad RecordsAffected del objeto Database o Querydef. Por ejemplo, RecordsAffected contienen el
número de registros eliminados, actualizados o insertados al ejecutar una consulta de acciones. Al
utilizar el método Execute para ejecutar un objeto Querydef, en la propiedad RecordsAffected del
Querydef se establece el número de registros afectados.
Para obtener el mejor rendimiento, especialmente en un entorno multiusuario, puede anidar el método
Execute dentro de una transacción: Utilice el método BeginTrans en el objeto Workspace actual, use
luego el método Execute y complete la transacción con el método CommitTrans en el objeto Workspace.
De esta forma se guardarán los cambios en el disco y se liberarán los bloqueos que se hayan podido
producir durante la ejecución de la consulta.
IMÁGENES EN UNA BASE DE DATOS ACCESS
Una imagen (la fotografía de una persona por ejemplo) puede guardarse en una base de datos tipo
ACCESS y presentarse en un control Picture. ¡¡ Imagine una aplicación que sea una agenda de teléfonos
y pueda insertar la foto de la persona !!
Para introducir una imagen en una BD, el campo de esa BD donde se va a introducir la imagen debe ser
LongBinary ( si esa versión de ACCESS lo tiene) u Objeto OLE.
Introducir y presentar un bit-map en una base de datos es necesario hacerlo mediante un Control Data.
Un bit-map puede presentarse en un control Picture o en un control Image. Ambos son controles
enlazados a datos. Si introducimos un Control Data y un Control Picture o Control Image en el
Formulario, asociamos el Control Data a la Base de Datos, y el campo que contiene el gráfico a el
Control Picture (o Control Image) mediante sus propiedades DataSource = Nombre del Control data,
DataField = Nombre del Campo, tenemos el problema resuelto. Para meter un gráfico en la BD basta
con introducir ese gráfico en el Picture (o Image) mediante LoadPicture, por ejemplo, y guardar los datos
en la BD, bien cambiando el registro actual del Control data, bien mediante el método UpdateRecord de
dicho Control Data.
La asociación de la Base de datos al Control Data puede hacerse, bien mediante sus propiedades
DatabaseName y RecordSource, bien creando un Recordset con código e igualando la propiedad
Recordset del Control Data a ese Recordset.
Es posible que se pueda introducir y presentar un bit-map en un control Picture o Image de otra forma,
sin usar el control Data. Eso sí, complicando el código. No merece la pena liarse con esto. Lo mismo que
decíamos que necesitamos un Control Data cuando vamos a usar un DBGrid, debemos usar un Control
Data cuando vayamos a presentar una imagen.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 359
Visual Basic - Guía del Estudiante Cap. 13
Acceso a Bases de Datos remotas mediante el motor Jet
ODBCDirect
Acceso a Bases de Datos remotas mediante objetos RDO
Acceso a Bases de Datos remotas mediante el motor Jet
ODBCDirect
Hasta ahora todos los accesos realizados a una base de datos los hemos realizado directamente a través del Motor de
bases de Datos Microsoft JET. Este motor de bases de datos abre, lee y graba el fichero .MDB (o el dBase,
FoxPro, Paradox, etc.) de la misma forma que un editor de textos puede abrir, leer o escribir un fichero creado por
el mismo o por otros editores conocidos.
Las bases de datos (las buenas) tienen unas herramientas comunes para manejarlas. Estas herramientas son, por una
parte el lenguaje SQL que puede dar instrucciones para leer o escribir una base abierta, mediante un lenguaje común
para todas las bases, y por otra, la herramienta que abre esa base de datos y nos hace verla, desde el exterior, bajo
una forma única para todas las bases: el ODBC.
El ODBC es una herramienta que nos permite ver a todas las bases de una forma única. No es un lenguaje común a
todas las Bases de datos. Ese es el SQL. Es la interface que adapta a una base de datos para que nos podamos
entender con ella en SQL. Por lo tanto es fácil pensar que esa interface deberá fabricarla el mismo fabricante que ha
realizado la base de datos. El lenguaje SQL es conocido por todo el mundo, pero la forma interna de trabajar una
base de datos solamente la conoce su fabricante. Por eso, el Driver ODBC que es el que nos permite adaptar las
particularidades de esa base de datos al lenguaje común, deberá suministrarlo el fabricante de la base.
Microsoft desarrolló varios drivers para otras tantas bases de datos y hojas de cálculo. Entre ellas para Access y
Excel, dBase y FoxPro. También lo desarrolló para bases de datos tan populares como Oracle. Ese driver hay que
instalarlo en el ordenador, aunque Windows instala algunos por defecto.
Veamos ahora otro elemento fundamental para el trabajo con ODBC: la conexión. La conexión ODBC es el
conjunto de datos que hay que aportarle a Windows para que pueda enlazar nuestra aplicación con la base de datos.
Estos datos son, al menos:
El nombre de la conexión, por el cual la podremos nombrar para referirnos a ella.
El driver que debe utilizar para entenderse con la base de datos
El nombre (y Path) de la base de datos que queremos manejar con esa conexión.
La conexión ODBC no la realiza Visual Basic. La realizará Windows. Veamos como podemos establecerla.
Vaya a Inicio | Configuración | Panel de Control | ODBC de 32 Bits . Haga doble click y le aparecerá un cuadro
como el de la figura 13-1. En este cuadro figuran todos los enlaces que están establecidos. Estos enlaces puede
establecerlos para un usuario (DSN de usuario), de sistema o de archivo. La elección de uno u otro dependerá de los
permisos de acceso que quiera establecer (y eso es, de momento, para nota). En cualquier caso, todas los enlaces
ODBC que establezca funcionarán del mismo modo, exceptuando que puede otorgar unas prerrogativas distintas de
uso, dependiendo de como lo haya abierto.
Observe uno que figura en la lista: Luki. En esa línea figura otro dato: Microsoft Access Driver.(*.mdb) Esto
significa que el enlace de nombre Luki está usando el driver ODBC de Access. Y significa también que si
queremos llamar a esa conexión deberemos llamarla por su nombre : Luki
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 360
Fig. 13-1 Creación de un enlace ODBC. Muestra las conexiones existentes (una vez creada la conexión Luki)
Sigamos con la creación del enlace ODBC. Para crear uno nuevo, haga click en el botón Agregar de la figura 13-1.
Le aparecerá un cuadro donde le pide el driver que quiere utilizar.
Fig. 13 – 2 Elección del driver ODBC
Haciendo click en Finalizar, le pedirá el nombre del nuevo enlace, un comentario, (no es necesario introducirlo), y
la base de datos con la que quiere enlazar
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 361
Fig. 13-3 Introducción del nombre del enlace, comentario (descripción) y base de datos asociada al
enlace ODBC
Veamos los datos que hemos introducido en nue stra conexión “Luki”
Nombre del Origen de datos. Luki
Descripción (Opcional) Conexión ODBC Cap. 21
Haciendo click en Base de Datos | Seleccionar nos muestra un cuadro de diálogo donde `podemos buscar la base de
datos. Se elige la base de datos deseada. Hacemos click en ACEPTAR y ya está creada la nueva conexión.
La base de datos del sistema deberá elegirla para poder introducir usuarios con distintas atribuciones de acceso a la
base de datos. Si no introduce esta base de datos de sistema, deberá trabajar sin restricción de acceso.
Una vez creada la conexión podemos utilizarla para conectar nuestra aplicación con la base de datos. El proceso
para ello consiste en algo parecido a lo que hacíamos trabajando con el motor Jet en el espacio de trabajo Microsoft
Jet, pero de distinta forma. En ese entorno se manejaba la base de datos creando un objeto Database, que
manipulaba el fichero de la base de datos directamente. En este caso, la base de datos se maneja mediante un objeto
Connection.
El trabajar sobre una conexión nos aporta mayor versatilidad a las aplicaciones. Piense por ejemplo un caso en el
que se emplea una base de datos Access. Si quisiésemos ampliar las prestaciones de la base de datos de esa
aplicación posiblemente pensaríamos en migrar la BD a Oracle o SQLServer. Si atacamos a la base de datos a
través de ODBC solamente deberíamos cambiar la conexión, tal como vimos más atrás. Nuestro programa seguiría
llamando a la misma conexión ODBC, pero esta conexión, ahora, abriría una base Oracle o SQLServer en vez de la
Access que abría originalmente. No necesitaríamos realizar ninguna modificación en nuestro programa.
Este razonamiento es válido para cualquier sistema de acceso a bases de datos a través de ODBC. (RDO ó ADO)
Sin embargo el ODBCDirect tiene una ventaja `para los que trabajamos normalmente con DAO: usa los mismos
nombres para casi todos los métodos y funciones, por lo que el cambio de código es mínimo. El cambio se limita
prácticamente a crear el objeto Connection en vez del objeto Database. Comencemos a ver esto con u ejemplo. Es
un ejemplo uy simple, en el que abrimos una base de datos Access llamada Alumnos.Mdb que tiene una tabla
llamada Personas. Creamos la conexión Luki tal como se describió mas atrás. La tabla personas tiene solamente
tres campos: ID_Alumno, Nombre y Apellidos. Creamos una interface gráfica sencilla
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 362
Fig. 13-4 Nuestra primera aplicación con ODBCDirect
Mediante esta sencilla aplicación queremos visualizar los datos existentes, añadir nuevos registros y borrar el
registro actual. Veamos el código con los comentarios oportunos.
General/Declaraciones
Option Explicit
Dim MiSesion As Workspace
Dim MiConexion As Connection
Dim RsODBC As Recordset
'Declaramos las variables tipo objeto
Private Sub BCrearConexion_Click()
'Se le dice al DBEngine que debe trabajar en el espacio de trabajo ODBCDirect
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
'Se crea el objeto conexión
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
´Se crea el objeto Recordset
Set RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync, dbPessimistic)
'Es necesario recorrer el recordset para conocer cuantos registros tiene (Es Dynaset)
RsODBC.MoveLast
RsODBC.MoveFirst
If RsODBC.AbsolutePosition <> -1 Then
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "La base de datos no tiene ningún registro"
End If
End Sub
Public Sub PresentaDatos()
TB_ID = "": TB_Nombre = "" : TB_Apellido = ""
TB_ID = RsODBC!ID_Alumno
TB_Nombre = RsODBC!Nombre
TB_Apellido = RsODBC!Apellidos
LNumReg = RsODBC.AbsolutePosition + 1
End Sub
Private Sub BEliminar_Click()
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 363
RsODBC.Delete
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveFirst
PresentaDatos
End If
End Sub
Private Sub BGuardarDatos_Click()
RsODBC.AddNew
RsODBC!ID_Alumno = TB_ID
RsODBC!Nombre = TB_Nombre
RsODBC!Apellidos = TB_Apellido
RsODBC.Update
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
End Sub
Private Sub BMas_Click()
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveNext
If RsODBC.AbsolutePosition <> -1 Then
PresentaDatos
Else
RsODBC.MoveLast
PresentaDatos
End If
End If
End Sub
Private Sub BMenos_Click()
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MovePrevious
If RsODBC.AbsolutePosition <> -1 Then
PresentaDatos
Else
RsODBC.MoveFirst
PresentaDatos
End If
End If
End Sub
Private Sub BMMas_Click()
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
PresentaDatos
End If
End Sub
Private Sub BMMenos_Click()
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveFirst
PresentaDatos
End If
End Sub
Private Sub BNuevoReg_Click()
Limpia
End Sub
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 364
Public Sub Limpia()
TB_ID = ""
TB_Nombre = ""
TB_Apellido = ""
End Sub
Observe que casi todo el código es igual que el que escribiríamos si hubiésemos utilizado el espacio de trabajo
Microsoft Jet. Solamente hemos utilizado código distinto el procedimiento BCrearConexion_Click. Vamos a
analizar las instrucciones de ese procedimiento que son distintas a las que estamos acostumbrados a manejar
DBEngine.DefaultType = dbUseODBC
Vea la propiedad DefaultType en el Capítulo 20. Tenga en cuenta que el ODBCDirect lo ejecuta el motor Jet (que
como recordará es el objeto DBEngiine). La propiedad DefaulType debemos igualarla a dbUseODBC para que
trabaje en el espacio de trabajo ODBCDirect. Si no le diésemos ningún valor a esa propiedad, tomaría el otro valor
posible (dbUseJet) que es su valor por defecto. Por eso, cuando utilizábamos los métodos CreateDataBase u
OpenDatabase no necesitábamos darle ningún valor a esa propiedad.
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
Vea mas abajo la información de OpenConnection para ver los parámetros que hay que pasarle a este método.
Set RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync, dbPessimistic)
Vea mas abajo una ampliación del método OpenRecordset
Método OpenConnection
Es un método del Workspace que solamente es aplicable cuando el DBEngine está trabajando en el espacio de
trabajo ODBCDirect. Abre un objeto Connection usando un origen de datos ODBC ya creado.
El objeto Connection sería el equivalente en DAO al objeto Database. Debemos declararlo antes de usarlo
Dim MiConexion as Connection
Si MiSesion es el Workspace que queremos usar, la sintaxis de OpenConnection es la siguiente:
Set MiConexion = MiSesion.OpenConnection (Nombre, Opciones, Sólolectura y Conectar)
En el ejemplo:
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
Veamos que son los parámetros Nombre, Opciones, Sólolectura y Conectar
es el nombre de la conexión (no se debe confundir con el nombre del objeto Connection que es
MiConexion, y que es el nombre por el que nos tendremos que referir a esa conexión en toda la aplicación. Nombre
no lo usará normalmente)
Nombre
El parámetros Nombre puede ser una cadena cualquiera, o el nombre del enlace ODBC establecido en Windows
(que en nuestro ejemplo sería Luki). Si opta por poner una cadena cualquiera (como hicimos en el ejemplo,
Conexión1) deberá poner el nombre del enlace ODBC en el parámetro Conectar. Si opta por poner el nombre del
enlace ODBC, Visual Basic interpreta que debe conectar a través de ese enlace y ya no necesita poner ningún valor
al parámetro Conectar.
Opciones Este parámetro es para definir que tipo de respuesta va a dar el administrador del controlador de ODBC
para solicitar al usuario información sobre la conexión (Nombre del origen de datos (DSN), nombre del usuario y
contraseña). Puede tomar uno de los siguientes valores:
El administrador del controlador de ODBC toma los datos de los parámetros
para saber cual es el enlace ODBC que debe usar. Si no proporciona suficiente
información, se producirá un error de tiempo de ejecución.
DbDriverNoPrompt
Nombre y Conectar
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 365
DbDriverPrompt El administrador del controlador
de ODBC muestra el cuadro de diálogo de ODBC, que
muestra todos los enlaces ODBC existentes. La conexión se hace con el DSN que selecciona el usuario en
ese cuadro de diálogo.
Fig. 13.5 Cuadro de diálogo de ODBC
Una vez seleccionada la conexión, aparecerá otro cuadro solicitando el nombre de inicio de sesión y la contraseña.
En resumen, con este parámetro DbDriverPrompt forzamos al programa a que utilice los recursos Windows para
seleccionar el enlace ODBC
DbDriverComplete (Este
DbDriverNoPrompt
es el valor predeterminado). Se comporta (aparentemente) como si se pone
DbDriverCompleteRequired Al igual que la anterior,
esta opción se comporta (aparentemente) como si se
pone DbDriverNoPrompt
(Opcional). True si la conexión se va a abrir con acceso de sólo lectura y False si la conexión se va a
abrir para acceso de lectura/escritura (predeterminado)
Sólolectura
Conectar (Opcional si se ha puesto el nombre del enlace en el parámetro Nombre). Este parámetro está formado
por varias partes. Una, obligatoria, que contiene la expresión " ODBC;" Otra parte obligatoria, si no ha puesto en el
parámetro Nombre el nombre del enlace ODBC es " DSN = NombredelaConexión; " Si desea especificar el usuario
propietario de esa conexión debe añadir " UID = usuario;" y como ese usuario tendrá una contraseña, deberá
añadirla también " PWD = contraseña; " También puede indicar cuanto tiempo debe esperar el administrador del
controlador de ODBC para generar un error en caso de que no conteste el sistema a la petición ODBC. Este tiempo
deberá introducirlo con la expresión " LOGINTIMEOUT = segundos;" Observe que cada una de estas partes
lleva un identificador y un dato, ambos separados por un signo =, y siempre terminan con el signo punto y coma (;)
Si omite los parámetros UID y/o el PWD, estos datos se obtendrán de las propiedades UserName y Password del
objeto Workspace.
Método OpenRecordset
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 366
Este método ya se estudió en el capítulo anterior, pero se van a ver ciertas peculiaridades que tiene cuando se abre
un recordset en el espacio de trabajo ODBCDirect
En este caso es el objeto Connection quien abre el recordset.:
Set MiRecordset =
= MiConexion.OpenRecordset (Origen, Tipo, Opciones, Bloquearmodificaciones)
Origen Puede ser un nombre de tabla, de una consulta o una instrucción SQL que devuelva registros.
Tipo Indica el tipo de recordset que queremos crear. El espacio de trabajo ODBCDirect no permite recordsets
tipo
Tabla. Los tipos que se pueden elegir son:
DbOpenDynamic
Abre un objeto Recordset de tipo Dynamic, que es parecido a un cursor dinámico
ODBC
Abre un objeto Recordset de tipo Dynaset, similar al estudiado en el capítulo 20 para el
espacio de trabajo Microsoft Jet
DbOpenSnapshot Abre un objeto Recordset de tipo Snapshot,
dbOpenForwardOnly Abre un objeto Recordset de tipo Forward-only, que tiene la particularidad de que
no permite movernos en el recordset de adelante hacia atrás. Este es el tipo que creará por defecto si no se
especifica nada en el parámetro Tipo.
DbOpenDynaset
Opciones Debe indicar uno de estos dos valores (si no pone alguno de ellos da error):
DbRunAsync
Ejecuta una consulta asíncrona, que es la forma normal de trabajar del ODBC. Esto
permite a su aplicación seguir procesando otras instrucciones mientras se ejecuta la consulta en segundo
plano (Vea mas adelante la propiedad StillExecuting
dbExecDirect
Ejecuta una consulta saltando el método SQLPrepare y llamando directamente al método
SQLExecDirect. Utilice esta opción sólo cuando no se abra un objeto Recordset basándose en una
consulta de parámetros. Para obtener más información, consulte la "Referencia del programador de
Microsoft ODBC 3.0."
Bloquearmodificaciones Este parámetro es fundamental si quiere escribir en la base de datos, pues si lo omite le
pone por defecto que la base es de solo lectura. Mediante este parámetro va a determinar el tipo de bloqueo de la
base de datos para entornos de trabajo multiusuario. Puede poner uno de estos valores:
DbReadOnly (Predeterminado) No permite que los usuarios hagan cambios en los registros del Recordset
DbPessimistic Permite cambiar datos y añadir registros en el recordset, utilizando el criterio de bloqueo
pesimista. Esto significa que bloquea la página donde se encuentra el registros desde que se ejecuta el
método Edit hasta que se ejecuta el Update. Es el criterio mas seguro de bloqueo de datos, pero debe tener
en cuenta que tiene la base bloqueada desde el Edit hasta el Update. Si hace bloqueo pesimista, procure
que las instrucciones entre uno y otro no tengan ningún tiempo de espera, por ejemplo a que el usuario
introduzca un dato. (El tamaño de una página depende de la base de datos que esté usando. En Access es
de 2048 Bytes. Esto significa que solamente tendrá bloqueada una parte relativamente pequeña de la base
de datos, pudiendo modificar otros registros que estén fuera de ese segmento de 2 Kbytes. Lógicamente
este bloqueo solamente tendrá efecto cuando esté trabajando en un entorno multiusuario.
Permite cambiar datos y añadir registros en el recordset, utilizando el criterio de bloqueo
optimista. El bloqueo optimista significa que solamente estará bloqueada la página que contiene el registro
mientras se ejecuta el método Update. Esto puede ocasionarle que, si están dos usuario trabajando sobre el
mismo registro, se introduzca un dato erróneo. Parece así en principio que no se debe usar, pero todo va a
depender de la aplicación, de sus datos, y de la probabilidad de que ocurra esa colisión. La ventaja que
tiene es que tiene menos tiempo bloqueada la página de la base de datos.
DbOptimistic
Utiliza la concurrencia optimista basándose en valores de fila. Funciona de forma
similar al dbOptimistic.
dbOptimisticValue
dbOptimisticBatch
LSB
Activa la actualización optimista por lotes.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 367
Actualización por lotes. Modelo de cursor para clientes que trabajan con cursores, pero no mantienen bloqueos en
el servidor o ejecutan actualizaciones por fila. En su lugar, el cliente actualiza muchas filas que están almacenadas
en el búfer local y después ejecuta una actualización por lotes. Este modelo de cursor también permite al cliente
cancelar la conexión con el servidor y volverla a establecerla con el mismo servidor o con otro diferente.
Para utilizar la actualización por lotes en DAO 3.5, debe utilizar un espacio de trabajo de ODBCDirect, la
propiedad DefaultCursorDriver se debe establecer a dbUseClientBatchCursor en el momento de abrir la conexión y
se debe abrir el Recordset con el argumento de tipo de bloqueo del método OpenRecordset establecido a
dbOptimisticBatch.
Propiedad StillExecuting
Cuando abrimos una conexión mediante OpenConnection, un QueryDef o creamos un recordset y le ponemos en
Opciones DbRunAsync, la operación se realiza de forma asíncrona, por lo tanto no sabemos cuando tendremos
disponible el objeto a crear o los datos de la consulta. Para poder controlar si la operación se está realizando todavía
leeremos la propiedad StillExecuting, que devolverá True si todavía se está ejecutando, y False si ha terminado.
Basta con hacer un bucle del tipo
Do While MiConexion.StillExecuting = True
DoEvents
Loop
Mientras la propiedad StillExecuting sea True, no se puede tener acceso a ningún objeto devuelto. Por ejemplo, no
pretenda crear un recordset con MiConexion Mientras que StillExecuting sea True, pues MiConexión no existe aún.
Esta propiedad puede ser muy útil cuando tiene consultas encadenadas y necesita esperar a que termine una para
comenzar con la siguiente.
StillExecuting se utiliza con los objetos y para
las operaciones siguientes:
Objeto Connection, para controlar que aún se está ejecutando uno de los métodos Execute u OpenConnection
Objeto QueryDef, para comprobar su método Execute
Recordset, donde podrá comprobar si aún se están realizando los métodos Move, NextRecordset
OpenRecordset
u
Para ver el valor que tiene la propiedad StillExecuting deberá poner el nombre del objeto que quiere comprobar
(Connection, QueryDef o Recordset) después de haber iniciado uno de los métodos citados anteriormente. Por
ejemplo, para esperar a que se haya creado el objeto Connection MiConexion, haremos un bucle de la siguiente
forma
Set MiConexion = MiSesion.OpenConnection("Luki1", dbDriverNoPrompt)
Do While MiConexion.StillExecuting = True
Aquí las instrucciones que quiera
Loop
Método Cancel
Cancela la ejecución de un método asícrono de llamada. Sólo funciona espacios de trabajo ODBCDirect.
Sintaxis
objeto.Cancel
La sintaxis del método Cancel consta de las siguientes partes:
Objeto puede ser:
Connection para cancelar el método Execute u OpenConnection
QueryDef, para cancelar el método Execute
Recordset para cancelar el método OpenRecordset
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 368
El método Cancel solamente sirve para cancelar la ejecución de una llamada asíncrona de los métodos Execute,
OpenConnection u OpenRecordset que se hayan invocado con la opción dbRunAsync. Cancel devolverá un error
de tiempo de ejecución si en el método que está intentando finalizar no se utilizó dbRunAsync.
Objetos Database y QueryDef en el espacio de trabajo ODBCDirect
Repasemos la estructura jerárquica de los objetos de acceso a datos en el espacio de trabajo ODBCDirect. Podemos
ver que siguen existiendo, aparte de los ya estudiados en este capítulo, dos objetos que ya nos son conocidos: el
QueryDef y el Database. Veamos cada uno de ellos.
Fig. 13-6 Estructura jerárquica de los objetos de acceso a datos en el espacio ODBCDirect
Objetos QueryDef en el espacio de trabajo ODBCDirect
Habíamos visto en el capítulo 20 que un QueryDef era una consulta cuando todavía no estaba guardada en el disco.
Es decir, un QueryDef es una consulta en memoria RAM. Ese QueryDef se transforma en una consulta de la base de
datos una vez que se cierra el objeto Database.
En el espacio de trabajo ODBCDirect no se pueden crear bases de datos. Se pueden crear objetos QueryDef, que en
este caso serán objetos efímeros, que solamente existirán en la memoria RAM, desapareciendo en el momento que
cerremos ese QueryDef o cerremos la aplicación.
Puede crear un QueryDef para crear posteriormente a partir de él un Recordset con el que puede presentar o escribir
el contenido de los registros. En el siguiente ejemplo hemos abierto la conexión, y como paso previo a la creación
del recordset hemos creado un QueryDef con todos aquellos registros cuyo campo Apellidos sea igual a Alvarez
Pérez. Una vez creado ese QueryDef, hemos creado un recordset a partir de él. No tiene mucho sentido hacer esto
ya que podríamos crear directamente el recordset imponiendo esa condición en el campo Apellidos. Se expone aquí
con fines didácticos, no prácticos.
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 369
Set MiConsulta = MiConexion.CreateQueryDef ("Pepito", "Select * From Personal Where Apellidos = "Alvarez
Pérez")
Set RsODBC = MiConsulta.OpenRecordset(dbOpenDynaset, dbRunAsync, dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "El recordset no tienen ningún registro"
End If
Puede apreciar en la fig. 13-6 otro objeto que está jerárquicamente debajo del QueryDef. El Objeto Parameter. Este
objeto sirve para cambiar los parámetros que se le pasan al QueryDef para crearlo. Le remito a la ayuda de VB para
mayor explicación de este objeto.
El objeto Database en el espacio de trabajo ODBCDirect
En el espacio ODBCDirect puede también abrir un objeto Database en vez de un objeto Connection. La diferencia a
la hora de crear un objeto Database (abrir una base d e datos) entre el espacio de trabajo Microsoft Jet y
ODBCDirect es que en el primero abrimos directamente el fichero de la base de datos, y en el segundo, abrimos el
fichero que indique el enlace ODBC. Deberemos suministrarle información del enlace ODBC que debe usar. La
sintaxis sigue siendo igual que en el espacio de trabajo Microsoft Jet:
Set MiBaseDatos = MiSesion. OpenDatabase (Nombre, Opciones, Sólolectura, Conexión)
Para indicarle el enlace ODBC que debe usar puede hacerlo de las dos formas que venimos viendo para los
parámetros Nombre y Conexión. Si indica el nombre del enlace en el parámetro Nombre lo aceptará y será
necesario poner el parámetro Conexión. Si `pone un nombre cualquiera en el parámetro Nombre deberá indicar el
nombre del enlace en el parámetro Conexión.
Esta posibilidad de crear un objeto Database nos aproxima aún más al código empleado en el espacio de trabajo
Microsoft Jet. Por lo tanto puede ser muy útil usar este objeto en aquellos casos en los que ya se había escrito el
código, y pasamos posteriormente a usar ODBC.
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
'En la siguiente línea le pasamos el nombre del enlace ODBC en el parámetro Nombre
Set MiBaseDatos = MiSesion.OpenDatabase("Luki", dbDriverNoPrompt)
'Pero podríamos haberselo pasado en el parámetro Conexión y ponerle como parámetro 'nombre cualquier cadena
de caracteres
Set MiBaseDatos =
MiSesion.OpenDatabase("BaseDatos1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
'Ahora creamos el recordset, como en los otros casos
Set RsODBC = MiBaseDatos.OpenRecordset("Personal", dbOpenDynaset, dbRunAsync, dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "La base de datos no tiene ningún registro"
End If
Mediante los ejemplos expuestos en este capítulo espero que el alumno comprenda como trabaja DAO a través de
ODBC, mediante el ODBCDirect.
No olvide que sigue tratándose de DAO, y que por lo tanto deberá poner la misma referencia (En Proyecto |
referencia) que en el caso del DAO trabajando en el espacio de trabajo Microsoft Jet. En la siguiente parte de este
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 370
capítulo se estudiarán los objetos RDO, objetos que trabajan exclusivamente a través de ODBC. Con las ideas
captadas hasta aquí verá que es sencillo abordar estos nuevos objetos.
Visual Basic - Guía del Estudiante Cap. 13 Continuación
Acceso a Bases de Datos remotas mediante objetos RDO
En la primera parte de esta capítulo hemos visto como acceder a bases de datos a través de ODBC usando el motor
JET. El acceso se realizaba mediante ODBCDirect, modo de operación del motor JET, y podíamos usar la misma
sintaxis y objetos que habíamos visto con los objetos DAO. También vimos como crear un enlace ODBC, enlace
que vamos a utilizar en este capítulo. Como ya se explicó en el capítulo anterior, damos por supuesto que el alumno
conoce como crear ese enlace.
Los objetos RDO se crearon para cubrir el hueco que tenía VB para conectar con bases de datos distintas a las que
trabaja el motor JET. (Access, dBase, FoxPro, etc.). Esta forma de trabajar nos permite enlazar con bases de datos
tipo Oracle o SQLServer, pero también nos permite trabajar con Access, dBase o FoxPro, que también tienen su
propio driver ODBC.
Lo primero que nos encontramos al trabajar con RDO es que es más lento que DAO. Si creamos dos aplicaciones
que trabajen sobre una base Access, una directamente a través de DAO y otra a través de RDO, observaremos que la
primera accede a la BD con una rapidez mayor que la segunda. Normal, no es lo mismo abrir un fichero y leerlo
(que es lo que hace DAO) que pasar unos parámetros a otro programa (Driver ODBC de Access) para que este abra
el fichero, obtenga los datos y nos los pase. Lo mismo podemos decir cuando tenemos que contar registros,
movernos de un registro a otro, editar o añadir nuevos registros. Esa falta de rapidez es el coste de la tecnología de
bases abiertas.
Lo segundo que nos va a llamar la atención es el nombre de los objetos de acceso a datos. Una vez que nos
habíamos familiarizado con palabras como Recordset, DataBase o Dynaset, nos las cambian por rdoResultset,
rdoConnection o Keyset respectivamente. Y lo peor no es solamente tener que aprender sus nombres, sino que en
una aplicación hecha en DAO que sea necesaria cambiarla a RDO, nos vemos obligados a retocar la mayor parte de
las líneas de código (Cosa que no ocurría con ODBCDirect)
Y lo tercero, RDO no tiene la posibilidad de crear bases de datos como hacíamos en DAO. Normal, ya que en este
caso no trabajamos directamente sobre la BD sino sobre la conexión ODBC que Windows realizó a una base de
datos. Podemos añadir mas desventajas de RDO: no puede contar los registros que tiene, tiene un comportamiento
muy irregular con la propiedad AbsolutePosition, y varios detalles que procuraremos explicar en este capítulo para
ahorrar al alumno el trabajo de tener que experimentarlos por sí mismo. (Aunque, consejo de viejo profesor, es la
forma más segura de aprenderlos).
Tras estos inconvenientes parece lógico encontrar alguna contrapartida positiva. Por ejemplo poder conectar con
cualquier tipo de base de datos, pudiendo incluso realizar la aplicación atacando una base Access, para luego
trabajar con una base SQLServer u Oracle sin variar ni una línea de código. Esa debería ser la gran ventaja de RDO.
Pero lamentablemente, y en contra de toda teoría de ODBC, no es cierto. Si preparamos una aplicación en RDO
trabajando con una base Access y pretendemos cambiar la base por otra SQLServer, observaremos que lo que
funciona perfectamente en la primera no funciona en la segunda. (Y esto no es teoría. Es simplemente experiencia
del autor). ¡Y Access y SQLServer son del mismo fabricante!. La razón está en que los drivers de una base y otra no
trabajan exactamente igual. Tampoco son iguales las protecciones y los permisos de acceso. Consejo de viejo
profesor: Si va a trabajar con una determinada base de datos a través de RDO comience el proyecto usando esa base
de datos. Y puestos a dar consejos, si piensa usar SQLServer u Oracle y si la aplicación va a escribir datos en la
base no use RDO. Si solamente los va a leer no tendrá problemas. Y si tiene problemas nadie se los va a resolver,
argumentando que deje RDO y use ADO. De hecho RDO ya se ha quedado obsoleto al nacer ADO. Pero eso será
objeto de otro capítulo de esta Guía del Estudiante y hoy nos toca aprender RDO. Comencemos.
RDO y DAO. Comparación de sus objetos. El control RemoteData
Al igual que DAO, RDO tiene objetos de acceso a datos, que deberemos declarar y crear. Mediante estos objetos
podemos leer y escribir datos en una BD mediante código. También, al igual que en DAO existía el Control Data ,
con el que podíamos acceder a la base de datos sin escribir ni una línea de código, en RDO existe un control similar:
el Control RemoteData. El funcionamiento es similar, pero las propiedades son distintas y tienen distintos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 371
nombres. Mediante el control RemoteData podemos enlazar una base de datos a los típicos controles enlazados a
datos (Label, TextBox, DBGrid), pero en este caso se enlazan a través de una conexión ODBC, por lo que es fácil
pensar que las propiedades de este control y los valores que deben tomar son distintas a los del control Data. Como
es mucho más sencillo (sencillo no quiere decir mejor) usar el control RemoteData que trabajarse con código los
objetos de acceso a datos, vamos a comenzar estudiando este control.
Pero antes vamos adelantar la equivalencia entre los objetos DAO y los objetos RDO. La lista siguiente está copiada
literalmente de la información de Microsoft MSDN Library Visual Studio, información que merece la pena
instalarla en su ordenador pese a lo que ocupa.
Objetos de datos remotos y los objetos de DAO/Jet equivalentes
Objeto de RDO
Objeto de DAO/Jet equivalente
rdoEngine
rdoError
rdoEnvironment
rdoConnection
rdoTable
No está implementado
rdoResultset
No implementado
Tipo Keyset
Tipo static
Tipo dynamic
Tipo forward-only
No implementado (*)
RdoColumn
rdoQuery
rdoParameter
No implementado (**)
No implementado (*)
Control RemoteData
DBEngine
Error
Workspace
Database
TableDef
Index
Recordset
Tipo Table
Tipo Dynaset
Tipo Snapshot
(ninguno)
Tipo forward-only
User
Field
QueryDef
Parameter
Relation
Group
Control Data
(*) En RDO, los usuarios y grupos de usuarios son precisamente los que lleve implícitos la conexión ODBC.
(**) Al no trabajar directamente sobre la base de datos, no se pueden crear relaciones en ella.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 372
El control RemoteData
Este control nos permite crear una aplicación de acceso a datos completa sin utilizar código. Eso sí, será necesario
tener una conexión ODBC hecha, ya que el control RemoteData no abre un fichero de BD sino una conexión ya
establecida.
No está normalmente en la caja de herramientas, por lo que habrá que añadirlo en Proyecto | Componentes
introduciendo el Microsoft Remote Data Control 6.0 El control Remote Data tiene un aspecto similar al control
Data, tanto en la caja de herramientas como en el formulario:
El control RemoteData toma por defecto el nombre MSRDCx.
Algunas Propiedades del Control RemoteData
DatasourceName
Devuelve o establece el nombre del origen de datos (DSN). El DSN No es más que el nombre de la conexión
ODBC.
Esta propiedad se puede dejar en blanco si la propiedad Connect del control identifica un nombre de origen de
datos (DSN) registrado en el Registro de Windows.
Sintaxis NombredelControlRDO. DatasourceName = MiConexión
Puede cambiarse en tiempo de ejecución. En este caso, inmediatamente debe utilizar el método Refresh para abrir la
nueva conexión con la base de datos.
Puede leer el valor de esta propiedad. Le devolverá precisamente el DNS que está utilizando. Esta propiedad sólo le
devolverá un valor si ha introducido previamente algún valor en la propiedad DatasourceName. No le devolverá
valor alguno si ha introducido la conexión a través de la propiedad Connect.
Propiedad Connect
Esta propiedad cumple la misma función que la anterior, pero por otro camino. Mediante la propiedad Connect le
introducimos al control RemoteData la información necesaria para abrir la conexión, incluyendo en esta
información, no solamente el nombre de la conexión, como hacíamos con la propiedad DatasourceName, sino
ampliarla con otros datos de la conexión, tal como el nombre del usuario, su contraseña, nombre del controlador
ODBC a usar, el nombre de la base de datos, el servidor donde se ubica esta base de datos, nombre de la estación de
trabajo desde la que vamos a trabajar e incluso el nombre de la aplicación en la que vamos a usar los datos de esa
base. Esta propiedad es mucho más completa que la anterior, pero un poco más complicada de usar.
Para introducir los datos de la propiedad Connect deberá usar una palabra para definir el dato, seguido del signo = y
del dato a introducir. Como final del dato debe introducir necesariamente el signo punto y coma ;
DSN Origen de datos ODBC registrado.
DSN=MiConexiónODBC;
UID
Nombre de un usuario reconocido
UID=Luis;
PWD Contraseña asociada al usuario
PWD=MiContraseña;
DRIVER
Descripción del controlador
DRIVER=SQL Server;
DATABASE
Base de datos predeterminada
para usarla una vez conectado
DATABASE=MiBase;
SERVER
Nombre del servidor donde se
aloja la base de datos
SERVER=MiServidor;
WSID
Nombre de la estación de trabajo
(Nombre del PC que se va a
comunicar con el servidor
WSID=NombredemiPC;
APP
Nombre de la Aplicación que va a
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 373
Usar la Base de Datos
APP=MiAplicación
- Si conoce SQLServer, DATABASE es el nombre de la base de datos que quiere utilizar una vez realizada
la conexión. Para los que no conocen SQLServer, dentro de un fichero de esta base de datos pueden existir varias
bases de datos. Y cada una de ellas puede tener varias tablas. Es decir, la configuración de esta BD no es tan
simple como la de Access. Cada una de estas bases de datos tiene un propietario y varios usuarios. Cada usuario
tiene habilitadas unas funciones (p.e. un usuario puede leer y escribir y otro solamente leer) Este parámetro le
indica cual de esas bases de datos que contiene el fichero de SQLServer (para hablar con mas propiedad, el
sistema de ficheros de SQLServer)
NOTA
SQLServer mostrando su carpeta de Bases de Datos (BDGepa, master, model, …)
Observe que tras cada parámetro existe un separador ; No es necesario introducir todos los datos. Dependerá del
driver, de cómo haya creado la base de datos, los atributos que le dio a cada uno de los usuarios. Y como no,
dependerá del tipo de base de datos que esté usando (SQLServer, Oracle, etc.). Recuerde lo mencionado más atrás.
No se fíe nunca de que su aplicación trabaja perfectamente sobre una base de datos. Lo más probable es que si
cambia de BD ya no le trabajará tan perfectamente.
Veamos un ejemplo de cómo introducir esta propiedad:
Dim MiVariable As String
MiVariable = "DSN=MiConexionODBC;UID=Luis;PWD=MiContraseña;DATABASE=BaseGE;"
RemoteData1.Connect = MiVariable
El hecho de que podamos abrir una base de datos mediante DatasourceName o Connect tiene su explicación. Si
tenemos creada una conexión ODBC con todos los datos necesarios para que pueda abrir una base de datos, es
mucho más simple usar la propiedad DatasourceName y el Control RemoteData le abrirá perfectamente la BD.
Pero cuando usamos una BD a través de Red de Area Local, lo normal es que esa base esté compartida por varios
usuarios, que cada uno tendrá un nombre y un Password, que puede estar habilitado para trabajar desde un
puesto o desde varios puestos, e incluso puede estar habilitado para trabajar sobre una BD utilizando una
determinada aplicación, y no estarlo para utilizar esa misma BD con una aplicación distinta. Por eso este control
nos brinda las dos posibilidades, una sencilla, DatasourceName, para trabajar con los datos ya introducidos en la
conexión ODBC, y la otra, para variar los datos de esa conexión ODBC ya existente y lograr con ello todas las
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 374
ventajas que nos ofrece ODBC respecto a restricciones de usuarios, contraseñas, etc. (la conexión ODBC en este
caso es muy normal que tenga solamente el nombre, y que no apunte a ninguna base de datos concreta). Puede
incluso utilizar ambas propiedades. Es muy típico por ejemplo, que la conexión apunte a una determinada base de
datos, (el nombre de la conexión se lo pasamos en la propiedad DatasourceName) y que en la propiedad Connect
le pasamos el nombre del usuario y la contraseña.
Puede utilizar el control, RemoteData incluso sin tener una conexión preestablecida. Pero deberá establecer
mediante el programa, utilizando los métodos OpenConnection o EstablishConnection. Se sale del contenido
deseado para este curso comentar estos métodos, pero el alumno aventajado puede intentar obtener información
en la escasa bibliografía existente. No le recomiendo que se complique la vida rizando el rizo, pudiendo establecer
previamente la conexión ODBC.
Propiedad SQL
Mediante las dos propiedades estudiadas, DatasourceName y Connect hacemos que el control RemoteData sepa la
conexión sobre la que va a trabajar - y por lo tanto la base de datos que utilizará. Ahora nos falta indicarle los datos
que deseamos leer o escribir. Nos falta lo que sería en DAO, darle los datos para crear el Recordset (Por ejemplo el
nombre de una tabla o una sentencia SQL, tal como hacíamos en la propiedad RecordSource del control Data).
Para el control RemoteData esta información se le introduce en la propiedad SQL
La propiedad SQL establece o devuelve una instrucción SQL válida para crear un conjunto de registros a partir del
origen de datos establecido en las propiedades DatasourceName o Connect. Esta instrucción SQL debe comenzar
necesariamente por SELECT, En tiempo de ejecución, podemos asignar a esta propiedad el nombre de una
Consulta ya almacenada en la BD, pero en este caso, debemos anteponer la palabra EXECUTE. También podemos
introducir en esta propiedad un rdoQuery, un rdoResultset o un rdoTable. Eso lo veremos más adelante.
Para establecer esta propiedad en tiempo de diseño, basta con escribir la instrucción SQL en la ventana de
propiedades. Una instrucción típica sería
SELECT * From Alumnos
SELECT * From Alumnos Where Apellido1= 'Suárez'
En tiempo de ejecución podemos introducir una de estas instrucciones en la propiedad SQL
MSRDC1.SQL = "SELECT * From Alumnos Where Apellido1= 'Suárez'"
Si la BD tiene una consulta (la típica consulta de Access) llamada C_Suarez, donde hemos seleccionado todos los
registros cuyo campo Apellido1 sea Suárez, podemos poner:
MSRDC1.SQL = EXECUTE C_Suarez
(No intente hacer esto mismo con el nombre de una tabla. Solamente sirve para consultas)
Con los registros seleccionados por la propiedad SQL, formamos lo que en DAO era un recordset, pero en este caso
adopta otro nombre: rdoResultset. En RDO se ha buscado otra terminología, posiblemente para diferenciarlo
claramente de DAO. Por ejemplo, en vez de registros es habitual hablar de Filas, y en vez de campos, hablamos de
Columnas.
Si pudiésemos crear un rdoResultset mediante algún procedimiento, (y seguro que podremos hacerlo), podemos
introducir directamente ese rdoResultset como rdoResultset del control RemoteData, al igual que lo hacíamos con
el Recordset del Control Data en DAO:
Set MSRDC1.Resultset = rdoResultsetYaCreado
Propiedad Connection
Veamos previamente que es un objeto rdoConnection. Un Objeto rdoConnection es un objeto de acceso a datos
remotos. Es el equivalente al objeto Database en DAO (Vea cuadro página 2) El control RemoteData tiene un
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 375
objeto rdoConnection subyacente y podemos "verlo" mediante esta propiedad. El poner verlo entre comillas no
significa otra cosa que, al igual que ocurría con el objeto Database, el objeto rdoConnection es un objeto de acceso
a datos del que podemos ver sus propiedades y ejecutar sus métodos. Por ejemplo, si queremos ver la cadena de
conexión completa podemos analizar la propiedad Connect del Objeto Connection:
Label1 = MSRDC1.Connection.Connect
Si deseamos saber si el control RemoteData sigue conectado para realizar una determinada operación:
If MSRDC1.Connection.StillConnecting Then ….
Podemos ejecutar uno de sus métodos. Por ejemplo, cerrar la conexión
MSRDC1.Connection.Close
Propiedades EOFAction y BOFAction
Establecen el comportamiento del RemoteData cuando llega a la fila anterior a la primera o a la fila posterior a la
última. (Y no es un juego de palabras) Puede establecerse en tiempo de diseño, mediante la caja de propiedades, o
en tiempo de ejecución mediante la siguiente sintaxis:
MSRDC1.BOFAction = valor
MSRDC1.EOFAction = valor
Los valores (o constantes) que puede tomar son los siguientes:
Para la propiedad BOFAction
Valor
Constante
Efecto
0
1
rdMoveFirst
rdBOF
Se mueve a la primera fila
Se mantiene en la fila anterior a la primera. Se genera el evento
Validate y a continuación el evento Reposition, y se desactiva el botón de desplazar
hacia abajo
Para la propiedad EOFAction
Valor
0
1
Constante
2
rdAddNew
rdMoveLast
rdEOF
Efecto
Se mueve a la última fila
Se queda en la fila posterior a la última. Se genera el evento Validate
y a continuación el evento Reposition. Se desactiva el botón de
desplazar hacia arriba.
Crea una nueva fila.
La propiedad EOFAction sólo tiene efecto cuando se manipula el cambio de filas mediante el ratón, sobre los
botones del control RemoteData. No tiene efecto si se llega a la fila posterior a la última mediante código. (Por
ejemplo, mediante la instrucción MSRDC1.resultset.MoveNext)
NO es recomendable establecer la propiedad BOFAction a 1 (rdBOF) ni la propiedad EOFAction a 1 ( rdEOF),
ya que puede entrar en una situación de la que es imposible salir. Si ve aparecer un aviso de error parecido a Estado
del conjunto de datos no válido para Update le está indicando que se ha metido en un proceso del que no puede
salir, debido a que se encuentra en el EOF ó BOF intentando introducir un nuevo dato, y no puede.
Propiedad CursorDriver
Devuelve o establece un valor que especifica el tipo de cursor que se va a crear. Veamos primero qué es un cursor.
Según la definición de Microsoft:
Conjunto lógico de filas administrado por el origen de datos o por el administrador de controladores ODBC. Los
cursores reciben dicho nombre porque indican la posición actual dentro del conjunto de resultados, igual que el
cursor de la pantalla indica la posición actual. (#G!*¡&@%)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 376
Vamos a no complicarnos la vida para intentar comprenderlo. El mecanismo de ODBC espera una base de datos
albergada en un servidor, a la que le vamos a manipular sus registros desde un puesto conectado al servidor donde
se encuentra la base de datos a través de una red de área local. Cuando creamos un recordset, el conjunto de
registros que forma ese recordset deberá estar en la memoria RAM de algún equipo. ¿Del servidor? ¿Del cliente?
En cualquiera de ellos que esté deberá estar en la memoria RAM, ocupando cierto espacio. A esa memoria ocupada
por el recordset, y a la forma en la que están guardados los datos dentro de ella es a lo que llamamos Cursor. Este
concepto de cursores es nuevo (No existía en DAO) debido a que RDO se utiliza fundamentalmente en sistemas
basados en un servidor, donde se alberga la base de datos, y una serie de puestos de operación, unidos al servidor a
través de una red. El tráfico de datos a través de la red es algo que se debe optimizar. Y en algunos casos puede ser
beneficioso llevarse todas las filas de un rdoResultset al puesto, operar con ellas e introducirlas de nuevo, si es
necesario, en la base de datos, una vez procesadas, o puede ser beneficioso mantener ese conjunto de filas en la
memoria RAM del servidor para tener disponibles allí los datos y acceder a ellos de forma rápida a través de la red.
En un caso lograremos o rapidez y en otro poco tráfico, pero en ambos casos gastaremos recursos. Podemos no
crear un cursor, no usaremos memoria pero, o empleamos mas tiempo, o introducimos más tráfico en la red.
El crear un cursor de lado cliente o de lado servidor puede hacer que su código funciones o no
funcione. Los cursores lado cliente suelen ser de lectura / escritura, que permiten avanzar hacia a
delante y hacia atrás. Los cursores lado servidor suelen ser solamente de lectura y de avance
solamente hacia delante. Hemos empleado una palabra no muy exacta: suelen ser. Y es que eso
dependerá de la base de datos (Oracle no se comporta como SQLServer, y ninguna de ellas se
comporta como Access) y depende también del controlador ODBC que utilice (Hay controladores
de varias marcas para la misma base de datos) Es muy frecuente realizar un código que funciona
perfectamente con un controlador ODBC, y cuando se cambia de controlador – o de versión – ya
no funciona. Le recomiendo mucho cuidado.
El control RemoteData permite elegir el crear un cursor en el servidor, en el puesto, o crearlo solamente si es
necesario. Para ello usamos la propiedad CursorDriver. Puede tomar los siguientes valores:
Constante
Valor
Descripción
El controlador ODBC elegirá el tipo de cursores adecuado. Se usarán
cursores del servidor si hay alguno disponible.
1
RemoteData usará la biblioteca de cursores de ODBC .
rdUseOdbc
2
Se usarán cursores del lado del servidor.
rdUseServer
3
RDO usará la biblioteca de cursores por lotes de tipo optimista.
rdUseClientBatch
Le recomiendo que repase el tema de cursores de la base de datos concreta que esté usando, y espero que la
bibliografía que le brinda el fabricante sea suficiente. No suelen ser muy explícitos con los manuales aportados, o al
menos tienen la habilidad de explicarlo de una forma tan sutil que es a veces inescrutable. Casi siempre esas dudas
se resuelven en el curso que cada marca tienen para su base de datos, que es estrictamente de pago.
rdUseIfNeeded
0
Métodos del control RemoteData
Método UpdateRow
Es equivalente al método UpdateRecord del Control Data. Guarda los valores actuales de los controles enlazados en
la base de datos. El método UpdateRow tiene el mismo efecto que ejecutar el método Edit, modificar una columna
y después ejecutar el método Update, excepto que no ocurre ningún evento.
Nota Cuando usa una biblioteca de cursores ClientBatch, todas las actualizaciones a las tablas base se retrasan hasta
que use el método BatchUpdate . En este caso, el método UpdateRow actualiza el rdoResultset local, pero no
actualiza las tablas base. Estos cambios pueden perderse si la aplicación termina antes de que se haya completado el
método BatchUpdate.
Método BatchUpdate (Método del rdoResultset)
Este método no es del control RemoteData, sino de su rdoResultset asociado.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 377
De igual forma que un control data tenía asociado un recordset, un RemoteData tiene asociado un Resultset. El
Resultset es el objeto rdoResultset del control RemoteData (Colección de registros, o si lo prefiere, de filas ya que
estamos en RDO), y que como cualquier objeto de acceso a datos, tiene sus métodos, y este es uno.
Realiza una actualización optimista por lotes.
Sintaxis
MSRDC1.Resultset.BatchUpdate (filaunica, forzar)
Donde MSRDC1 es el nombre del control RemoteData
Filaunica (Booleano) indica si es True, que solamente actualizará la fila actual, si es False, actualiza todo el lote. El
lote es un conjunto de filas. Pueden ser las filas del cursor.
Forzar (Booleano)indica si está a True que sobreescribirá la fila actual, independientemente de si causa o no
colisiones. Si está a False, no sobreescribirá si va a ocurrir una colisión.
Este método es un método del rdoResultset. Si tenemos un rdoResultset creado con código (Ahora veremos como se
hace) la sintaxis sería
MirdoResultset. BatchUpdate (filaunica, forzar)
Con esta introducción ya podemos pensar que el alumno tiene cierta idea respecto a lo que es el control
RemoteData. Vamos a comenzar a explicar lo que son los objetos de acceso remoto a datos (Objetos RDO) y
podremos seguir viendo cosas acerca del control RemoteData como aplicación de estos nuevos objetos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 378
Objetos de datos remotos (Objetos RDO)
Como ya conocemos los objetos de acceso a datos DAO, veremos los objetos RDO basándonos un poco en este
conocimiento.
Los objetos de datos remotos nos permiten manipular componentes de un sistema de base de datos ODBC remoto.
Lo de remoto no implica que la base de datos deba estar en un ordenador distinto al que tiene la aplicación.
(Aunque esta sea la disposición más usual en aplicaciones que usan RDO). El significado de RDO es que se accede
a la base de datos a través de una conexión ODBC.
RDO solamente funciona en plataformas de 32 bits. (Windows 95/98/2000 o Windows NT). Para usar objetos de
datos remotos, debe establecer una referencia a Microsoft Remote Data Object 2.0 en Proyecto | Referencias.
Al igual que en DAO, los objetos RDO tienen una estructura jerárquica que se puede ver en la siguiente figura:
Estructura jerárquica de los objetos RDO
Los objetos RDO siguen la misma regla para su creación que los objetos DAO: el objeto jerárquicamente
superior crea al objeto inferior.
El Objeto rdoEngine
El objeto rdoEngine representa el origen de datos remoto. Es el equivalente al dbEngine de DAO, es decir, el
motor de bases de datos. Es el objeto de nivel jerárquico superior, por lo tanto no se crea por otro objeto, sino que
está creado simplemente al introducir la referencia.
La característica del rdoEngine es que trabaja siempre a través del Administrador de controladores. El objeto
rdoEngine contiene al objeto rdoEnvironments (Colección de objetos rdoEnvironment) y el rdoErrors.
Los objetos rdoEnvironment de nueva creación se inicializan de acuerdo a los valores predeterminados
establecidos en el objeto rdoEngine. Se crea de forma automática el objeto rdoEnvironments(0), al igual que lo
hacía el dbEngine con el Workspaces(0) en DAO.
El objeto rdoErrors contiene todos los mensajes de error enviados desde el origen de datos remoto. Cada vez que
se recibe uno de estos mensajes, se produce el evento InfoMessage del rdoEngine
Propiedades del objeto rdoEngine
rdoDefaultLoginTimeout Determina el valor predeterminado la propiedad LoginTimeout de los objetos
rdoEnvironment que se creen. Esta propiedad se utiliza en la administración del tiempo disponible para la
conexión. Si la conexión no se ha realizado en el número de segundos indicado, dará error.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 379
Sintaxis rdoEngine.rdoDefaultLoginTimeout = NumeroDeSegundos
Si el valor NumeroDeSegundos es cero, esperará indefinidamente a que se realice la conexión.
rdoDefaultCursorDriver Determina el valor predeterminado de la propiedad CursorDriver de los objetos
rdoEnvironment. Esta propiedad determina si el Administrador de controladores ODBC crea cursores por lotes del
lado del cliente, locales, del servidor o si no crea cursores.
Sintaxis rdoEngine.rdoDefaultCursorDriver = valor
Donde Valor es un valor o contante según puede verse en la siguiente tabla
RdUseIfNeeded (Predeterminado) elige el estilo de cursores más apropiado para el
Controlador
Utiliza la biblioteca de cursores ODBC.
RdUseODBC
Utiliza cursores del servidor
RdUseServer
Usa la biblioteca de cursores optimista por lotes
RdUseClientBatch
No crea un cursor desplazable. Básicamente es un conjunto de
RdUseNone
resultados de sólo lectura de tipo forward-only
rdoDefaultUser y rdoDefaultPassword Determinan los valores predeterminados de las propiedades
UserName y Password de los objetos rdoEnvironment cuando se abren conexiones sin suministrar valores para
estos parámetros.
rdoVersion Examina la versión de RDO en uso.
rdoLocaleID Devuelve o establece un valor que indica la configuración regional de la biblioteca RDO,
para mostrar los mensajes de error.
Sintaxis rdoEngine.rdoLocaleID = valor
Por defecto, esta propiedad toma el valor 0, que pone la configuración establecida en Windows.
Si el archivo DLL del idioma especificado no está presente en el equipo del usuario, RDO se establece como
rdLocaleEnglish, lo cual no requiere un archivo DLL independiente. Cuando esto ocurre, se coloca un mensaje
informativo en la colección rdoErrors para indicar que RDO no pudo cargar el archivo DLL de recursos para la
configuración regional especificada.
Cuando distribuya la aplicación, asegúrese de incluir el archivo DLL del lenguaje apropiado.
Métodos del rdoEngine
rdoCreateEnvironment Este método es equivalente al CreateWorkspace de DAO. Crea un nuevo
objeto rdoEnvironment. (Es decir, una sesión de trabajo)
Sintaxis Set MiSesion = rdoEngine.rdoCreateEnvironment(Nombre, Usuario, Contraseña)
Donde:
es la propiedad Name del nuevo objeto rdoEnvironment. (En el código, para nombrar a este
rdoEnvironment debemos hacerlo con MiSesion). Debe suministrar un nombre, ya que si no lo hace, este
rdoEnvironment creado no se suma a la colección rdoEnvironments.
Usuario es el nombre del usuario.
Con traseñ
a es la contraseña usada en esa sesión. Puede tener hasta 14 caracteres.
Nombre
Cuando se inicializa el rdoEngine se crea automáticamente una sesión de trabajo predeterminada, el
rdoEnvironments(0), con el nombre de usuario que tenga el rdoEngine en su propiedad rdoDefaultUser y con
contraseña igual a la propiedad rdoDefaultPassword . En una aplicación multiusuario es necesario crear un
rdoEnvironment para cada uno de ellos, siempre que empleemos transacciones. En este método es necesario
suministrar todos los parámetros (Nombre, Usuario y Contraseña)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 380
rdoRegisterDataSource Introduce la información de conexión en el Registro de Windows para un
origen de datos ODBC (Crea una conexión ODBC igual que lo haríamos en Windows)
Sintaxis
rdoEngine.rdoRegisterDataSource DSN, controlador, silencio, atributos
DSN es el nombre que queremos dar a la conexión ODBC
Controlador es el nombre del controlador ODBC. Debe ser uno de los
instalados y hay que poner el nombre exacto
por el que se le conoce en Windows, NO el nombre de la DLL. Por ejemplo, debe poner Microsoft Access Driver
y no odbcjt32.dll
Silencio es un valor True / False y se refiere a si queremos que presente el cuadro de creación de un enlace ODBC
(El mismo que aparece en Windows) Si ponemos False en esta propiedad, le introducimos los datos de la conexión
a través de ese cuadro. Si le ponemos True, no mostrará el cuadro, y por lo tanto deberemos pasarle todos los
parámetros correctamente. Si la información suministrada no es completa, mostrará el cuadro citado.
Atributos. Una expresión de cadena que es una lista de palabras clave que se van a agregar al archivo ODBC.INI.
Las palabras claves están en una cadena delimitadas por retornos de carro. No es trivial esta cadena de caracteres y
es propia de cada controlador. Por lo tanto, le recomiendo que si no conoce muy bien la cadena a introducir, ponga
el parámetro Silencio a False y se olvide de este parámetro de atributos. Eso sí, deberá ser el usuario quien
introduzca los datos a través del cuadro de creación del enlace ODBC.
Hasta aquí las propiedades y métodos del rdoEngine. Vamos a bajar un nivel jerárquico y ver el siguiente objeto
RDO
El Objeto rdoEnvironment
Un objeto rdoEnvironment es una sesión de trabajo en RDO. Equivale al Workspace de DAO. En un
rdoEnvironment podemos tener varios objetos Connection (varias conexiones) de la misma forma que en un
Workspace podíamos tener varias objetos Database.
La colección de todos los objetos rdoEnvironment es el objeto rdoEnvironments. Visual Basic crea
automáticamente un rdoEnvironment, de la misma forma que creaba un Workspace. El objeto rdoEnvironment
creado es el rdoEnvironments(0) y el nombre de usuario será el que tenga el rdoEngine en su propiedad
rdoDefaultUser y la contraseña igual a la propiedad rdoDefaultPassword
NOTA. Visual Basic crea automáticamente un Workspace o un rdoEnvironment si el proyecto contiene la referencia
al motor de bases de datos correspondiente. Visual Basic no creará ninguno de ellos si no tiene la referencia a
ningún motor de bases de datos.
Los objetos rdoEnvironment se anexan automáticamente a la colección rdoEnvironments a menos que no
proporcione un nombre para el nuevo objeto cuando utilice el método rdoCreateEnvironment.
Propiedades del Objeto rdoEnvironment
Propiedad CursorDriver Ya hemos visto esta propiedad para el control RemoteData. La aplicación al objeto
rdoEnvironment es similar, por lo que solamente exponemos su sintaxis:
MiSesión.CursorDriver = Valor donde Valor toma uno de estos valores o constantes:
0
rdUseIfNeeded
1
2
3
rdUseOdbc
rdUseServer
rdUseClientBatch
LSB
El controlador ODBC elegirá el tipo de cursores adecuado. Se
usarán cursores del servidor si hay alguno disponible.
Usará la biblioteca de cursores de ODBC .
Se usarán cursores del lado del servidor.
RDO usará la biblioteca de cursores por lotes de tipo optimista.
Visual Basic – Guía del Estudiante
Capítulo 1
Página 381
Propiedad hEnv
Esta propiedad es el Handle de la conexión ODBC. Es similar a la propiedad hDC (para controles) o hWnd (para
formularios) que ya hemos visto en capítulos anteriores. Esta propiedad es sólo de lectura y devuelve un Long. Este
valor lo usan las APIs de Windows para trabajar. Alguna instrucción nos pedirá el hEnv como parámetro.
Propiedad LoginTimeout
Devuelve o establece el número de segundos que el Administrador de controladores ODBC espera antes de que se
produzca un error de espera al abrir una conexión.
Sintaxis NombreDelObjetordoEnvironment.LoginTimeout = NumeroDeSegundos
El valor predeterminado es el de la propiedad rdoDefaultLoginTimeout del objeto rdoEngine, y en su defecto, de
15 segundos. Si este valor es igual a 0 se espera indefinidamente y no se producirá ningún error.
Si establece un valor para esta misma propiedad en uno de sus objetos rdoConnection, este valor es prioritario al
establecido en el objeto rdoEnvironment.
Métodos del objeto rdoEnvironment
Método OpenConnection
Abre una conexión con un origen de datos ODBC. En otras palabras, crea un objeto rdoConnection, objeto que
deberá declarar antes de abrirlo:
Dim MiConexion as rdoConnection
Set MiConexión = MiSesion.OpenConnection(Nombre, LineaComandos, SóloLectura, Conectar, Opciones)
Nombre puede ser una conexión ya creada, en cuyo caso se
abrirá esa conexión. Si este parámetro es una cadena
vacía, deberá obtener los datos de la conexión, o bien del argumento Conectar, o mediante el cuadro de dialogo de
abrir la conexión.
LineaComandos. Determina si muestra o no muestra el cuadro de diálogo
de abrir la conexión ODBC. Puede tomar
estos valores
rdDriverPrompt (0)
rdDriverNoPrompt
rdDriverComplete
RdDriverComplete
Required
Muestra el cuadro de diálogo
No muestra nunca el Cuadro de diálogo
(1)
Muestra el cuadro de diálogo solamente si la información
(2)
facilitada no es suficiente para abrir la conexión.
Igual que rdDriverComplete pero deshabilita las opciones
(3)
que ya estén bien pasadas en la información facilitada.
Determina si la conexión se abre como sólo lectura o para lectura / escritura. Si no se especifica nada,
se abre para lectura / escritura.
SóloLectura
Este es el argumento que lleva los datos completos de la conexión. Es similar a la propiedad Connect del
control RemoteData, cuyo contenido repetimos aquí por comodidad.
Conectar
Para introducir los datos de la propiedad Connect deberá usar una palabra para definir el dato, seguido del signo = y
del dato a introducir. Como final del dato debe introducir necesariamente el signo punto y coma ;
DSN Origen de datos ODBC registrado.
UID
Nombre de un usuario reconocido
PWD Contraseña asociada al usuario
DRIVER
Descripción del controlador
DATABASE
Base de datos predeterminada
para usarla una vez conectado
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
DSN=MiConexiónODBC;
UID=Luis;
PWD=MiContraseña;
DRIVER=SQL Server;
DATABASE=MiBase;
Página 382
SERVER
WSID
APP
Nombre del servidor donde se
aloja la base de datos
SERVER=MiServidor;
Nombre de la estación de trabajo
(Nombre del PC que se va a
comunicar con el servidor
WSID=NombredemiPC;
Nombre de la Aplicación que va a
Usar la Base de Datos
APP=MiAplicación
Estos datos complementan la información de la conexión. Si ya habíamos establecido la conexión mediante el
argumento Nombre, y en esa conexión ya estaban perfectamente definidos todos los parámetros de esa conexión, de
este argumento Conectar solamente tomará el nombre de usuario y la contraseña.
Puede comprobar si se ha completado la conexión examinando la propiedad StillConnecting del objeto
rdoConnection recién creado, que debe devolver False cuando se ha completado la operación de conexión.
If MiConexion.StillConnecting = false then ….
BeginTrans, CommitTrans, RollbackTrans (Transacciones)
Son los métodos para realizar transacciones.
* BeginTrans comienza una nueva transacción.
* CommitTrans finaliza la transacción actual y guarda los cambios.
* RollbackTrans finaliza la transacción actual y restaura las bases de datos del objeto rdoEnvironment al
estado en que estaban cuando comenzó la transacción actual.
El funcionamiento en RDO es distinto al de DAO. Además, es distinto para cada base de datos. La forma de trabajar
de SQLServer es distinta de cómo lo hace Oracle. Y muy distinta de cómo lo hace Access. Le recomiendo que
estudie las transacciones en el manual de su gestor de base de datos.
Hay algunas bases de datos que no aceptan transacciones. Puede comprobarlo analizando la propiedad Transactions
del objeto Connection.
Método Close
Cierra un el rdoEnvironment y todas las conexiones que tenía abiertas. Las modificaciones pendientes
de los objetos RDO inferiores que estuviesen abiertos se deshacen.
Sintaxis
MiSesion.Close
No se puede cerrar el rdoEnvironments(0) Si utiliza Close con el objeto ya cerrado, se producirá un error
interceptable..
El objeto rdoConnection
Un objeto rdoConnection representa una conexión abierta con un origen de datos a través de ODBC. Es el
equivalente al Objeto DataBase de DAO
Un objeto rdoConnection (es decir, una conexión a una base de datos a trvés de ODBC) se crea o con un control
RemoteData o mediante el método OpenConnection del objeto rdoEnvironment.
Puede también crear un nuevo objeto rdoConnection que no esté vinculado de forma inmediata con una conexión
física específica a un origen de datos. Por ejemplo, el siguiente código crea un objeto rdoConnection
independiente:
Dim OtraConexion as New rdoConnection.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 383
Posteriormente puede introducir las características que desee y establecer la conexión real con la base
de datos. No es normal hacer esto, por lo que le remito en caso necesario, a la ayuda de VB de este
objeto.
Propiedades del Objeto rdoConnection
Un objeto rdoConnection tiene Propiedades. Muchas de ellas ya se han visto, bien al estudiar el control
RemoteData o los objetos RDO ya estudiados. Las propiedades que se han visto se describirán sólo de
forma somera.
Propiedad Connect Devuelve o establece un valor que proporciona información sobre el origen de un objeto
rdoConnection abierto. La propiedad Connect contiene la cadena de conexión ODBC. Esta propiedad puede leerse
siempre, pero no puede modificarse una vez establecida la conexión.
Sintaxis objeto.Connect = CadenaDeConexión
Las partes de CadenaDeConexión son: (Puede no usar alguna de ellas)
DSN
UID
PWD
DRIVER
DATABASE
SERVER
WSIS
APP
Nombre del origen de datos (Nombre de la conexión ODBC)
Nombre del usuario (Puede no tener nombre de Usuario)
Password. (Puede no tener Password)
Nombre del driver ODBC empleado
Nombre de la base de datos que se va a emplear
Nombre del servidor remoto
Nombre de la estación de trabajo dentro de la red
Nombre de la Aplicación
(El separador es el carácter punto y coma (;)
No es necesario aportar estos datos para crear la conexión, ya que son los que se han introducido en
Windows al crear la conexión ODBC. Estos datos solamente son necesarios si la conexión ODBC se
creó sin aportarle datos acerca de la base de datos.
Propiedad hDbc
Devuelve el controlador de conexión ODBC.
Sintaxis
MiConexion.hDbc
La propiedad hDbc devuelve un valor de tipo Long. Este valor lo utilizan las APIs de Windows. Y es similar a hDc
o hWnd
Propiedad LastQueryResults
Devuelve un objeto rdoResultset, precisamente el que se ha generado la última consulta, si la ha habido. Esta
propiedad podemos utilizarla para crear un nuevo Resultset, clónico del ultimo que se ha generado.
Sintaxis
Dim MiRs as rdoResultset
Set MiRs = MiConexion.LastQueryResults
Si no se había creado todavía ningún Resultset, devuelve Nothing.
Propiedad QueryTimeout
Devuelve o establece un valor que especifica el número de segundos que espera el Administrador de
controladores ODBC antes de que se produzca un error de tiempo de espera al ejecutarse una consulta.
El valor predeterminado es de 30 segundos.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 384
Propiedad StillConnecting
Devuelve un valor que indica si la conexión se está estableciendo todavía.
Sintaxis MiConexion.StillConnecting
Esta propiedad devuelve True si la conexión no ha terminado de establecerse, y False si ya está
establecida. Es fundamental saber que la conexión ya está establecida antes de realizar ninguna
operación con ella, por ejemplo, crear un Resultset
Propiedad StillExecuting
Devuelve un valor que indica si una consulta está aún ejecutándose. Esta propiedad se usa cuando creamos un
rdoResultset o un rdoQuery, para conocer si ya se ha finalizado el proceso de selección de filas que esa operación
implica. Esta propiedad puede aplicarse al rdoConnection, rdoQuery y rdoResultset. Devuelve True cuando la
consulta está ejecutándose todavía, False si ya se ha finalizado.
Sintaxis
objeto.StillExecuting
Propiedad Transactions
Devuelve un valor que indica si se pueden realizar transacciones con un objeto rdoConnection ó rdoResultset. Esta
propiedad le permite asegurarse de esta circunstancia antes de ejecutar la instrucción BeginTrans.
La propiedad Transactions llama a la función SQLGetInfo de ODBC para determinar si el controlador ODBC es
capaz de permitir transacciones, no si el conjunto de resultados actual es actualizable.
Propiedad AsyncCheckInterval
Devuelve o establece un valor que especifica el número de milisegundos que espera RDO entre dos comprobaciones
para ver si se ha completado una consulta asíncrona.
Sintaxis
MiConexion.AsyncCheckInterval = valor
El valor por defecto es de 1 segundo (1000 mseg)
Comentarios Al usar la opción rdAsyncEnable para ejecutar una consulta de forma asíncrona, RDO comprueba
periódicamente el origen de datos para determinar si la consulta se ha completado. Puede modificar la duración del
intervalo entre comprobaciones mediante la propiedad AsyncCheckInterval. RDO también comprueba el estado de
las consultas asíncronas cuando se examina la propiedad StillExecuting.
Propiedad UpdateOperation
Esta propiedad afecta a la forma en la que se realiza la modificación de una fila en una actualización
optimista por lotes. Si a esta propiedad se le pone el valor 0 (Predeterminado) la modificación de la fila
se realiza mediante una instrucción Update. Si el valor es 1, la operación de modificación se realiza
mediante dos instrucciones, primero una instrucción Delete (borra la fila) y a continuación otra
instrucción Insert (Crea la fila con los nuevos valores).
Sintaxis objeto.UpdateOperation [= valor]
El Objeto rdoResultset
El Objeto rdoResultset es el conjunto de filas que devuelve la ejecución de una consulta. Es el equivalente al
Recordset de DAO
El Objeto rdoResultset se crea mediante el método OpenResultset del rdoConnection.
Ejemplo:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 385
‘Creamos el objeto rdoEnvironment utilizando el objeto creado
automáticamente por VB
Set GepaWs = rdoEnvironments(0)
‘El objeto rdoEnvironment crea el objeto rdoConnection
Set GepaConex = GepaWs.OpenConnection(“Gepa”, rdDriverNoPrompt, False)
‘(Gepa es el n ombre de la conexión ODBC creada en el ordenador)
‘El objeto rdoConnection crea el objeto rdoResultset
Set GepaRs = GepaConex.OpenResultset("Select Ex_expedite, Ex_numproye, " & _
"Ex_presenta, Ex_plan, Ex_tipoexpe, Ex_tipoprop, Ex_tipotram, Ex_redaproy, Ex_situxpe, " & _
"Ex_Numero_Ini, Ex_subsiste " & _
"From Expedientes Order By Ex_Numero_Ini", rdOpenDynamic, rdConcurRowVer)
Puede ver que el proceso de creación de un rdoResultset en RDO no difiere demasiado de la creación
de un recordset en DAO.
Veamos cada una de las partes del Método OpenResultset
Set MirdoResultset = MiConexión.OpenResultset(nombre [,tipo [,tipoBloq [,opciones]]])
Donde
MirdoResultset = variable tipo rdoResultset que debe estar declarada.
MiConexión = Objeto Connection con el que se crea el rdoRsultset
Nombre =
Nombre de una tabla o consulta de la base de datos, o una sentencia
SQL que pueda devolver filas.
Tipo =
Tipo de cursor que se va a crear
TipoBloq =
Tipo de bloqueo de la base de datos. Por defecto, lo crea solo lectura.
Opciones =
Opciones que puede tener el rdoResultset
El argumento Tipo puede tener una de estos valores:
Constante
rdOpenForwardOnly
rdOpenKeyset
rdOpenDynamic 2
rdOpenStatic
Valor
Descripción
0
(Predeterminado) Abre un rdoResultset tipo forward-only.
1
Abre un rdoResultset tipo Keyset
Abre un rdoResultset tipo Dinamico
3
Abre un rdoResultset tipo estático
El tipo forwar-only es un rdoResultset en el que las filas solamente se pueden explorar en sentido
ascendente. No se puede retroceder .
El tipo Keyset es un rdoResultset que se puede actualizar, insertar nuevas filas, y se puede recorrer en
ambos sentidos sin limitación. Los miembros de este rdoResultset son fijos.
El tipo Dinámico es un rdoResultset que se puede actualizar, insertar nuevas filas, y se puede recorrer
en ambos sentidos sin limitación. Los miembros de este rdoResultset no son fijos.Es similar al Dynaset
de DAO.
El tipo estático presenta los valores existentes en la BD en el momento de su creación y no detecta las
posibles variaciones de los datos en la misma. Es similar al Snapshot de DAO
Para el parámetro Tipo de Bloqueo acepta los siguientes datos:
Constante
rdConcurReadOnly
RdConcurLock 2
rdConcurRowVer
Valor
Descripción
1
(Predeterminado) Sólo lectura.
Concurrencia pesimista.
3
Concurrencia optimista basada en el Id. de fila. rdConcurValues
4
Concurrencia optimista basada en valores de filas. rdConcurBatch
5
Concurrencia optimista
usando actualizaciones de modo por
lotes. Valores Status devueltos por
cada fila actualizada con
éxito.
El parámetro opciones acepta estos valores: (Se pueden sumar ambas)
Constante
LSB
Valor
Descripción
Visual Basic – Guía del Estudiante
Capítulo 1
Página 386
rdAsyncEnable
rdExecDirect
32
Ejecuta la operación de forma asíncrona.
64
(Predeterminado) Evita la creación de procedimientos
almacenados para ejecutar la consulta.
El objeto rdoResultset tiene algunas particularidades que no tienen los recordsets de DAO, por ejemplo,
poder obtener resultados múltiples, es decir, se pueden introducir varias sentencias SELECT y cada una
de ellas crea un conjunto de registros. Esto no significa que haya mas de un rdoResultset, sino que
existe un único rdoResultset con resultados múltiples. Se puede ir accediendo a cada uno de los
conjuntos de registros mediante el método MoreResults.
Propiedades del Objeto rdoResultset
El rdoResultset no tiene exactamente las mismas propiedades que el Recordset. Y además no siempre funcionan tal
como lo hacían en el recordset. En RDO van a depender del tipo de cursor y del tipo de bloqueo. Veamos las
propiedades del rdoResultset
AbsolutePosition.
Igual que en RDO, pero no siempre funciona, ya que depende del tipo de cursor.
ActiveConnection
Devuelve una referencia a la conexión con la que está asociado el rdoResultset
BatchCollisionCount Devuelve un valor que especifica el número de filas que no finalizaron la última
actualización por lotes. Devuelve un Long. En caso de que esta propiedad sea mayor de 0 significa que
la actualización por lotes no se ha completado con éxito. En este caso habrá que ejecutar el método
BatchUpdate para completar la actualización.
BatchCollisionRows
Devuelve una matriz de marcadores que indica las filas que han provocado colisiones en la última
operación de actualización por lotes. Devuelve un Variant con una matriz de las filas que han provocado
una colisión la última vez que se invocó el método BatchUpdate. El número de elementos de esta matriz
es el que indica la propiedad BatchCollisionCount
BatchSize (Propiedad)
Devuelve o establece un valor que especifica el número de instrucciones enviadas al servidor en cada
lote. De forma predeterminada se envían 15 instrucciones al servidor en cada lote. Esta propiedad puede
modificarse en cualquier momento. Si un DBMS no admite lotes de instrucciones, puede establecer esta
propiedad a 1, con lo que cada instrucción se enviará por separado.
BOF, EOF
Son idénticas a las mismas propiedades del Recordset de DAO
Funciona igual que en el Recordset de DAO. Pero en RDO es posible que esa propiedad no se pueda
usar. Depende del tipo de cursor. Para asegurarse de que el objeto rdoResultset admite marcadores, examine el valor
de su propiedad Bookmarkable antes de usar su propiedad Bookmark. Si Bookmarkable es False, el objeto
rdoResultset no admite marcadores y el uso de Bookmark producirá un error
La propiedad Bookmark no se aplica a los objetos rdoResultset de tipo forward-only.
Bookmark
En DAO la variable donde se guarda el Bookmark debía se un String. En RDO es un variant.
Desconozco la razón, pero usando una variable String para almacenar el Bookmark falla.
Bookmarkable Devuelve un valor que indica si un objeto rdoResultset admite marcadores, es decir, si
acepta la propiedad Bookmark.
Devuelve un valor que indica el estado de edición de la fila actual. Devuelve un integer o
EditMode
una constante de acuerdo con la tabla siguiente:
Constante
LSB
Valor
Descripción
Visual Basic – Guía del Estudiante
Capítulo 1
Página 387
RdEditNone
RdEditInProgress
0
1
No se está efectuando ninguna operación de modificación.
Se ha invocado el método Edit y la fila está en buffer de copia.
RdEditInProgress
2
Se ha invocado el método AddNew y la fila actual del búfer de
copia es una fila nueva que no se ha guardado en la B. D.
LastModified Devuelve un marcador que indica la última fila modificada o agregada más
recientemente. Este marcador es el Bookmark de esa fila. Devuelve un Variant.
LockEdits Devuelve un valor de tipo Booleano que indica el tipo de bloqueo en vigor. Si devuelve True
utiliza bloqueo pesimista. Si devuelve False utiliza bloqueo optimista.
Si LockEdits es True y otro usuario ya tiene la página bloqueada, se producirá un error al
intentar usar el método OpenResultset. En general, los demás usuarios pueden leer datos de las
páginas bloqueadas.
Si LockEdits es False (valor predeterminado) y utiliza después Update mientras la página está bloqueada
por otro usuario, se producirá un error.
El bloqueo se realiza sobre una página de datos. La página suele se de 2 K (Ese es el tamaño que utiliza
Microsoft SQL Server)
LockType Devuelve o establece un valor entero de tipo Long que indica el tipo de tratamiento de
concurrencia. Los valores admitidos son:
Constante
Valor
Descripción
(Predeterminado) El cursor es de sólo lectura. No se admiten actualizaciones.
Concurrencia pesimista.
rdConcurLock
Concurrencia optimista basada en el identificador de fila.
rdConcurRowVer
Concurrencia optimista basada en los valores de las filas.
rdConcurValues
Concurrencia optimista con actualizaciones por lotes. Se obtienen valores de
5
rdConcurBatch
estado para cada fila actualizada correctamente.
Lea la ayuda de VB para obtener mayor información de cada uno de los tipos.
rdConcurReadOnly
1
2
3
4
Restartable Devuelve un valor que indica si un objeto rdoResultset admite el método Requery, que
vuelve a ejecutar la consulta en la que está basado el objeto rdoResultset. Debe usarse antes de utilizar
el método Requery para evitar que se produzca un error.
PercentPosition
Devuelve o establece un valor que indica o modifica la ubicación aproximada de la fila actual en el objeto
rdoResultset, basándose en el porcentaje con respecto al total de filas de dicho objeto. El valor devuelto es un
Single entre 0,0 y 100,0
Puede usar la propiedad PercentPosition con una barra de desplazamiento de un control Form o TextBox para
indicar la ubicación de la fila actual en un objeto rdoResultset. Esta propiedad solamente se aplica a los
rdoResultset tipo Keyset y Dynamic.
RowCount Devuelve el número de filas a las que se ha tenido acceso en un objeto rdoResultset. Es un
Long.
Esta propiedad no indica el número de filas del Resultset, sino el número de filas a las que se ha
accedido. No es por lo tanto, el equivalente a la propiedad RecordCount del Recordset DAO.
Si esta propiedad no está disponible en el controlador, devuelve -1
Devuelve o establece el estado de la fila o columna actual. El valor de esta propiedad indica si la fila o la
columna estarán implicadas en la próxima actualización optimista por lotes y de qué modo lo estarán.
Status
Los valores admitidos para la propiedad Status son:
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 388
Constante
Valor
rdRowUnmodified
0
rdRowModified
1
rdRowNew
2
rdRowDeleted
3
rdRowDBDeleted
4
Valor de la propiedad Prepared
(Predeterminado) La fila o la columna no se han modificado o se han
actualizado correctamente.
La fila o la columna se han modificado y aún no se han actualizado en
la base de datos.
La fila o la columna se han insertado con el método AddNew, pero aún
no se han insertado en la base de datos.
La fila o la columna se han eliminado, pero aún no se han eliminado de
la base de datos.
La fila o la columna se han eliminado localmente y también de la base
de datos.
StillExecuting Devuelve un valor de tipo Booleano que indica si una consulta está aún ejecutándose.
Esta propiedad es muy útil (muy necesaria) para saber si la consulta ya está disponible, antes de presentar los datos
de esa consulta. La propiedad debe ser False para poder presentarlos. Es típico crear un bucle parecido a este:
Do While GepaRs.StillExecuting = True
DoEvents
Loop
Transactions
Devuelve un valor Booleano que indica si un rdoResultset permite transacciones.
Devuelve un Long el tipo de rdoResultset. (0 = rdOpenForwardOnly, 1 = rdOpenKeyset, 2 =
rdOpenDynamic, 3 = rdOpenStatic)
Type
Updatable Devuelve un valor Booleano que indica si se pueden efectuar cambios en el rdoresultset
Métodos del Objeto rdoResultset
El rdoResultset tiene algunos métodos comunes con el Recordset de DAO, sin embargo no se puede
esperar que funcionen siempre de la misma forma. En DAO era Visual Basic quien abría la base de
datos, y una base muy concreta, Access, dBase, etc., bases que controla directamente Visual Basic a
través de la dll correspondiente a la versión de la BD que vamos a abrir. Esto no es exactamente igual en
RDO. Aquí quien abre el fichero que contienen la base de datos no es Visual Basic, sino el driver de
ODBC. Y no solamente eso, dependiendo de la base de datos, unas permiten hacer unas operaciones y
otras no. Lo mismo podemos decir del tipo de rdoResultset, del cursor y de si es lado cliente o lado
servidor. Por lo tanto no se asuste si pretende ejecutar un método y no funciona. Probablemente es que
Visual Basic ha puesto por defecto unas características a los objetos que no son las adecuadas. Y si no
fuese posible, en última instancia nos queda realizar directamente la operación que pretendíamos
realizar con el método, es decir, mediante las operaciones que nos permite el propio driver de ODBC.
Eso sí, en este caso estamos en sus manos. Lo veremos más adelante.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 389
Método AddNew
Crea una nueva fila para un objeto rdoResultset actualizable.
Sintaxis
MirdoResultset..AddNew
Funciona igual que el mismo método de DAO, se ejecuta el método AddNew, se introducen los datos en los campos
y se termina la operación con el método Update, que es cuando los datos entran en la base de datos. Si se está
usando cursores de tipo Client Batch los datos se escribitrán en la BD cuando se ejecute el método BatchUpdate.
Hay que tener cuidado, pues el método AddNew no devuelve ningún error si se intenta añadir una nueva fila a un
rdoResultset no actualizable. Ese error va a salir cuando ejecutemos el método Update. Para evitar este error hay
que comprobar la propiedad Updatable del rdoResultset.
Debe tener cuidado también con asegurarse que tras el método AddNew ejecuta el método Update antes de
cambiar de fila, ya que de no hacerlo se pierden los cambios realizados y VB no avisa de ese error.
Si desea interrumpir la entrada de datos, una vez ejecutado el método AddNew puede anularse usando el método
CancelUpdate
MirdoResultset. CancelUpdate
La fila recién añadida no pasa a ser la fila actual. Sigue siendo fila actual la que era anteriormente. Para que sea la
nueva la fila actual basta con poner el siguiente código:
MirdoResultset.BookMark = MirdoResultset.LastModified
Pero eso sí, el rdoResultset debe aceptar marcadores. Para comprobarlo, se usa la propiedad Bookmarkable.
Método BatchUpdate
Realiza una actualización optimista por lotes. Veamos que significa esto.
Este método solamente se puede aplicar a un rdoResultset del tipo Client Batch (Cuando se crea el rdoResultset
usando como tercer parámetro rdUseClientBatch) El tipo de rdoResultset puede ser Keyset o Dynamic. En estas
condiciones, cuando usamos el método Update para guardar los datos, solamente se guardan en el rdoResultset
local, pero no se meten en la base de datos. Cuando se ejecuta este método, se envían a la base de datos todos los
cambios pendientes.
Sintaxis MirdoResultset.BatchUpdate (filaÚnica, forzar)
El parámetro filaÚnica es un Booleano que si es True, hace que la actualización sea solamente de la fila actual. Si
es False, se actualizan todas las filas pendientes.
forzar es tambiénun Booleano que si es True fuerza a escribir los valores, aunque puedan causar colisiones.
Si usa el método CancelBatch, se descartan los cambios guardados en el objeto rdoResultset local.
Método Close
Cierra un rdoResultset abierto. Es igual al método Close del Recordset de DAO
Sintaxis
MirdoResultset.Close
Método Delete
Elimina la fila actual de un objeto rdoResultset actualizable.
Sintaxis MirdoResultset.Delete
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 390
Es posible deshacer la eliminación de una fila si emplea transacciones y el método RollbackTrans, suponiendo que
usa BeginTrans antes que el método Delete.
Se producirá un error al utilizar Delete si:
No hay ninguna fila actual.
La conexión o el rdoResultset es de sólo lectura.
Ninguna columna de la fila es actualizable.
La fila ya se ha eliminado.
Otro usuario ha bloqueado la que contiene la fila.
El usuario no tiene permiso para realizar la operación.
Método Edit
Inicia la operación de cambiar los valores de los datos de la fila actual o en un objeto rdoResultset actualizable.
Funciona de la misma forma que el método del mismo nombre del Recordset de DAO. Al igual que en el método
AddNew, es necesario terminar la operación con el método Update.
Sintaxis
MirdoResultset.Edit
Si cambia la fila actual antes de ejecutar el método Update, se perderán los cambios. Si desea anular el cambio que
está realizando, basta con ejecutar el método CancelUpdate.
Cuando la propiedad LockEdits del objeto rdoResultset es True (bloqueo pesimista), todas las filas del conjunto
de filas del objeto rdoResultset se bloquean en cuanto se ejecuta Edit, y se mantienen bloqueadas hasta que se
ejecuta Update.
Método GetRows
Recupera múltiples filas de un rdoResultset y las introduce en una matriz.
Sintaxis
matriz = MirdoResultset.GetRows (filas)
Donde filas es el número de filas que se quieren recuperar. Es un Long
matriz es un Variant
El primer subíndice de la matriz identificará la columna y el segundo identifica el número de fila, de esta forma:
matriz(intColumn)(intRow)
Método MoreResults
Este método se utiliza cuando se ha creado un rdoResultset de resultados múltiples, es decir, se han
empleado varias sentencias SELECT para crearlo. Cada sentencia formará dentro del rdoResultset un
juego de filas. Cuando se utiliza el método MoreResults se borran las filas del conjunto de resultados
actual y se colocan en su lugar las filas correspondientes al siguiente. El método devuelve un Booleano
que es True si ha encontrado un nuevo conjunto de resultados, o False si no lo ha encontrado. No todas
las bibliotecas de cursores son compatibles con consultas de conjuntos de resultados múltiples. Por
ejemplo, la biblioteca de cursores del servidor no es compatible con este tipo de consultas si no
desactiva el procesamiento del cursor en un cursor de sólo lectura sólo hacia adelante con la propiedad
RowsetSize a 1.
Método Move
Cambia la posición de la fila actual en un objeto rdoResultset. Funciona igual que el mismo método del Recordset
de DAO
Sintaxis
LSB
MirdoResultset.Move filas[, inicio]
Visual Basic – Guía del Estudiante
Capítulo 1
Página 391
Métodos MoveFirst, MoveLast, MoveNext y MovePrevious
Funciona de la misma forma que los métodos del mismo nombre en el Recordset de DAO.
Método Requery
Actualiza los datos de un objeto rdoResultset volviendo a ejecutar la consulta en la que está basado el objeto.
Sintaxis
MirdoResultset.Requery [opciones]
El valor admitidi para Opciones es rdAsyncEnable (32) que ejecuta la operación de forma asíncrona
Método Update
Termina una operación de modificación de datos o de añadir una nueva fila. Ya se ha comentado su funcionamiento
con los métodos AddNew y Update.
No vamos a profundizar más en los objetos RDO. Su comportamiento es muy parecido a DAO,
exceptuando los nombres de los objetos, y las particularidades del ODBC en cuanto a la situación de los
cursores.
ODBC es una tecnología ya obsoleta (En el año 2002) y no debe emplearse para nuevos proyectos.
Lógicamente un curso de Visual Basic debe incluir RDO, pero siempre para aplicarlo al mantenimiento
de aplicaciones ya existentes. No se debe emplear para nuevos proyectos, ya que si se quiere emplear
ODBC es mucho más práctico y sencillo emplear DAO en su versión de ODBCDirect. Tendrá código
compatible con DAO, y más rapidez que con RDO. Además RDO es una tecnología considerada
obsoleta por Microsoft, con lo que ello conlleva.
Microsoft dice, y este autor recomienda: USE ADO EN TODOS SUS NUEVOS PROYECTOS
Pero si usa Access con la base de datos instalada en el mismo ordenador que el programa, use
directamente DAO. Si usa Access olvídese de nuevas tecnologías. Con Access DAO significa: Rapidez,
sencillez, eficacia, control sobre el programa, independencia de drivers.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 392
Visual Basic - Guía del Estudiante Cap. 14
ACTIVE X DATA OBJECT (ADO)
ADO es lo último de Microsoft en acceso a bases de datos. No se porqué, pero desde su inicio, ADO
está como metido en una aureola de dificultad a la que solamente pueden acceder informáticos
especialmente elegidos. Quizás sea el uso de palabras de argot muy rebuscadas, que más que facilitar
el estudio, atemorizan al principiante. La Guía del Estudiante pretende quitar esos velos que ocultan la
sencillez de lo cotidiano y mostrar la facilidad de esta técnica. Con el estilo didáctico que caracteriza a
este libro, pasaremos de las definiciones gloriosas e iremos a lo verdaderamente importante: saber
programar con ADO
ADO permite crear aplicaciones capaces de manipular bases de datos a través de un proveedor OLE DB
(Object Linking and Embedding for DataBase). El objetivo de OLE DB es poner a disposición del
programador una herramienta de nivel inferior que le de acceso universal a los datos con independencia
del origen de datos, ya sea un servidor de correo electrónico, una hoja de cálculo u otro tipo de
almacenamiento de datos. Debido a la complejidad de los elementos de OLE DB, no se puede acceder a
ellos directamente desde Visual Basic; para ello utilizaremos los objetos ADO que permiten acceder a la
práctica totalidad de las funciones de OLE DB.
O
L
E
D
B
A
D
O
s
to
a
d
Bases de datos
Relacionales
O
D
B
C
s
lo
a
e
d
e
c
c
Texto
a
e
u
q
n
ói
Modelo de datos ADO
c
a
icl
p
A
R
D
O
D
A
O
O
D
B
C
Bases de datos
relacionales
Modelo DAO/RDO
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 393
Las características generales de ADO son:


Mayor velocidad y facilidad de uso.
Menor carga de memoria y de espacio en el disco duro.
Las características específicas que proporciona ADO para entornos de Cliente/Servidor (C/S) son:
Creación de los objetos de forma independiente. No se necesita navegar por ninguna jerarquía
de objetos para poder crearlos. La mayoría de los objetos se pueden instanciar de forma
independiente. De esta forma crearemos solo los objetos que necesitemos.
ADO nos permite utilizar los procedimientos almacenados en el sistema gestor de la base de
datos (si este soporta esta funcionalidad), pudiendo recoger los resultados devueltos por dichos
procedimientos como parámetros de salida. Esta característica permite mejorar el rendimiento y
la rapidez de las aplicaciones.
Diferentes tipos de cursores.
Soporte para limitar el número máximo de registros devueltos de una sola vez en un recordset.
Esta característica mejora el rendimiento tanto de la aplicación como de la red.
Soporte para recibir varios recordset como resultados devueltos de un procedimiento
almacenado.





Hay que tener en cuenta que todas estas características están limitadas por el servidor de los datos. Es
decir, si el servidor de datos no soporta procedimientos almacenados, no podremos utilizar con él las
características de ADO que se refieren a dichos tipos de procedimientos.
Fig 72.1 Jerarquía de Objetos ADO.
Connection*
Error*
Errors
Command*
Parameter *
Parameters
Recordset
Field*
Fields
* Todos los objetos marcados con un asterisco contienen la colección Properties con un subconjunto
de objetos Property.
Pro erties
Pro ert
Como puede verse en la figura, existen tres objetos principales dentro de ADO: El objeto Connection, el
objeto Command y el objeto recordset. Luego veremos algunas de las características principales de
cada uno de estos objetos.
Antes de proseguir con estos objetos vamos a explicar donde y porqué se deben utilizar objetos ADO en
vez de objetos DAO u objetos RDO
Hasta ahora habíamos utilizado bases de datos Access, y también otras bases de datos sencillas como
dBase. Acceder a Access es extremadamente fácil. Y ello es debido a que Access es una base de datos
sin grandes aspiraciones en cuanto a seguridad. Es una gran base de datos, y tiene sus dispositivos de
seguridad en cuanto a permisos de acceso (Vea El dbEngine. Visión desde DAO y la propiedad
SystemDB en el Capítulo 12) sin embargo estas posibilidades se usan en muy pocas ocasiones, y estos
mecanismos de seguridad de Access tampoco son una maravilla. Por lo tanto Access se ha quedado
como una gran base de datos para aplicaciones que no pasen de algunos centenares de miles de
registros y con pocos puestos de operación. En esta base de datos, el método ideal de acceso es DAO,
bien directamente o a través de ODBC Direct. Cuando se accede directamente, la BD se suele buscar
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 394
bien mapeando el disco del servidor como una unidad más del puesto cliente, o bien accediendo a través
de la dirección IP del servidor.
Cuando queremos empezar a tener una seguridad en los accesos, disponer de privilegios distintos para
cada usuario, trabajar en una red de área local con muchos usuarios, hay que recurrir a bases de datos
tipo Oracle o SQLServer. Ya empezamos a tener problemas: Visual Basic no puede acceder
directamente a abrir estas bases de datos. Podemos acceder a través de ODBC, pero como ya se dijo
en el, capítulo correspondiente, ODBC se ha quedado obsoleto. Y Microsoft ha sacado para ello ADO. Y
ADO permite abrir la base de datos usando para ello un dispositivo intermedio que es el proveedor OLE
DB. Este no es más que una DLL. Mejor dicho, un juego de DLLs que puede ver en la carpeta:
C:\Archivos de Programa\Archivos Comunes\System\Ado
Estas DLLs permiten conectar con las bases de datos más conocidas (Oracle, SQLServer, Access y las
demás BD controladas por el motor Jet). ADO funciona de forma diferente a ODBC. Con ODBC se
preparan conexiones permanentes en el ordenador, y cualquier programa puede acceder a la BD a
través de esas conexiones. Con ADO no hay que preparar previamente ninguna conexión. Es el propio
programa el que llama al proveedor de datos OLE DB y le pasa como parámetros los datos necesarios
para que este realice la conexión y abra la BD. Si hubiese dos programas ejecutándose
simultáneamente y accediendo a la misma base de datos a través de ADO, cada programa prepara una
conexión a esa BD. En ODBC podríamos ver las conexiones existentes en el PC a través del Panel de
Control | Fuentes de Datos ODBC. En ADO no existe esa posibilidad ya que, como se ha dicho, es el
propio programa quien crea esa conexión al ajecutarse.
Para que VB pueda acceder a ADO es necesario introducir en el programa la referencia a Microsoft
ActiveX Data Objets 2.1 Library (Proyecto|Referencias)
Una particularidad de ADO frente a lo ya visto con DAO o RDO es que ADO se salta la jerarquía a la
hora de crear nuevos objetos. En DAO, el objeto DAO superior creaba al objeto DAO inferior (Recuerde
aquello del juego de niños). En ADO podemos crear cada objeto sin que exista el objeto inmediatamente
superior. Por ejemplo podemos crear un recordset sin que exista el objeto Connection. Claro que en
este caso, a la hora de crear el objeto recordset deberemos indicarle, mediante los parámetros que
debemos aportar en la sintaxis de creación del recordset, todos aquellos datos que le aportaríamos a la
creación del objeto Connection. Como ve no tiene ventajas. Solamente que nos desentendemos un poco
de abrir y cerrar el objeto Connection.
Veamos como se crea la conexión: Mediante el Objeto Connection
EL OBJETO CONNECTION
El objeto Connection representa una sesión con el origen de los datos. Dependiendo de la funcionalidad
del proveedor de los datos podremos utilizar determinadas propiedades, métodos y colecciones de este
objeto. La función de este objeto es recoger toda la información del proveedor de los datos que se va a
utilizar para crear un objeto recordset.
Para crear un objeto Connection, previamente debemos declararlo como variable objeto Connection:
Dim MiConexion as ADODB.Connection
El sitio donde se debe declarar depende como siempre, del ámbito que deseamos que tenga ese objeto.
Para crear el objeto Connection deberemos utilizar la siguiente sintaxis:
Set MiConexion = New ADODB.Connection
Nota: En el caso de que ejecutemos la aplicación y nos salga un error diciendo que el tipo no está
definido por el usuario, es que no hemos añadido la referencia de “Microsoft Actives Data Objects Library
x.x”
La conexión ¿está creada?. Sí, pero de momento es completamente inútil ya que no sabe ni siquiera
que base de datos debe abrir, ni con que usuario, ni las condiciones en las que debe abrir esa base
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 395
(Solo lectura, etc.) Esta información se la pasamos mediante la propiedad ConnectionString (Cadena de
conexión)
La propiedad ConnectionString
Es la propiedad más importante del objeto Connection. Se basa en encadenar una serie de argumentos
en una cadena de caracteres. Los diferentes argumentos son (dependiendo del proveedor OLE DB y de
la configuración de la red, se necesitarán todos o parte de ellos)
Especifica el nombre del proveedor que se usa en la conexión. (Oracle, SQLServer, Jet,
etc)
Data Source Especifica el nombre de la fuente de datos para la conexión. (Nombre de la base de
datos a la que se va a acceder.
Especifica el nombre de usuario que abre la conexión. Debe ser un usuario ya declarado
User Id
en la base de datos.
Especifica la clave utilizada por el usuario para abrir la conexión. Debe coincidir con el
Password
que tiene ese usuario registrado en la Base de datos.
File Name
Especifica el nombre del fichero específico de proveedor, que contiene la información de
configuración de la conexión. Este fichero es útil en instalaciones en red que requieran
modificaciones de conexión frecuentes.
Remote Provider
Especifica el nombre de un proveedor de datos remoto cuando se utiliza una
conexión cliente/servidor
Remote Server
Especifica el nombre del camino al servidor que se va a usar cuando se
establece una conexión cliente/servidor
Provider
Como ejemplo para la conexión a una base de datos Oracle, con el usuario que esa BD tiene por
defecto (scott) y el Password de este usuario (tiger) tendremos que especificar en el ConnectionString
la siguiente cadena de caracteres.
‘Provider=MSDAORA.1;Password=tiger;User ID=scott;Data Source=MADRID;’
donde el valor de Source es la cadena de conexión de Oracle que previamente tiene que estar
configurada con el SQL*Net o Net8 de Oracle.
Si lo que queremos es crear una conexión con una base de datos Access 2000
‘Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiadelEstudiante\PruebaADO.mdb;’
Si la base de datos es de Access 97 entonces tendremos que especificar otro provider:
‘Provider=Microsoft.Jet.OLEDB.3.5;Data Source=C:\GuiadelEstudiante\db1.mdb;’
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 396
Para una base de datos SQLServer
"Provider=SQLOLEDB.1;Password=ayudas01; User ID=ayudas01; Initial Catalog=Ayudas_M; Data
Source=ayudas_sql" (en una línea única)
Como puede comprobar, resulta una tanto complicado construir la cadena de conexión y mientras que
seamos novatos en ADO podemos tener problemas para crear esta cadena. ¿Pero es que no existe una
manera más fácil de construir esta cadena? Efectivamente. Hay un pequeño truco mediante el cual no
solo podemos crearla con un asistente, sino que además probaremos si la conexión es satisfactoria o
no.
Truco para construir la cadena de conexión.
1) Primero tenemos que incluir el componente “Microsoft ADO data control 6.0 (OLEDB)”. Podemos
hacerlo pulsando Ctrl.-T o en el menú Proyecto  Componentes.
2) Metemos en nuestro formulario el control y pulsamos F4 para ver sus propiedades.
3) Hacemos Click en la propiedad
ConnectionString y nos
aparecerá el botón de puntos
suspensivos. Hacemos Click en
el botón.
4) Ahora nos aparece el asistente
que nos mostrará 3 opciones.
Utilizar un DSN de archivo,
utilizar un controlador ODBC o
utilizar una cadena de conexión.
En todos los casos, a la
derecha de la opción hay una
opción que nos permite
seleccionar o generar el origen
de los datos. Usaremos la
cadena de conexión (opción por
defecto) y pulsaremos el botón
generar.
5) Al pulsar el botón generar, nos aparece otra ventana en la que tenemos cuatro pestañas aunque
únicamente necesitaremos dos de ellas para crear una cadena de conexión correcta y probada.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 397
El resto de las pestañas forman parte de otro capítulo exclusivo del control data de ADO, aunque
le invito a que curiosee por ellas. Seleccionaremos el proveedor de datos que queramos utilizar y
pulsaremos el botón siguiente para pasar a la siguiente pestaña.
6) En la Pestaña conexión, tenemos que proporcionar los datos correspondientes al proveedor de
la base de datos a la que queremos conectar. Por ejemplo para conectar con una base de datos
de tipo MS Access (MS Jet 4.0 OLEDB Provider para la versión 2000 de Access, MS Jet 3.5
OLEDB Provider para la versión 97 de Access), tenemos que decirle el nombre y path de la BD.
Para ello podemos utilizar el botón de los puntos suspensivos, que abrirá una ventana que
permitirá seleccionar el archivo .mdb . Si utilizamos el proveedor de datos de Oracle, tendremos
que indicarle como nombre de servidor la cadena de conexión utilizada en el SQL Net o en el
Net8 de Oracle (la misma cadena que especifica cuando se conecta a través de SQL*Plus).
En esta pestaña existen dos opciones interesantes:


“Contraseña en Blanco”, si la marcamos no nos permitirá teclear la contraseña.
“Permitir guardar la contraseña”, dependiendo de si está o no seleccionada, incluirá o no
en la cadena de conexión la clave del usuario. Para la primera prueba le recomiendo
que la marque. No obstante, haga diferentes pruebas con ellas para ver los resultados.
Después de haber dado esta información, pulsaremos el botón Probar conexión. En el caso de
que haya algún error, el asistente nos lo indicará con un mensaje.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 398
Prueba de conexión (fallida) con Proveedor de datos de Oracle
Prueba satisfactoria
7) Una vez que hemos probado satisfactoriamente la conexión, pulsaremos aceptar y volveremos a
la pantalla inicial, la de las 3 opciones. La diferencia es que ahora tenemos la cadena de
conexión rellenada por el asistente. Ahora podemos copiarla con ctrl.-C y llevarla a la parte del
código donde queremos establecer la conexión. No se olvide de que es una cadena y que
cuando se asigne a la propiedad ConnectionString debe ir entre comillas dobles.
8) Una vez que hemos probado que funciona al abrir el objeto Connection, No debemos olvidarnos
de eliminar el control data de ADO y de quitar el componente de nuestro proyecto, salvo que lo
vayamos a utilizar para otra cosa.
Ya conocemos el truco para formar la cadena de conexión y se la hemos introducido en la propiedad
ConnectionString ¿Ya está creada la conexión? Sí, pero todavía no sirve para obtener datos de la
base de datos. Pero ya hemos avanzado mucho. Ahora nuestro programa ya sabe al menos, como
poder abrir esa base de datos, pues conoce su nombre, usuario que la abre y Password. Solamente
queda aplicar un método del objeto Connection: el método Open con una sintaxis que no es
excesivamente difícil:
Miconexión.Open
La conexión se va a realizar a una base de datos que está en un servidor. Este servidor puede definirse,
bien por su dirección IP o por su nombre. Lo normal es definirlo por su nombre (Server_SQL_Mae) y no
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 399
por su dirección IP. Obviamente el nombre del servidor corresponderá a una dirección IP (Vamos a
considerar una red IP estática, pues si pretendemos entrar a explicar lo que es una red con direcciones
IP asignadas dinámicamente se nos complica la explicación). Esa dirección IP debemos indicársela al
PC en el fichero Hosts (o Lmhosts) que están en la carpeta Windows o en una de sus subcarpetas. En
estos ficheros explica como hacerlo. No se extrañe si, una vez indicado en ese fichero, sigue sin
encontrarlo. La primera conexión con el servidor la busca mediante llamadas broadcast en la red que no
siempre son bien tratadas por los routers. En muchas ocasiones he tenido que buscar el servidor a mano
(entorno de red) y, milagros de Windows, a partir de esa operación ya lo encuentra sin problemas.
Para seguir un poco el ejemplo que acompaña a este capítulo, vamos a ver el código utilizado para crear
la conexión. En el ejemplo usamos una base de datos Access (No es la mejor para demostrar como
funciona ADO, pero es la que los alumnos van a tener con mayor facilidad. Una base Oracle o SQL no
se instala fácilmente en un ordenador personal)
Set MiConexion = New ADODB.Connection
'MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"
'MiConexion.Open
Ahora nuestro programa ya está en contacto con la base de datos. Lo que falta ya lo puede suponer:
crear un recordset.
Aquí vamos a ver la primera diferencia con DAO. El recordset no lo crea el objeto Connection. Se crea él
a sí mismo. Para que pueda existir un objeto Recordset primero hay que declararlo:
Dim MiRecordset As ADODB.Recordset
(Hay que declararlo en el sitio adecuado dependiendo
del ámbito que necesite)
En el procedimiento donde se vaya a crear el recordset, para crearlo utilizaremos la siguiente sintaxis:
Set MiRecordset = New ADODB.Recordset
(Ya está creado. Pero no está abierto, ahora hay que
abrirlo)
MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic
Ya tenemos abierto el recordset. En este caso el recordset está formado por todos los registros con
todos sus campos de la tabla Alumnos, que está en la base de datos definida en la conexión
MiConexion, es del tipo Dynamic y el bloqueo de escritura es optimista.
Podríamos elegir ciertos registros, y solamente unos campos. Utilizaríamos una sentencia SQL
MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape2 From Alumnos " _
& “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adLockOptimistic
Si no hubiésemos creado previamente el objeto Connection, podríamos crear y abrir igualmente este
objeto recordset, pero, en vez de pasarle el nombre de la conexión (MiConexion) le pasaríamos la
cadena de conexión usada para crear ese objeto Connection.
Set MiRecordset = New ADODB.Recordset
MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False", adOpenDynamic,
adLockOptimistic
(Es solamente una línea. Ha sido Word quien la ha troceado)
Ahora ya podemos presentar los campos del recordset, usando la sintaxis que ya conocemos de DAO
TbNombre = “” & MiRecordset!Alumno_Nombre
TbApe1 = “” & MiRecordset!Alumno_Ape1
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 400
TbApe2 = “” & MiRecordset!Alumno_Ape2
Hagamos una pequeña pausa. Observe que hay diferencias de trabajar con ADO o hacerlo con DAO.
Con DAO.
Declarar MiSesion, MiBase y MiRecordset
Dim MiSesion as Workspace
Dim MiBase As DataBase
Dim MiRecordset as Recordset
Crear el objeto Workspace, el objeto DataBase y el objeto Recordset
Set MiSesion = Workspaces(0)
Set MiBase = MiSesion.OpenDatabase (“C: \GuiadelEstudiante\Alumnos.Mdb”)
Set MiRecordset = MiBase.OpenRecordset (“Alumnos, dbOpenDynaset)
Con ADO (Creando el objeto Connection)
Declarar MiConexion y MiRecordset
Dim MiConexion As ADODB.Connection
Dim MiRecordset As ADODB.Recordset
Crear la conexión y ponerle la cadena de conexión en su propiedad ConnectionString
Set MiConexion = New ADODB.Connection
MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"
Abrir el objeto Connection
MiConexion.Open
Crear el objeto recordset
Set MiRecordset = New ADODB.Recordset
Abrir el objeto Recordset
MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic
Con ADO (Sin crear el objeto Connection)
Declarar MiRecordset
Dim MiRecordset As ADODB.Recordset
Crear el Recordset
Set MiRecordset = New ADODB.Recordset
Abrir el Recordset
MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False", adOpenDynamic,
adLockOptimistic
Observe siempre que tanto en las declaraciones del objeto Connection y del objeto Recordset, como en
su creación, debemos anteponer siempre la palabra ADODB
Tanto el objeto Recordset como el objeto Connection se deberán cerrar cuando ya no se utilicen, o al
menos, al cerrar la aplicación. Esto es tanto más necesario cuanto mayor sea la seguridad de la base de
datos que vamos a utilizar. En algunas bases de datos, dejar una sesión abierta significa dejar una
aplicación zombie ejecutándose en el servidor, que habrá que cerrar desde su propio sistema operativo.
Este problema no le va a ocurrir utilizando Access, pero como ya se dijo al principio, Access no es el
mejor ejemplo de utilización de ADO. Para cerrar una sesión y un recordset utilizaremos el método Close
MiRecordset.Close
MiSesion.Close
LSB
(Recuerde que debe cerrar antes el recordset que la conexión)
Visual Basic – Guía del Estudiante
Capítulo 1
Página 401
¿Qué pasa con el equivalente del Workspace?
Cuando resumíamos en la página anterior el código a usar si usábamos DAO o ADO, parecía (aunque
no fuese cierto) que podíamos asimilar estos objetos
DAO
ADO
Recordset
DataBase
WorkSpace
Recordset
Connection
¿
Efectivamente el Workspace no tiene algo que pudiésemos decir “equivalente” en ADO. Esto es debido
a que ADO ya considera que el acceso desde los usuarios lo gestiona directamente la base de datos.
Recuerde que el Workspace en DAO era una “sesión de trabajo” de la base de da tos, donde podíamos
asociar un Workspace a cada usuario. ADO ya le pasa a la BD el nombre del usuario y su Password
para que la propia base de datos quien autorice a ese usuario.
Algunas cosas que le van a ocurrir cuando ya haya creado el recordset.
El empleo de bases de datos complejas en cuanto a seguridad nos va a obsequiar con limitaciones a los
recordsets que vamos a abrir en ADO. Y además esas sorpresas van a ser distintas si usa uno u otro
tipo de base de datos. (nos centraremos solamente en Oracle y SQLServer. Access, con la modestia
que le caracteriza, no va a dar ningún problema.)
Los recordsets abiertos mediante una consulta SQL (aquellos en los que seleccionamos parte de los
registros mediante
Select … Where van a crearse solo de lectura. Independientemente de los
parámetros que le pasemos a la hora de crearlos. La descripción del error va a ser algo así como que el
cursor es solamente de lectura. También observará con frecuencia, cuando intente ir a un registro
anterior al actual, MiRecordset.MoveFirst, p.e.) que le enviará un error diciendo que el cursor es
solamente de avance hacia a delante. Estos efectos los observará también cuando use la instrucción
SQL Order By. No hay que arrojar la toalla solamente por esto. Cuando eso ocurra, lo que hay que
hacer es volver a crear el recordset de forma que acepte escritura y movimiento hacia atrás. Eso
generalmente se logra abriendo el recordset con todos los registros de la tabla, e incluyendo en él todos
los campos.
En vez de :
MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape2 From Alumnos " _
& “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adLockOptimistic
usar esta otra alternativa:
MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic
Posiblemente necesitemos crear dos recordsets en un mismo procedimiento. Por ejemplo, es muy típico
tener que buscar el último registro para ver el último número de un identificador de registro (Alumno_ID)
y poner en este campo, al registro que vamos a crear, un número igual a ese más 1. En ese caso,
abriríamos el recordset usando la sentencia Order By Alumno_ID. Cuando queramos introducir un
nuevo registro mediante:
MiRecordset.AddNew
nos dirá que el cursor (el recordset, para entendernos) es solamente de
lectura. La solución es, abrir el recordset con la sintaxis anterior, leer el número de Alunmo_ID, cerrar el
recordset, crear otro recordset con el mismo nombre, usando la sintaxis:
MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic
Ahora ya nos permitirá usar el método AddNew. Basta con añadir las líneas de código adecuado para
introducir los valores en cada campo:
Mirecordset.AddNew
MiRecordset!Alumno_ID = Valor numérico
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 402
MiRecordset!Alumno_Nombre = Valor string
Etc.
….
MiRecordset.Update
No renuncie nunca a intentar hacer esto. No siempre funciona. Pero esto es mucho más sencillo que
introducir los datos “a capón” utilizando la instrucción SQL Insert que ya veremos más adelante.
SQLServer es bastante más dócil que Oracle para usar el método AddNew.
A este respecto, hay que citar la propiedad CursorLocation que veremos más adelante. Si creamos un
cursor lado cliente, seguramente nos permitirá utilizar más opciones (entre ellas AddNew) que si lo
establecemos de lado servidor. Tenga en cuenta que si usa un cursor lado cliente, el recordset no se
actualiza cuando otro usuario realiza modificaciones en la base.
Modificar datos mediante EDIT
En ADO no hace falta usar Edit para modificar los datos del registro actual. Edit no existe en ADO .
Para modificar un dato basta con poner el mismo código que utilizábamos en DAO, pero sin comenzar
por la línea Mirecordset.Edit. Colocándonos en el registro a modificar pondremos:
MiRecordset!Alumno_Nombre = “Pedro”
MiRecordset!Alumno_Ape1 = “Perez”
MiRecordset.Update
De cualquier forma, esto tampoco tiene porque funcionar en todas las bases de datos. En ese caso
tendremos que recurrir, al igual que para un registro nuevo, a las instrucciones SQL, que en este caso
será Update. Pero ya lo veremos más adelante. Hasta ahora solamente he querido usar el código
más simple para que pueda empezar con ADO, y sobre todo, para que vea que esta es una técnica
completamente accesible, aunque, dadas las grandes prestaciones que tiene, un poco más adelante se
va a complicar algo.
Ya ha visto que podemos trabajar perfectamente con recordsets, tal como lo hemos hecho con el DAO
de toda la vida. Pero ya lo comentábamos al principio, parece que hay que adornar lo obvio para que no
lo parezca tanto. Y ahí viene el Objeto Command, que como habrá podido ver en la figura de la Jerarquía
de los objetos ADO, es un objeto que aún no sabemos lo que hace.
El objeto Command lo que va a hacer es crear un recordset. O también, meter “a capón” un nuevo
registro, o borrarlo, utilizando directamente instrucciones SQL. Hay que darse cuenta que ADO trabaja
con una gran diversidad de bases de datos, y no todas trabajan igual. Por eso, muchas veces fallan
operaciones tan sencilla como añadir un nuevo registro con el método AddNew del recordset
MiRecordset.AddNew
Y hay que emplear una instrucción SQL: INSERT
En estos casos, en ADO utilizamos el método EXECUTE sobre el objeto Connection. Creamos una
variable, StrIntroducir, con el contenido de la instrucción SQL y ejecutábamos esa instrucción mediante
Execute
StrIntroducir = "Insert Into INT_DOCUMENTOS " _
& "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC,” _
& “L_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC)"_ &
"Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & "','" & TbTitulo.Tag _
& "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)"
ConexBDPrensa.Execute StrIntroducir
Esta línea (StrIntroducir) es el contenido de la propiedad CommandText de un objeto Command de ADO.
Ni más ni menos que una instrucción que queremos realizar sobre la BD. Un objeto Command tiene
pocas cosas más. Como objeto ADO que es tiene sus propiedades y métodos. Pero en esencia es lo
que acaba de ver con la instrucción EXECUTE del objeto Connection. Lo que pasa, que ADO lo han
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 403
hecho muy organizado, y por eso tiene la categoría de Objeto. Es hacer lo mismo, utilizando las mismas
expresiones, pero dándole más cuerpo.
Con la instrucción anterior, lo que hacíamos era añadir un registro. Si lo que queremos hacer es crear
un recordset, la instrucción SQL comenzaría por “Select * From ….” Y el método EXECUTE devolvería
un Recordset
StrIntroducir = “Select * From Alumnos Where Apellido1 = ‘Suarez’”
Podemos crear un recordset (MiRecordset, previamente declarado como tal) con esta instrucción
MiRecordset = ConexBDPrensa.Execute StrIntroducir
O con estas otras
Set MiComando as New ADODB.Command
MiComando.ActiveConnection = ConexBDPrensa
MiComando.CommandText = “Select * From Alumnos Where Apellido1 = ‘Suarez’”
MiRecordset = MiComando.Execute
Verá el ejemplo completo al final del capítulo.
Ahora, tras la explicación informal de cómo se crea una conexión y un recordset en ADO, y que es un
Command, vamos a entrar a conocer sus propiedades y métodos. Al final, y con un buen ejemplo
realizado de varias formas, entenderá perfectamente la forma de trabajar con ADO.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 404
ADO. El Objeto Connection
Un objeto Connection representa una conexión abierta con un origen de datos. Ya hemos visto como
crear un objeto Connection, por lo que vamos a pasar directamente a ver sus
objetos, colecciones, propiedades y métodos.
Como puede verse en la figura, el Objeto Connection tienen los objetos Command
y Recordset, y la colección Errors.
El Objeto Recordset es el recordset de toda la vida: un conjunto de registros que
contienen datos. El Objeto Recordset, aunque pertenece al objeto Connection,
puede crearse sin que exista previamente un objeto Connection. Esta es una de las propiedades de los
objetos ADO: no necesita cumplir estrictamente con la jerarquía.
El Objeto Command es una definición de un comando específico que se piensa ejecutar contra un
origen de datos. Los objetos Command sirven para tener almacenadas operaciones de acceso a datos y
usarlas en el momento adecuado, simplemente citándolas. Lo que obtenemos de un objeto Command
es, o un recordset (verá que no merece la pena usar un objeto Command para crear un recordset,
puesto que se pueden crear directamente) o una operación que afecte a los registros de la base de
datos (añadir registros, borrarlos, si es que no se deja hacer eso mediante recordsets)
La Colección Errors es el conjunto de errores generados por el proveedor de datos ante el fallo de una
operación de acceso. La colección Errors se refiere únicamente a los errores generados por el
proveedor, no a los fallos interceptables producidos por el programa, que deben ser tratados de la forma
habitual: mediante Err
Propiedades del Objeto Connection (Lea esto de las propiedades sin complicarse demasiado la vida.
Las realmente importantes verá que están advertidas debidamente)
Las propiedades del objeto Connection dependen de cada proveedor. No todos se comportan de igual
forma, por lo que cada propiedad debe condicionarse a si el proveedor es capaz de ofrecerla.
Propiedad Attributes
Es un Long. Acepta dos valores o la suma de los dos:
adXactCommitRetaining
adXactAbortRetaining
Estos atributos condicionan el modo de operación de la conexión con los métodos CommitTrans y
RollBackTrans.
Propiedad CommandTimeout
Indica, en segundos, el intervalo de espera para que se ejecute un comando (Objeto Command) antes
de que finalice el intento y se genere un error. Es un Long. El valor predeterminado es 30.
Propiedad ConnectionTimeout
Indica, en segundos, el intervalo de espera para establecer una conexión antes de que finalice el intento
y se genere un error. Es un Long y el valor predeterminado es 15.
Propiedad ConnectionString (IMPORTANTE)
Es una cadena de caracteres que contiene la información que se utiliza para establecer una conexión a
un origen de datos. (Vea la explicación amplia más atrás)
La cadena de conexión tiene varios argumentos, todos ellos separados por un punto y coma (;) de la
forma
argumento1 = valor; argumento2 = valor; argumento3 = valor etc.
ADO procesa solamente cuatro argumentos: Provider, File Name, Remote Provider y Remote Server.
Los demás argumentos los pasa al proveedor para que el los procese (Usuario, Password, etc)
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 405
Si al emplear el método Open se utiliza el parámetro Connection String, este parámetro utilizado en el
método Open sustituirá a cualquier otro existente anteriormente. Una vez abierta la conexión, esta
propiedad no se puede cambiar puesto que es solamente de lectura.
Los argumentos File Name y Provider son excluyentes.
Propiedad CursorLocation (IMPORTANTE)
Establece o devuelve la posición de un servicio de cursores. Es un Long, y acepta las siguientes
constantes:
AdUseNone No se usan servicios de cursor. (Esta constante es obsoleta y aparece
únicamente por compatibilidad con versiones anteriores.)
AdUseClient Usa cursores del lado del cliente.
AdUseServer Predeterminado. Usa cursores del lado servidor.
Esta propiedad parece que no dice nada. Y es sumamente importante.
Los cursores son, por decirlo de alguna manera, los mecanismos de la base de datos donde se crean los
recordsets. Se estará dando cuenta que las bases de datos que tienen cursores son ya bases de datos
con mecanismos propios para la creación de recordsets. (SQL Server u Oracle, p.e.) Estas bases de
datos trabajan como aplicaciones cliente – servidor. Tienen en el servidor, aparte de los datos, la
mayoría de sus recursos. En el cliente tienen prácticamente los recursos de conectividad, y poco más.
Esta conectividad permite enviar desde el cliente una petición a la base de datos alojada en el servidor.
Esa petición será el resultado por ejemplo, de una sentencia SQL. Al recibirla el servidor, gestionará la
obtención de los resultados y una vez que los haya conseguido viene su primera duda: ¿Dónde los
almaceno? Puede almacenarlos en el servidor, y cada vez que necesitemos un nuevo registro, por
ejemplo al ejecutar la sentencia MiRecordset.MoveNext, el cliente se lo indica al servidor y este le envía
el nuevo registro. También puede almacenar los datos obtenidos en el cliente, y de esta forma el cliente
puede moverse con entera libertad a lo largo de los registros del recordset. Puede hasta contarlos y
saber en que posición está. La diferencia entre uno y otro sistema es que en el primer caso el tráfico por
la red es mínimo (solamente se envía la información estrictamente necesaria) y en el segundo caso, se
envía mucha información de un golpe, la correspondiente a todos los registros del recordset,
independientemente de si se va a usar en el servidor o no.
Considerando el tráfico generado, parece que es mejor crear los cursores en el lado servidor. Pero esto
trae también sus dificultades. Nos priva de muchas propiedades del recordset. Una propiedad muy
usada, AbsolutePosition, no la tienen los cursores de lado servidor, circunstancia que no nos debe
sorprender, ya que al no estar todos los registros en el cliente, éste, aunque disponga de todos los datos
guardados en todos los campos de un determinado registro, no puede saber que posición ocupa ese
registro dentro de la totalidad de registros del recordset. Por lo tanto, usar cursores de lado cliente o lado
servidor será siempre una decisión a tomar dependiendo de la velocidad de la red, de la memoria
disponible en el cliente, de la complejidad del programa, etc.
Recuerde que por defecto, ADO crea cursores de lado servidor. Para que la conexión le cree todos los
cursores de lado cliente basta ejecutar la instrucción:
MiConexion.CursorLocation = adUseClient
Si desea hacer transacciones, deberá crear cursores del lado servidor, ya que los de lado cliente no las
admiten. Comprenderá según vaya programando y encontrándose con problemas, que esta propiedad
es absolutamente importante.
Este valor debe establecerlo antes de crear la conexión. De esta forma, todos los cursores creados con
esa conexión serán de lado cliente o lado servidor, según haya elegido. Pero muchas veces sería ideal
que unos recordsets tuvieran el cursor de un tipo y otros de otro. Los recordsets también tienen esta
propiedad, por lo que puede elegir el lado deseado para cada recordset utilizando esta propiedad
aplicada no a la conexión, sino al recordset.
El número de registros que el servidor envía al cliente, cuando el cursor es de lado servidor, se controla
mediante la propiedad CacheSize del recordset. Lo verá más adelante.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 406
Propiedad DefaultDatabase
Establece la base de datos predeterminada para un objeto Connection. Es un string con el nombre de la
base de datos por defecto de esa conexión. Solamente es válida con aquellos proveedores que permiten
varias bases de datos por conexión.
IsolationLevel
Esta propiedad afecta al comportamiento de un objeto Connection durante una transacción. Una vez
establecida esta propiedad, solamente será efectiva cuando se invoque el método BeguinTrans. Vea la
ayuda para mayor información de los valores posibles.
Propiedad Mode,
Establece los permisos disponibles para modificar datos en un objeto Connection.
Los valores aceptados son:
AdModeUnknown
Predeterminada. Indica que los permisos no se han establecido aún o
que no se pueden determinar.
Indica que son permisos de sólo lectura.
AdModeRead
Indica que son permisos de sólo escritura.
AdModeWrite
Indica que son permisos de lectura/escritura.
AdModeReadWrite
Impide que otros abran una conexión con permisos de lectura.
AdModeShareDenyRead
Impide que otros abran una conexión con permisos de
AdModeShareDenyWrite
escritura.
AdModeShareExclusive
Impide que otros abran una conexión.
Impide que otros abran una conexión con cualquier tipo de
AdModeShareDenyNone
permiso.
Sólo puede establecer la propiedad Mode cuando el objeto Connection está cerrado. Cuando se usa en
un objeto Connection del lado del cliente, la propiedad Mode sólo se puede establecer a
adModeUnknown.
Propiedad Provider
Es un string que indica el nombre del proveedor de un objeto Connection. Si no se especifica ningún
proveedor, la propiedad tendrá el valor predeterminado MSDASQL (Proveedor de Microsoft OLE DB
para ODBC).
Propiedad State
Devuelve el estado del objeto Connection: abierto (adStateOpen = 1) o cerrado (adStateClosed = 0).
Propiedad Version
Devuelve el número de versión de ADO. Es un String.
Métodos del Objeto Connection
Métodos BeginTrans, CommitTrans y RollbackTrans
Estos métodos de transacción administran el proceso de la transacción dentro de un objeto Connection
de la forma siguiente:
BeginTrans: inicia una nueva transacción.

LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 407
CommitTrans: guarda las modificaciones y termina la transacción actual. También puede iniciar
una nueva transacción.

RollbackTrans: cancela las modificaciones efectuadas durante la transacción actual y termina la
transacción. También puede iniciar una nueva transacción.

Después de invocar el método BeginTrans, el proveedor ya no aplicará inmediatamente las
modificaciones hasta que invoque CommitTrans o RollbackTrans para terminar la transacción. Los
métodos BeginTrans, CommitTrans y RollbackTrans no están disponibles en los objetos Connection
del lado del cliente.
Método Cancel
Cancela la ejecución de una llamada asíncrona pendiente a un método Execute u Open.
Sintaxis
NombreConection.Cancel
El método Cancel se utiliza para terminar la ejecución de una llamada asíncrona a un método Execute o
Open (es decir, el método fue invocado con la opción adAsyncConnect, adAsyncExecute o
adAsyncFetch). Cancel devolverá un error de ejecución si no se utilizó adAsyncExecute en el método
que quiere terminar.
Close, método
Cierra el objeto Connection.
Sintaxis
NombredelObjetoConnection.Close
El cierre de un objeto Connection mientras hay objetos Recordset abiertos en la conexión cancela las
modificaciones pendientes en todos los objetos Recordset. El cierre explícito de un objeto Connection
(llamando a su método Close) mientras una transacción está en progreso genera un error. Si un objeto
Connection cae fuera del alcance mientras la transacción está en progreso, ADO cancela
automáticamente la transacción.
El cierre de un objeto Connection no lo elimina de la memoria; puede modificar los valores de sus
propiedades y volver a abrirlo más tarde. Para eliminar completamente un objeto de la memoria,
establezca la variable de objeto a Nothing.
Set NombredelObjetoConnection = Nothing
Método Execute (Vea también Método Execute para el objeto Command)
Ejecuta una consulta, instrucción SQL, procedimiento almacenado especificados o texto específico del
proveedor.
Sintaxis (Para una cadena de comando que no devuelva filas):
conexión.Execute CommandText , RecordsAffected , Options
(Para una cadena de comando que devuelva filas):
Set MiRecordset = connection.Execute (CommandText , RecordsAffected , Options )
(MiRecordset debe ser una variable declarada tipo ADODB.Recordset)
CommandText Es un String que contiene la instrucción SQL, el nombre de la tabla, el procedimiento
almacenado o el texto específico del proveedor que se va a ejecutar.
RecordsAffected Opcional. Una variable Long en la que el proveedor devuelve el número de registros
afectados por la operación.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 408
Options Opcional. Una constante o valor Long que indica cómo debe evaluar el proveedor el argumento
CommandText . Puede ser uno de los siguientes valores.
Constante
adCmdText
adCmdTable
adCmdTableDirect
adCmdTable
adCmdStoredProc
adCmdUnknown
adAsyncExecute
adAsyncFetch
Descripción
Indica que el proveedor tiene que evaluar CommandText como
definición textual de un comando, como una instrucción SQL.
Indica que ADO tiene que generar una consulta SQL para devolver
todas las filas de la tabla mencionada en CommandText .
Indica que el proveedor tiene que devolver todas las filas de la tabla
mencionada en CommandText .
Indica que ADO tiene que generar una consulta SQL para devolver
todas las filas de la tabla mencionada en CommandText .
Indica que el proveedor tiene que evaluar CommandText como
procedimiento almacenado.
Indica que el tipo de comando en CommandText es desconocido.
Indica que el comando se tiene que ejecutar de forma asíncrona.
Indica que el resto de las filas siguientes a la cantidad inicial
especificada en la propiedad CacheSize tiene que ser recuperada
de forma asíncrona.
Cuando esta operación termina se genera el evento ExecuteComplete.
(IMPORTANTE)
Método Open
Abre una conexión a un origen de datos.
Sintaxis
MiConnection.Open ConnectionSTring , UserID , Password, Options
MiConnection.Open
Los parámetros ConnectionSTring, UserID, Password, Options puede introducirlos previamente a abrir la
conexión, y utilizar la segunda sintaxis cuando desee abrirla realmente. Estos parámetros se le pasan en
la cadena de conexión:
ConexBDPrensa.ConnectionString = "Provider=MSDAORA.1;User ID=INTRANET;” & _
“Password=INTRANET;Data Source=intranet;Persist Security Info=False"
Options Opcional. Puede ser una de las constantes siguientes:
AdConnectUnspecified Abre la conexión de forma sincronía
AdAsyncConnect
Abre la conexión de forma asíncrona
Cuando se usa un objeto Connection del lado del cliente, el método Open no establece realmente una
conexión con el servidor hasta que se abre un Recordset del objeto Connection.
Colecciones del Objeto Connection
Colección Errors
Contiene todos los objetos Error creados en respuesta a un único fallo relacionado con el proveedor.
Cada objeto Error representa un error específico del proveedor, no un error ADO. Los errores ADO se
exponen al mecanismo de control de excepciones en tiempo de ejecución. Por ejemplo, en Microsoft
Visual Basic, cuando ocurre un error específico de ADO dispara un evento On Error y aparece en el
objeto Err.
Cuando otra operación ADO genera un error, se borra la colección Errors y el nuevo conjunto de objetos
Error se coloca en la colección Errors. Las operaciones ADO que no generan un error no tienen ningún
efecto sobre la colección Errors. Para borrar manualmente la colección Errors utilice el método Clear.
Cada objeto Error de la colección, nos dará información sobre un error producido en la conexión. Sus
propiedades son las siguientes:
Description: Contiene la descripción del error producido (String).
NativeError: Indica el error devuelto por la base de datos (Long).


LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 409
Number: Es el código de error (Long).
Source: Indica el nombre del objeto o aplicación que ha generado el error (String).
SQLState: Indica el error SQL estándar asociado.(String).
Debido a que este objeto será de gran utilidad a continuación se incluye un ejemplo de su uso.
Ejemplo del tratamiento de errores:
El resultado de la ejecución es el siguiente:
Private Sub CBConexion_Click()
Dim MiConex1 As ADODB.Connection
Dim MiError As ADODB.Error
On Error GoTo RutErr
Set MiConex1 = New ADODB.Connection
MiConex1.ConnectionString = "Provider=MSDAORA.1;Password=tiger;User
ID=EScot;Data Source=MADRID;Persist Security Info=True"
MiConex1.Open
Exit Sub
RutErr:
For Each MiError In MiConex1.Errors
MsgBox ("Error VB:" & MiError.Number & vbCrLf _
& "Error Oracle:" & MiError.NativeError & vbCrLf _
& "Error SQL:" & MiError.SQLState & vbCrLf _
& "Generado Por:" & MiError.Source & vbCrLf _
& "Descripción:" & MiError.Description)
Next
End Sub



Como
puede
observ
arse,
alguna
s
de
las
propiedades no devuelven los valores esperados: NativeError vale 0 cuando debería valer –1017, que es
el error asociado de Oracle. Aún así podemos capturar el código del error desde la cadena de caracteres
description. Con este comentario se pretende sugerir que se realicen pruebas con el proveedor de
datos que vayamos a utilizar para conocer su comportamiento respecto a este objeto error y dónde nos
devuelve los códigos.
Observese en el código que la declaración de MiError se hace con ADODB.Error
Colección Properties
Es el conjunto de objetos Property
Objeto Property
Un objeto Property representa una característica dinámica de un objeto ADO que está definida por el
proveedor.
Los objetos ADO tienen dos tipos de propiedades: intrínsecas y dinámicas.
Las propiedades intrínsecas son aquellas propiedades implementadas en ADO e inmediatamente
disponibles para cualquier nuevo objeto, utilizando la sintaxis Objeto.Propiedad. No aparecen como
objetos Property en la colección Properties de un objeto, de forma que aunque puede modificar sus
valores, no puede modificar sus características.
Las propiedades dinámicas están definidas por el proveedor de los datos y aparecen en la colección
Properties del objeto ADO apropiado. Por ejemplo, una propiedad específica del proveedor puede
indicar si un objeto Recordset acepta transacciones o actualizaciones. Estas propiedades adicionales
aparecerán como objetos Property en la colección Propiedades de dicho objeto Recordset. A las
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 410
propiedades dinámicas se les puede hacer referencia sólo a través de la colección, utilizando la sintaxis
Objeto.Properties(0) u Objeto.Properties("Name").
Un objeto Property dinámico tiene cuatro propiedades incorporadas propias:
La propiedad Name es una cadena que identifica la propiedad.
La propiedad Type es un entero que especifica el tipo de datos de la propiedad.
La propiedad Value es un variant que contiene el valor de la propiedad.
La propiedad Attributes es un valor Long que indica características de la propiedad específicas
del proveedor.




El Objeto Recordset de ADO
El objeto Recordset representa un conjunto de registros. El recordset en ADO puede crearse abriéndolo,
tomando todos los registros de una tabla o seleccionándolos con una consulta SQL, o ejecutando un
comando que contienen el nombre de esa tabla o la consulta. En un momento determinado, el objeto
Recordset sólo hace referencia a un único registro dentro del conjunto de registros, llamado registro
actual.
Propiedades del Objeto Recordset
El recordset de ADO tiene propiedades iguales al recordset de DAO, pero tienen otras que no tienen el
de DAO. Se van a estudiar todas, profundizando más en las que son particulares del recordset ADO.
Propiedad AbsolutePosition (ADO)
Especifica la posición ordinal del registro actual de un objeto Recordset. Esta propiedad devuelve un
Long con el número de orden del registro. Es posible que el recordset no acepte esta propiedad,
dependiendo del proveedor de datos, y del tipo de cursor (lado cliente o lado servidor. El cursor tipo
lado servidor no permite esta propiedad) Esta propiedad devolverá 1 cuando el registro actual sea el
primer registro del recordset.
Propiedades BOF y EOF
Indican si la posición del puntero del Recordset está apuntando a un registro anterior al primero (BOF =
True) o posterior al último (EOF = True). Esta propiedad siempre la podremos mirar,
independientemente si el cursor es lado cliente o lado servidor.
Propiedad ActiveConnection (ADO)
Indica a qué objeto Connection pertenece actualmente el objeto Recordset especificado. Devuelve un
string con el nombre del objeto Connection.
Propiedad Bookmark
Devuelve un marcador que identifica unívocamente al registro actual de un objeto Recordset o establece
el registro actual de un objeto Recordset al registro identificado por un marcador válido. El valor del
Bookmark hay que introducirlo en una variable tipo Variant.
La propiedad Bookmark solo podrá establecerse cuando el proveedor lo permita. Puede utilizarse el
método Supports para averiguarlo. Cuando el recordset es de lado cliente, siempre está disponible el
Bookmark.
Propiedad CacheSize
Indica el número de registros del objeto Recordset que están en la memoria caché local. Es un Long de
lectura y escritura. El valor predeterminado es 1.
Esta propiedad nos permite conocer cuantos registros están en la memoria local. Si ponemos esta
propiedad por ejemplo a 10, al abrir la primera vez el objeto Recordset, el proveedor recupera los 10
primeros registros en la memoria local. A medida que se desplaza por el objeto Recordset, el proveedor
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 411
devuelve los datos desde el búfer de memoria local. Tan pronto como pasa del último registro de la
memoria caché, el proveedor recupera los 10 registros siguientes desde el origen de datos y los carga
en la memoria caché.
Los registros recuperados desde la memoria caché no reflejan los cambios concurrentes que hagan
otros usuarios en el origen de datos. Para forzar una actualización de todos los datos en la memoria
caché, debe usarse el método Resync.
Propiedad MaxRecords
Indica el número máximo de registros que se devuelven a un Recordset desde una consulta. Es un Long
y el valor predeterminado es 0, que significa sin límite (Obtienen todos los registros). Esta propiedad es
de lectura y escritura cuando el recordset está cerrado, y solamente de lectura cuando está abierto.
Esta propiedad debe usarse solamente cuando se prevé que se pueden obtener un número muy grande
de registros. Es prudente tomar medidas frente a aquellas operaciones en las que el ordenador pueda
meterse en un proceso excesivamente largo o que ocupe más recursos de los disponibles. Estas cosas
son las que suelen “colgar” al ordenador y en las que es muy frecuente echarle luego la culpa a Windows
Si estamos frente a una base de datos con todos los datos de los afiliados a la Seguridad Social, no es
del todo prudente crear un recordset mediante esta sentencia:
SELECT * From Afiliados Where Apellido1 = ‘Fernandez’
Incluso las hay peores:
SELECT * From Afiliados
A nadie se le ocurriría, pero puede surgir involuntariamente cuando ese acceso se realiza desde un
puesto de operación público (Acceso desde Internet por ejemplo). Con la propiedad MaxRecords puede
limitar el número de registros obtenidos. Posiblemente no llegue a obtener el dato deseado, y se vea en
la obligación de realizar la misma consulta sucesivas veces hasta encontrarlo.
Propiedad CursorLocation
Establece o devuelve la posición de un servicio de cursores. Es idéntica a la propiedad del mismo
nombre vista más atrás con todo detalle para el objeto Connection.
Propiedad CursorType
Indica el tipo de cursor que se usa en un objeto Recordset. Es de lectura y escritura si el recordset está
cerrado, y solo de lectura si está abierto. Puede tomar uno de los siguientes valores:
AdOpenForwardOnly Predeterminado. Idéntico a un cursor estático, excepto sólo permite
desplazarse hacia delante en los registros. Esto mejora el rendimiento en situaciones en las que
sólo se quiere pasar una vez por cada registro.
En muchas ocasiones es necesario moverse por el recordset hacia delante y hacia atrás. Este
tipo de cursor solamente permite moverse hacia delante. Tenga presente que este es el tipo
predeterminado.
AdOpenKeyset Cursor de conjunto de claves. Igual que un cursor dinámico, excepto que no se
pueden ver los registros que agregan otros usuarios, aunque los registros que otros usuarios
eliminan son inaccesibles desde su conjunto de registros. Los cambios que otros usuarios hacen
en los datos permanecen visibles.
AdOpenDynamic Cursor dinámico. Las incorporaciones, cambios y eliminaciones que hacen
otros usuarios permanecen visibles, y se admiten todo tipo de movimientos entre registros, a
excepción de los marcadores si el proveedor no los admite. Es el equivalente en DAO al tipo
Dynaset
AdOpenStatic Cursor estático. Una copia estática de un conjunto de registros que se puede
usar para buscar datos o generar informes. Las incorporaciones, cambios o eliminaciones que
hacen otros usuarios no son visibles. Es el equivalente en DAO al tipo Snapshot
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 412
NOTA. Si un proveedor no admite el tipo de cursor solicitado, el proveedor puede que devuelva otro tipo
de cursor. La propiedad CursorType cambiará para coincidir con el tipo de cursor en uso cuando el
objeto Recordset se abra. Para comprobar la funcionalidad específica del cursor devuelto, use el
método Supports. Cuando cierre el Recordset , la propiedad CursorType volverá a su configuración
original.
Propiedad LockType
Indica el tipo de bloqueo que se pone en los registros durante el proceso de edición. Establece también
si el recordset se actualiza registro a registro o por lotes. Este último sistema permite realizar varios
cambios en el recordset y mantenerlos en la caché durante cierto tiempo, y proceder a la actualización
de todos los cambios pendientes en una sola operación. Esto es muy importante cuando se está
trabajando con una base de datos situada en un servidor con un acceso lento (conexión vía Internet, por
ejemplo)
Los valores de la propiedad LockType pueden ser:
Predeterminado. Sólo lectura—no puede modificar los datos
AdLockReadOnly
Bloqueo pesimista, registro a registro: el proveedor hace lo necesario
AdLockPessimistic
para asegurar la modificación correcta de los registros, generalmente
bloqueando registros en el origen de datos durante todo el proceso de
modificación. Este valor solamente es válido si el cursor (Propiedad
CursorLocation) esta establecido a lado servidor.
AdLockOptimistic
Bloqueo optimista, registro a registro: el proveedor usa bloqueo
optimista, bloqueando registros sólo cuando llama al método Update.
Actualizaciones optimistas por lotes: requerido para el modo de
AdLockBatchOptimistic
actualización por lotes como contraposición al modo de
actualización inmediata.
Propiedad EditMode
Indica el estado de modificación del registro actual. Es solamente de lectura. Devuelve uno de las
siguientes constantes:
AdEditNone
Indica que no hay ninguna operación de modificación en ejecución.
AdEditInProgress
Indica que los datos del registro actual se han modificado pero que no
se han guardado.
AdEditAdd
Indica que se ha invocado el método AddNew y que el registro situado
actualmente en el búfer de copia es un nuevo registro que no se ha
guardado en la base de datos.
AdEditDelete
Indica que el registro actual se ha eliminado.
Propiedad Filter
Esta propiedad solamente la tienen los recordset ADO. Y es que ADO presupone que está obteniendo
datos de una base de datos alojada en un servidor y que la comunicación entre servidor y cliente puede
ser especialmente lenta. Mediante Filter puede descartar registros que no cumplan una determinada
condición. En realidad lo que hacemos mediante Filter es crear un nuevo Recordset a partir de otro
Recordset.
La propiedad Filter se utiliza también para actuar sobre determinados registros en varios métodos del
recordset (Resync, Save, …) pero no se va a explicar en este manual la ex plicación de la utilización de
esta propiedad en esos métodos, ya que el nivel del programador que utiliza esos recursos debe ser
elevado. Le reservamos por tanto la posibilidad de conocerlo directamente desde la ayuda de Visual
Basic, que en este caso es bastante buena.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 413
De momento lo que vamos a hacer con Filter es crear un nuevo recordset ¿Por qué no creamos
directamente el nuevo recordset utilizando una sentencia SQL que lleve implícito ese filtro?
Personalmente no me gusta utilizar la propiedad Filter, y prefiero crear un nuevo recordset. Creo que
solamente lo he usado para rellenar un MSHFlexGrid con parte de los datos del recordset que uso en
una parte de la aplicación. Veamos un ejemplo:
(MiConexion es una conexión ya creada)
Dim RsInicial As ADODB.Recordset
Dim RsFiltrado As ADODB.Recordset
Set RsInicial = New ADODB.Recordset
Set RsFiltrado = New ADODB.Recordset
RsInicial.Open "Autores", MiConexion, adOpenDynamic, adLockOptimistic
‘Este es el recordset que uso para muchas cosas dentro de la aplica ción. Ahora quiero presentar en un
MSHFlexGrid solamente los datos de los autores de nacionalidad española. Filtro el recordset anterior
utilizando un criterio de igualdad de un campo: Nacionalidad
RsFiltrado = RsInicial.Filter (“Nacionalidad = ‘Española’”)
‘Ahora ya podemos aplicar este recordset al MSHFlexGrid:
Set MSHFlexG1.Recordset = RsFiltrado
‘Y cuando queremos presentar todos los autores, basta con poner la línea:
Set MSHFlexG1.Recordset = RsInicial
Este es el único ejemplo que puedo sacar de todas mis aplicaciones. Seguro que el alumno va a ver más
aplicaciones de esta propiedad.
La propiedad Filter puede mostrar también aquellos registros que han sido manipulados recientemente,
mediante las constantes siguientes:
Quita el filtro actual y vuelve a poner todos los registros a la
vista.
AdFilterPendingRecords
Permite ver sólo los registros que han cambiado, pero que no
han sido enviados aún al servidor. Aplicable sólo para el modo
de actualización por lotes.
AdFilterNone
AdFilterAffectedRecords
Permite ver sólo los registros afectados por la última llamada a
Delete, Resync, UpdateBatch o CancelBatch
Permite ver los registros de la caché actual, es decir, los
AdFilterFetchedRecords
resultados de la última llamada para recuperar registros de la
base de datos
AdFilterConflictingRecords Permite ver los registros que fallaron en el último intento de
actualización por lotes.
Propiedad Index
Indica el nombre del índice que se utiliza actualmente en el Recordset. Es un String con el nombre del
índice.
El índice se utiliza para moverse a lo largo del recordset mediante el método Move. El índice ya debe
estar creado en la tabla de la base de datos.
Al utilizar un índice, el orden de los registros se cambia al orden establecido en ese índice. Por lo tanto,
los valores obtenidos anteriormente por la propiedad AbsolutePosition cambiarán completamente.
No todos los proveedores de datos aceptan la propiedad Index. Puede comprobarlo mediante el método
Supports.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 414
Propiedad MarshalOptions
Esta propiedad se usa cuando estamos trabajando con cursores lado cliente. En este caso, como
vimos más atrás, los registros del recordset están en el equipo cliente. Todas las operaciones realizadas
sobre el recordset se realizan en el cliente, por lo tanto llegará el momento en que habrá que actualizar
en el servidor los datos que hayamos modificado en el recordset que está en el equipo cliente. Mediante
esta propiedad podemos hacer que se envíen al servidor todos los registros (filas) o solamente los que
han cambiado. Acepta estas dos constantes:
AdMarshalAll
Predeterminada. Indica que todos los registros se devuelven al
servidor.
Indica que sólo los registros modificados se devuelven al
AdMarshalModifiedOnly
servidor.
Esta propiedad puede mejorar el rendimiento de la aplicación para aquellos casos en los que se use un
canal de comunicación lento.
Propiedad PageSize
Indica cuántos registros constituyen una página del objeto Recordset. Es de lectura y escritura. Devuelve
un Long y su valor predeterminado es 10.
Esta propiedad permite determinar cuántos registros componen una página lógica de datos. Al
establecer un tamaño de página, puede utilizar la propiedad AbsolutePage y se moverá al primer
registro de una página específica. Esto es útil en las situaciones de servidor Web cuando se desea
permitir que el usuario pase páginas de datos y vea cierto número de registros al mismo tiempo. Esta
propiedad se puede establecer en cualquier momento y su valor se utilizará para calcular la ubicación del
primer registro de una página específica.
Propiedad PageCount
Indica cuántas páginas de datos contiene el objeto Recordset. Es solamente de lectura. Devuelve un
Long. Si el objeto Recordset no admite esta propiedad, el valor será -1 para indicar que no se puede
determinar el valor de PageCount.
Propiedad AbsolutePage
Especifica en qué página reside el registro actual. Es de lectura y escritura. Devuelve un Long o una de
las siguientes constantes:
AdPosUnknown
El objeto Recordset está vacío, la posición actual se desconoce o el
proveedor no admite la propiedad AbsolutePage.
AdPosBOF
El puntero del registro actual está al comienzo del archivo (es decir, la
propiedad BOF tiene el valor True).
El puntero del registro actual está al final del archivo (es decir, la
AdPosEOF
propiedad EOF tiene el valor True).
Propiedad RecordCount
Indica el número actual de registros de un objeto Recordset. Devuelve un Long
Es posible que esta propiedad no la permita el proveedor de datos, o que no pueda llegar a averiguarse,
ya que dependiendo del tipo de cursor utilizado puede que no suministre ese dato.
Propiedad Source
Devuelve la tabla, consulta o sentencia SQL utilizado en el método Open para crear el recordset. Es un
String.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 415
Propiedad State
Indica el estado (abierto, cerrado, proceso de ejecución) en el que se encuentra el recordset. Devuelve
uno de los siguientes valores:
Constante
Descripción
Valor predeterminado. Indica que el objeto está
adStateClosed
cerrado.
Indica que el objeto está abierto.
adStateOpen
Indica que el objeto Recordset se está
adStateConnecting
conectando.
Indica que el objeto Recordset está ejecutando un
adStateExecuting
comando.
Indica que se está obteniendo el conjunto de filas
adStateFetching
del objeto Recordset.
Puede tener una combinación de valores. Por ejemplo, si se está ejecutando una instrucción, esta
propiedad tendrá un valor combinado de adStateOpen y adStateExecuting.
Propiedad Status
Esta propiedad se refiere al registro actual. Indica el estado de este registro respecto a las operaciones
de actualización por lotes u otras operaciones masivas. No es una propiedad que se use todos los días.
Vea la ayuda para mas detalles.
Propiedades dinámicas del objeto recordset
Las propiedades anteriores se refieren a propiedades del recordset que se refieren a unas
características propias del recordset una vez creado. Son estas:
Unique Table, Unique Schema y Unique Catalog
Unique Table especifica la tabla sobre la que se permite realizar modificaciones de datos (Insertar o
actualizar), en el caso de que el recordset se haya creado mediante una operación JOIN
Unique Schema indica el nombre del propietario de la tabla
Unique Catalog indica el nombre de la base de datos a la que pertenece la tabla. Estas dos últimas
propiedades deben tener un valor para poder poner valor a la propiedad Unique Table. Estas
propiedades son tipo String
Estas propiedades dinámicas se anexan a la colección Properties del objeto Recordset al asignar el
valor adUseClient a la propiedad Cursor Location.
Métodos del objeto Recordset de ADO
METODO Supports
Este método es muy útil para ver si un recordset acepta una determinada funcionalidad. Devuelve un
Booleano y es solamente de lectura. De esta forma puede consultar si un recordset admite el método
MoveFirst, la propiedad AbsolutePosition, Bookmark, etc., antes de invocar ese método o leer esa
propiedad, y evitar de esta forma un error en la ejecución. Esto es muy útil habida cuenta que no todos
los proveedores funcionan de la misma forma. Es por lo tanto muy prudente consultar si el Recordset
soporta una funcionalidad antes de pedírsela.
Estas funcionalidades se le pasan como parámetro mediante una de las siguientes constantes:
AdAddNew
Puede usar el método AddNew para agregar nuevos registros.
AdApproxPosition
Puede leer y establecer las propiedades AbsolutePosition y
AbsolutePage.
Puede usar la propiedad Bookmark para tener acceso a registros
AdBookmark
específicos
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 416
AdDelete
Puede usar el método Delete para eliminar registros.
AdHoldRecords
Puede recuperar más registros o cambiar la posición de recuperación
siguiente sin efectuar todos los cambios pendientes.
Puede usar los métodos MoveFirst y MovePrevious, y los métodos
AdMovePrevious
Move o GetRows para desplazar hacia atrás la posición del registro
actual sin que se requiera marcadores.
AdResync
Puede usar el método Resync para actualizar el cursor con los datos
visibles en la base de datos subyacente.
Puede usar el método Update para modificar datos existentes.
AdUpdate
Puede usar actualización por lotes (métodos UpdateBatch y
AdUpdateBatch
CancelBatch) para transmitir grupos de cambios al proveedor.
Puede utilizar la propiedad Index para dar nombre a un índice.
AdIndex
Puede utilizar el método Seek para encontrar una fila en un Recordset.
AdSeek
En este ejemplo vemos la sintaxis de Supports:
If RsSeg.Supports(adApproxPosition) = True Then
MsgBox "SI"
Else
MsgBox "NO"
End If
Nota Aunque el método Supports puede devolver True para una funcionalidad determinada, eso no
garantiza que el proveedor pueda hacer que la característica esté disponible bajo cualquier
circunstancia. El método Supports devuelve simplemente si el proveedor puede admitir la funcionalidad
especificada, dando por supuesto que se reúnen determinadas condiciones. Por ejemplo, el método
Supports puede indicar que un objeto Recordset admite actualizaciones aunque el cursor se base en
una unión de múltiples tablas, de las que algunas columnas no son actualizables.
El valor devuelto por el método Supports dependerá del tipo de recordset elegido. En la siguiente tabla
puede ver el tipo de recordset y las constantes para las que va a devolver True:
AdOpenForwardOnly
AdOpenKeyset
AdOpenDynamic
AdOpenStatic
Ninguna
adBookmark, adHoldRecords, adMovePrevious, adResync
AdMovePrevious
adBookmark, adHoldRecords, adMovePrevious, adResync
Método Open
Es el método que A B R E el recordset. Este método es el que busca los registros que han de rellenar el
recordset.
Sintaxis. Esta es la sintaxis general:
MiRecordset.Open Source , ActiveConnection , CursorType , L o c k T y p e , Options
Un recordset puede abrirse partiendo de una conexión ya abierta. Pero también puede crearse
directamente, sin abrir previamente la conexión. Al final, deberá aportar todos los datos necesarios para
determinar en que base de datos se abre ese recordset. Sobre que tabla, consulta o sentencia SQL.,
que tipo de cursor va a ser, etc. Lo que ocurre es que ADO es muy flexible y nos permite hacerlo de
varias formas, aunque todas ellas conducen a lo mismo.
Source (Opcional) Es el nombre de una tabla, consulta o sentencia SQL de la cual se obtienen los
registros del Recordset.
ActiveConnection (Opcional). Es el nombre de un objeto Connection abierto o una cadena de conexión
válida. Esta cadena es la misma que la que emplearíamos para abrir el objeto Connection.
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 417
CursorType (Opcional). Un valor que determina el tipo de cursor que el proveedor debe usar al abrir el
Recordset. Puede ser una de las siguientes constantes
AdOpenForwardOnly
AdOpenKeyset
AdOpenDynamic
DAO)
AdOpenStatic
(Predeterminado) Abre un cursor de tipo sólo avance.
Abre un cursor de tipo conjunto de claves.
Abre un cursor de tipo dinámico. (Igual que el Dynaset de
Abre un cursor de tipo estático.
LockType (Opcional). Un valor que determina el tipo de bloqueo que debe usar el proveedor al abrir el
Recordset. Con este parámetro se le indica también si debe hacer las actualizaciones registro a registro
o en bloque. Puede ser una de las siguientes constantes
(Predeterminado) Sólo lectura. No puede modificar los datos.
AdLockReadOnly
Bloqueo pesimista, registro a registro. El proveedor hace lo
AdLockPessimistic
necesario para asegurar una modificación correcta de los
registros, normalmente bloqueando registros en el origen de
datos inmediatamente antes de la modificación.
AdLockOptimistic
Bloqueo optimista, registro a registro. El proveedor usa
bloqueooptimista, bloqueando registros sólo cuando se llama al
método Update.
Actualizaciones optimistas por lotes. Requeridas en el
AdLockBatchOptimistic
modo de actualización por lotes en oposición al modo
de actualización inmediata. (Actualización en bloque)
Options (Opcional). Constante que determina como va a evaluar el proveedor de datos el argumento
Source . Puede ser una de las siguientes constantes de esta lista.
AdCmdText Indica que el proveedor debe evaluar Source como una definición
textual de un comando.
AdCmdTable Indica que ADO debe generar una consulta SQL para devolver
todaslas filas de la tabla nombrada en Source .
Indica que el proveedor debe devolver todas las filas de la
AdCmdTableDirect
tabla nombrada en Source .
Indica que el proveedor debe evaluar Source como un
AdCmdStoredProc
procedimiento almacenado
AdCmdUnknown
Indica que el tipo de comando del argumento Source es
desconocido.
AdCmdFile
Indica que el Recordset guardado se debe restaurar desde el
archivo nombrado en Source .
Indica que Source se debe ejecutar de forma asíncrona.
AdAsyncExecute
Indica que, tras alcanzar la cantidad inicial especificada en la
AdAsyncFetch
propiedad Initial Fetch Size, las filas restantes deben buscarse de
forma asíncrona. Si se requiere una fila que no se
ha encontrado, se
bloqueará el subproceso principal hasta que
se disponga de la fila solicitada.
AdAsyncFetchNonBlocking Indica que el subproceso principal nunca se bloquea
durante la búsqueda. Si no se encuentra la fila
solicitada, la fila actual se desplaza automáticamente
al final del archivo.
Habrá observado que hemos remarcado que el método Open ABRE un recordset. No lo crea. El
recordset debe estar creado previamente. ¿Qué cuando se crea? Mediante la instrucción:
Set MiRecordset = New ADODB.Recordset
Metodo Requery
Actualiza los datos de un objeto Recordset volviendo a ejecutar la consulta utilizada para abrirlo. Se
obtiene el mismo resultado que si se cerrara el recordset y se volviera a abrir.
Sintaxis
LSB
MiRecordset.Requery Opciones
Visual Basic – Guía del Estudiante
Capítulo 1
Página 418
Optiones Opcional. Máscara de bits que indica opciones que afectan a esta operación. Si el valor de
este parámetro está establecido a adAsyncExecute, esta operación se ejecutará de forma asíncrona y
se emitirá un evento RecordsetChangeComplete cuando concluya.
Método Resync
Actualiza los datos del objeto Recordset actual. Este método, a diferencia del método Requery, no
vuelve a ejecutar el comando de creación del recordset, sino que lee los registros existentes en el
recordset para actualizar su valor, pero no presenta aquellos registros que hubieran sido creados con
posterioridad a la apertura del recordset. Es más rápido que el método Requery, y en muchos casos
solamente nos interesa actualizar los registros sobre los que estamos trabajando.
Sintaxis
MiRecordset.Resync AffectRecords, ResyncValues
Los parámetros AffectRecords y ResyncValues determinan que registros se van a volver a leer y
sobreescribir. Vea la ayuda para mas detalles.
METODO AddNew
Crea un nuevo registro en un objeto Recordset actualizable.
Sintaxis
NombreDelRecordset. AddNew FieldList , Values
Los parámetros FieldList y Values son opcionales. En caso de ponerlos, FieldList serán los nombres de
los campos a los que se les va a poner un valor, y Values son los valores de cada uno de estos campos.
El orden nombre - valor debe mantenerse estrictamente.
Siempre recomendaré que, en vez de meter los datos mediante estos parámetros, se metan
posteriormente linera a línea, tal como se hizo siempre con los recordsets
NombreDelRecordset!NombredelCampo = ValorDelCampo
ó
NombreDelRecordset(“NombredelCampo”) = ValorDelCampo
Esta segunda forma es necesaria cuando el nombre del campo tiene espacios. Nunca es recomendable
poner espacios en los nombres de campos, pero en caso de que existan, debe optar por utilizar la
sintaxis segunda, con los paréntesis y comillas dobles.
No siempre se puede utilizar el método AddNew. Puede comprobar si se puede utilizar, usando el
método Supports visto anteriormente.
El método AddNew convierte a este registro recién creado en registro actual. Pero este registro
solamente existe en el recordset. Para introducir los datos en la base de datos, (Y por lo tanto en el disco
duro) es necesario invocar el método Update una vez introducidos todos los valores de los campos que
deseamos introducir. Con algún tipo de cursor es necesario también utilizar el método Requery para
poder acceder al registro recién creado.
Si se invoca el método AddNew mientras se está editando el registro actual, o durante otra operación
AddNew, ADO invoca automáticamente el método Update para guardar los cambios. Vea más adelante
los métodos Update y UpdateBatch.
Método Update
Guarda los cambios realizados en el registro actual de un objeto Recordset. Se utiliza tanto para
“rematar” una operación de creación de un registro iniciada con AddNew, como para guarda r los nuevos
datos del registro actual (Recuerde que en ADO no existe el método Edit, tal como ocurría en DAO)
.
Sintaxis
NombreDelRecordset.Update Fields , Values
LSB
Visual Basic – Guía del Estudiante
Capítulo 1
Página 419
En esta sintaxis, Fields y Values son opcionales, y solamente tienen aplicación cuando se trata de
cambiar los valores del registro actual, no de terminar una operación de creación de un nuevo registro
mediante AddNew.
Vuelvo a recomendar lo anterior. Para cambiar los valores de varios campos de un registro, nos
colocaremos sobre ese registro, y sin invocar ningún método, ejecutaremos este código
MiRecordset!Campo1 = Valor1
MiRecordset!Campo2 = Valor2
……….
MiRecordset!CampoN = ValorN
MiRecordset.Update
Pero en ADO pasa una cosa que no pasaba en DAO. Si cambiamos de registro una vez modificado el
valor de un registro, ADO invoca automáticamente el método Update. Por lo tanto, el código siguiente:
MiRecordset!Campo1 = Valor1
MiRecordset!Campo2 = Valor2
……….
MiRecordset!CampoN = ValorN
Tendrá el mismo resultado que el anterior cuando cambiemos de r
Descargar